Repository navigation
fix(a2a): agents reach their own staging over loopback - #98
Merged
Merged
Conversation
A staged grant names a path on the agent's own public URL, and a sandbox can't always call that URL: on one provider the in-sandbox route to the sandbox's public hostname serves a certificate that doesn't verify there, so every staged transfer failed. Core's staged grants now also carry an AgentEnv-Staging-Path header, the path the agent's own server serves the URL at. The protocol's transfer helpers send such a request to http://127.0.0.1:$A2A_PORT<path> first, and to the grant's URL only when nothing listens there; transfers.loopback_url gives the same URL to agents with transfer code of their own. Agents and cores on either side of the change still work together: a grant without the header, or a helper that ignores it, uses the grant's URL. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e request on A2A_PORT reaches an agent's server only when whatever starts it sets it: agent-env does for an agent it deploys from an image, but an installed agent's own install commands start it. The SDK's server now serves each request serving_on the port its socket took it on, and loopback_url prefers that port, so an SDK agent reaches its staging over loopback however it was started. A2A_PORT stays the port for transfers made outside a request, as from a hook process. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When the object store's grants can't reach an agent, agent-env stages the agent's objects on the agent's own server and hands it grants that name paths on the agent's public URL. A sandbox can't always call its own public URL. On one provider, the in-sandbox route to the sandbox's public hostname serves a certificate that doesn't verify there, so every staged transfer failed with
transfer_unavailable, including the solver's and the judge's trajectories.The change
a2a_agent/staging.py): each staged grant (read, write and upload policy) also carries anAgentEnv-Staging-Pathheader. Its value is the path at which the agent's own server serves the URL (/ext/staging/<id>/<n>), taken from the card's staging endpoint.transfers.py,a2a_agent/framework.py):upload,downloadandNamespaceUploadersend such a request tohttp://127.0.0.1:{port}<path>first, and use the grant's URL only when nothing listens there.transfers.serving_on.A2A_PORT. agent-env sets it on agents it deploys from an image, and it also covers a separate process, such as a hook.transfers.loopback_url(url, headers)returns the same URL for agents with transfer code of their own.Loopback reaches the agent's server, not its staging directory. So it works from any process in the sandbox, and the server remains the only owner of its staging: byte counts,
If-Matchand atomic commits are unchanged.Compatibility
There are no wire-model or card changes.
Not covered
loopback_url.Verification
tst/unit, protocol tests)staging_test.py: every staging flow (skill bundle, trajectory, snapshot save and load, changelog upload, drain and apply), run a second time in a sandbox that refuses the agent's calls to its own public URLA2A_PORT. An agent that doesn't use loopback fails the same calls with the new hint.A2A_PORTnames another.A2A_PORTstages a 64 MiB in-request upload. A separate process reaches it throughA2A_PORTfor namespace POSTs and a download. A closed loopback port falls back to the grant URL and fails cleanly in 2 s. 1 GiB moves at about 250 MiB/s with 92 MiB client RSS. 32 concurrent uploads and 32 downloads all arrive intact. A full staging (413) is final, with no fallback. A server SIGKILLed mid-upload fails the transfer 2 s later instead of hanging, and a restarted server is reached again.http://127.0.0.1:8000and the server records the request from127.0.0.1, while agent-env's calls arrive through the ingress. Run alongside them, an agent on the released protocol still fails at the solver's trajectory, now with the new hint.🤖 Generated with Claude Code
The PR appears safe to merge; the previously reported installed-agent failure is fixed.
What we checked:
A2A_PORT.Summary
SDK agents can now reach their own staged objects over loopback, rather than relying on calls to their public hostname. The grant URL remains a fallback when no server accepts the loopback connection.
Diagram
sequenceDiagram participant Env as AgentEnv participant Agent as Agent SDK participant Stage as Local staging Env->>Agent: Send grant with staging path Agent->>Agent: Read current request port Agent->>Stage: Transfer over loopback Stage-->>Agent: Return staged objectReviews (2) · Last reviewed commit: "fix(a2a): the SDK's server reaches its s..." · Reviewed by Greptile