agentenv-framework-protocol 0.1.276__tar.gz → 0.1.278__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/PKG-INFO +14 -1
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/README.md +13 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/pyproject.toml +1 -1
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/a2a_agent/__init__.py +4 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/a2a_agent/extensions.py +21 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_a2a_agent.py +82 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/.gitignore +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/LICENSE +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/NOTICE +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/THIRD_PARTY_NOTICES.md +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/examples/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/examples/advanced_agent.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/examples/basic_agent.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/examples/custom_extensions_agent.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/examples/multimodal_agent.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/examples/reference_model.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/examples/streaming_agent.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/a2a_agent/_triggers.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/a2a_agent/framework.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/a2a_agent/registry.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/a2a_agent/tasks/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/a2a_agent/tasks/v1.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/agent_env_environment.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/client.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/manifest.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/preflight.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/transfers.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/src/agentenv_protocol/types.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_a2a_agent_examples.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_a2a_object_transfers.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_agent_env_environment.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_client.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_intake.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_manifest.py +0 -0
- {agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_preflight.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agentenv-framework-protocol
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.278
|
|
4
4
|
Summary: Open data-plane protocol and server SDK for agent environments.
|
|
5
5
|
Project-URL: Homepage, https://www.agentenvframework.com
|
|
6
6
|
Project-URL: Documentation, https://www.agentenvframework.com/docs
|
|
@@ -503,6 +503,19 @@ tools with (agent-env relays the env card's name: the MultiEnv's declared name,
|
|
|
503
503
|
`env` + 4 random digits, giving e.g. `mcp__env4821__<tool>`); when absent the agent mints
|
|
504
504
|
`mcp_<8 hex>`.
|
|
505
505
|
|
|
506
|
+
`ATTRIBUTION_PROBE_V1.probe` lets a caller check that an agent forwards attribution
|
|
507
|
+
upstream. Attribution is an open map of string dimensions, like AgentEnv's cost
|
|
508
|
+
attribution: the SDK assigns no keys, and each deployment uses whatever dimensions
|
|
509
|
+
its model gateway understands (the AgentEnv control plane configures `project_id`
|
|
510
|
+
and `task_id` on agents that declare those config fields). An agent records the
|
|
511
|
+
dimensions it last sent with a model request and returns them from a bodyless
|
|
512
|
+
`POST /ext/attribution-probe` as an `AttributionProbeResponse`:
|
|
513
|
+
`{"last_seen_attribution": {<dimension>: <value>, ...}, "last_seen_at_utc": ...}`.
|
|
514
|
+
The SDK does not record attribution itself, because only the agent knows what it sent.
|
|
515
|
+
The answer is agent-wide rather than per caller, and like every extension route the
|
|
516
|
+
probe carries no access check of its own, so expose an agent only to the control plane
|
|
517
|
+
that drives it.
|
|
518
|
+
|
|
506
519
|
Runnable, self-contained reference agents live in [`examples/`](https://github.com/scaleapi/agentenv-framework/tree/main/packages/agentenv-protocol/examples):
|
|
507
520
|
the normal, streaming, and multimodal `run(request)` paths, single- and
|
|
508
521
|
multi-operation custom extensions, and advanced ASGI-lifespan plus
|
|
@@ -474,6 +474,19 @@ tools with (agent-env relays the env card's name: the MultiEnv's declared name,
|
|
|
474
474
|
`env` + 4 random digits, giving e.g. `mcp__env4821__<tool>`); when absent the agent mints
|
|
475
475
|
`mcp_<8 hex>`.
|
|
476
476
|
|
|
477
|
+
`ATTRIBUTION_PROBE_V1.probe` lets a caller check that an agent forwards attribution
|
|
478
|
+
upstream. Attribution is an open map of string dimensions, like AgentEnv's cost
|
|
479
|
+
attribution: the SDK assigns no keys, and each deployment uses whatever dimensions
|
|
480
|
+
its model gateway understands (the AgentEnv control plane configures `project_id`
|
|
481
|
+
and `task_id` on agents that declare those config fields). An agent records the
|
|
482
|
+
dimensions it last sent with a model request and returns them from a bodyless
|
|
483
|
+
`POST /ext/attribution-probe` as an `AttributionProbeResponse`:
|
|
484
|
+
`{"last_seen_attribution": {<dimension>: <value>, ...}, "last_seen_at_utc": ...}`.
|
|
485
|
+
The SDK does not record attribution itself, because only the agent knows what it sent.
|
|
486
|
+
The answer is agent-wide rather than per caller, and like every extension route the
|
|
487
|
+
probe carries no access check of its own, so expose an agent only to the control plane
|
|
488
|
+
that drives it.
|
|
489
|
+
|
|
477
490
|
Runnable, self-contained reference agents live in [`examples/`](https://github.com/scaleapi/agentenv-framework/tree/main/packages/agentenv-protocol/examples):
|
|
478
491
|
the normal, streaming, and multimodal `run(request)` paths, single- and
|
|
479
492
|
multi-operation custom extensions, and advanced ASGI-lifespan plus
|
|
@@ -4,6 +4,7 @@ from a2a.types import AgentCapabilities
|
|
|
4
4
|
|
|
5
5
|
from .extensions import (
|
|
6
6
|
AGENT_CONFIG_V1,
|
|
7
|
+
ATTRIBUTION_PROBE_V1,
|
|
7
8
|
INSTALL_V1,
|
|
8
9
|
MCP_CONFIG_V1,
|
|
9
10
|
PEER_AGENTS_V1,
|
|
@@ -12,6 +13,7 @@ from .extensions import (
|
|
|
12
13
|
STANDARD_EXTENSIONS,
|
|
13
14
|
TRAJECTORY_V1,
|
|
14
15
|
TRIGGERS_V1,
|
|
16
|
+
AttributionProbeResponse,
|
|
15
17
|
BundleSkillRequest,
|
|
16
18
|
ChangelogIncrement,
|
|
17
19
|
ContextObjectTrajectoryRequest,
|
|
@@ -108,6 +110,7 @@ from ..transfers import (
|
|
|
108
110
|
|
|
109
111
|
__all__ = [
|
|
110
112
|
"AGENT_CONFIG_V1",
|
|
113
|
+
"ATTRIBUTION_PROBE_V1",
|
|
111
114
|
"INSTALL_V1",
|
|
112
115
|
"MCP_CONFIG_V1",
|
|
113
116
|
"PEER_AGENTS_V1",
|
|
@@ -122,6 +125,7 @@ __all__ = [
|
|
|
122
125
|
"AgentEnvAgent",
|
|
123
126
|
"AgentIdentity",
|
|
124
127
|
"AgentRunResult",
|
|
128
|
+
"AttributionProbeResponse",
|
|
125
129
|
"BundleSkillRequest",
|
|
126
130
|
"ChangelogIncrement",
|
|
127
131
|
"ContextObjectTrajectoryRequest",
|
|
@@ -231,6 +231,11 @@ class PeerAgentsSetRequest(ExtensionRequest):
|
|
|
231
231
|
peers: list[PeerAgent]
|
|
232
232
|
|
|
233
233
|
|
|
234
|
+
class AttributionProbeResponse(ExtensionResponse):
|
|
235
|
+
last_seen_attribution: dict[str, str]
|
|
236
|
+
last_seen_at_utc: str | None = None
|
|
237
|
+
|
|
238
|
+
|
|
234
239
|
class TriggerRegisterRequest(ExtensionRequest):
|
|
235
240
|
triggers: list[dict[str, Any]]
|
|
236
241
|
|
|
@@ -1037,6 +1042,21 @@ PEER_AGENTS_V1 = ExtensionDefinition(
|
|
|
1037
1042
|
},
|
|
1038
1043
|
)
|
|
1039
1044
|
|
|
1045
|
+
ATTRIBUTION_PROBE_V1 = ExtensionDefinition(
|
|
1046
|
+
uri="urn:agentenv:attribution-probe/v1",
|
|
1047
|
+
description="Report the attribution dimensions last sent with a model request.",
|
|
1048
|
+
endpoint="/ext/attribution-probe",
|
|
1049
|
+
core_operations={
|
|
1050
|
+
"probe": _op(
|
|
1051
|
+
"probe",
|
|
1052
|
+
"POST",
|
|
1053
|
+
"/ext/attribution-probe",
|
|
1054
|
+
RUNTIME,
|
|
1055
|
+
response_model=AttributionProbeResponse,
|
|
1056
|
+
),
|
|
1057
|
+
},
|
|
1058
|
+
)
|
|
1059
|
+
|
|
1040
1060
|
TRIGGERS_V1 = ExtensionDefinition(
|
|
1041
1061
|
uri="urn:agentenv:triggers/v1",
|
|
1042
1062
|
description="Register triggers and decide deterministic responses.",
|
|
@@ -1084,6 +1104,7 @@ STANDARD_EXTENSIONS: Mapping[str, ExtensionDefinition] = MappingProxyType(
|
|
|
1084
1104
|
TRAJECTORY_V1,
|
|
1085
1105
|
SNAPSHOT_V1,
|
|
1086
1106
|
PEER_AGENTS_V1,
|
|
1107
|
+
ATTRIBUTION_PROBE_V1,
|
|
1087
1108
|
TRIGGERS_V1,
|
|
1088
1109
|
INSTALL_V1,
|
|
1089
1110
|
)
|
{agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_a2a_agent.py
RENAMED
|
@@ -30,6 +30,7 @@ from a2a.types import (
|
|
|
30
30
|
)
|
|
31
31
|
from agentenv_protocol.a2a_agent import (
|
|
32
32
|
AGENT_CONFIG_V1,
|
|
33
|
+
ATTRIBUTION_PROBE_V1,
|
|
33
34
|
MCP_CONFIG_V1,
|
|
34
35
|
PEER_AGENTS_V1,
|
|
35
36
|
SKILL_CONFIG_V1,
|
|
@@ -40,6 +41,7 @@ from agentenv_protocol.a2a_agent import (
|
|
|
40
41
|
AgentConfig,
|
|
41
42
|
AgentEnvAgent,
|
|
42
43
|
AgentIdentity,
|
|
44
|
+
AttributionProbeResponse,
|
|
43
45
|
BundleSkillRequest,
|
|
44
46
|
ContextObjectTrajectoryRequest,
|
|
45
47
|
ContextTrajectoryRequest,
|
|
@@ -1348,6 +1350,86 @@ def test_handler_receives_the_canonical_request_model() -> None:
|
|
|
1348
1350
|
}
|
|
1349
1351
|
|
|
1350
1352
|
|
|
1353
|
+
def test_attribution_probe_reports_what_the_agent_last_sent() -> None:
|
|
1354
|
+
@a2a_agent(
|
|
1355
|
+
identity=AgentIdentity(name="attributing-agent", description="test", version="1")
|
|
1356
|
+
)
|
|
1357
|
+
class Agent(AgentEnvAgent):
|
|
1358
|
+
def __init__(self) -> None:
|
|
1359
|
+
self.sent: dict[str, str] = {}
|
|
1360
|
+
|
|
1361
|
+
async def run(self, request: TaskRequest) -> TaskResult:
|
|
1362
|
+
self.sent = {"project_id": "project-1", "task_id": "task-1", "team": "evals"}
|
|
1363
|
+
return TaskResult.text("ok")
|
|
1364
|
+
|
|
1365
|
+
@extension(ATTRIBUTION_PROBE_V1.probe)
|
|
1366
|
+
async def probe(self):
|
|
1367
|
+
return AttributionProbeResponse(
|
|
1368
|
+
last_seen_attribution=self.sent, last_seen_at_utc="2026-01-01T00:00:00Z"
|
|
1369
|
+
)
|
|
1370
|
+
|
|
1371
|
+
agent = Agent()
|
|
1372
|
+
with TestClient(agent.create_app()) as client:
|
|
1373
|
+
card = client.get("/.well-known/agent.json").json()
|
|
1374
|
+
assert _extension(card, ATTRIBUTION_PROBE_V1.uri)["params"]["endpoint"] == (
|
|
1375
|
+
"/ext/attribution-probe"
|
|
1376
|
+
)
|
|
1377
|
+
assert _operation(client, card, ATTRIBUTION_PROBE_V1.uri, "probe", {}).json() == {
|
|
1378
|
+
"last_seen_attribution": {},
|
|
1379
|
+
"last_seen_at_utc": "2026-01-01T00:00:00Z",
|
|
1380
|
+
}
|
|
1381
|
+
response = client.post("/a2a", json=_message_request())
|
|
1382
|
+
assert response.json()["result"]["status"]["state"] == "completed"
|
|
1383
|
+
assert _operation(client, card, ATTRIBUTION_PROBE_V1.uri, "probe", {}).json() == {
|
|
1384
|
+
"last_seen_attribution": {
|
|
1385
|
+
"project_id": "project-1",
|
|
1386
|
+
"task_id": "task-1",
|
|
1387
|
+
"team": "evals",
|
|
1388
|
+
},
|
|
1389
|
+
"last_seen_at_utc": "2026-01-01T00:00:00Z",
|
|
1390
|
+
}
|
|
1391
|
+
assert (
|
|
1392
|
+
_operation(
|
|
1393
|
+
client, card, ATTRIBUTION_PROBE_V1.uri, "probe", {"project_id": "x"}
|
|
1394
|
+
).status_code
|
|
1395
|
+
== 400
|
|
1396
|
+
)
|
|
1397
|
+
|
|
1398
|
+
|
|
1399
|
+
def test_attribution_probe_rejects_an_undeclared_response_field() -> None:
|
|
1400
|
+
@a2a_agent(
|
|
1401
|
+
identity=AgentIdentity(name="attributing-agent", description="test", version="1")
|
|
1402
|
+
)
|
|
1403
|
+
class Agent(AgentEnvAgent):
|
|
1404
|
+
async def run(self, request: TaskRequest) -> TaskResult:
|
|
1405
|
+
return TaskResult.text("ok")
|
|
1406
|
+
|
|
1407
|
+
@extension(ATTRIBUTION_PROBE_V1.probe)
|
|
1408
|
+
async def probe(self):
|
|
1409
|
+
return {"last_seen_attribution": {}, "headers": {"x-secret": "value"}}
|
|
1410
|
+
|
|
1411
|
+
with TestClient(Agent().create_app(), raise_server_exceptions=False) as client:
|
|
1412
|
+
card = client.get("/.well-known/agent.json").json()
|
|
1413
|
+
response = _operation(client, card, ATTRIBUTION_PROBE_V1.uri, "probe", {})
|
|
1414
|
+
assert response.status_code == 500
|
|
1415
|
+
assert "x-secret" not in response.text
|
|
1416
|
+
|
|
1417
|
+
|
|
1418
|
+
def test_attribution_probe_is_only_declared_by_a_handler() -> None:
|
|
1419
|
+
@a2a_agent(
|
|
1420
|
+
identity=AgentIdentity(name="plain-agent", description="test", version="1")
|
|
1421
|
+
)
|
|
1422
|
+
class Agent(AgentEnvAgent):
|
|
1423
|
+
async def run(self, request: TaskRequest) -> TaskResult:
|
|
1424
|
+
return TaskResult.text("ok")
|
|
1425
|
+
|
|
1426
|
+
with TestClient(Agent().create_app()) as client:
|
|
1427
|
+
card = client.get("/.well-known/agent.json").json()
|
|
1428
|
+
uris = {item["uri"] for item in card["capabilities"]["extensions"]}
|
|
1429
|
+
assert ATTRIBUTION_PROBE_V1.uri not in uris
|
|
1430
|
+
assert client.post("/ext/attribution-probe", json={}).status_code in (404, 405)
|
|
1431
|
+
|
|
1432
|
+
|
|
1351
1433
|
def test_handler_advertises_the_canonical_request_model() -> None:
|
|
1352
1434
|
class Agent:
|
|
1353
1435
|
@extension(SNAPSHOT_V1.save)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/THIRD_PARTY_NOTICES.md
RENAMED
|
File without changes
|
{agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/examples/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/examples/basic_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_client.py
RENAMED
|
File without changes
|
{agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_intake.py
RENAMED
|
File without changes
|
{agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_manifest.py
RENAMED
|
File without changes
|
{agentenv_framework_protocol-0.1.276 → agentenv_framework_protocol-0.1.278}/tests/test_preflight.py
RENAMED
|
File without changes
|