fix: A2A interop with real external agents (CLEAN-97) - #90
Merged
Merged
Conversation
A live run of 41 public A2A 1.0 agents from a2aregistry.org through the real import and delegation code showed the circuit works and interop does not: 40 imported, 6 answered with content. After this change the same run gives 36 answers with content; the remaining 4 are agents that require structured input, and they now say so. - Message replies. A blocking SendMessage may be answered with a Message instead of a Task; most public agents do exactly that. The client returns either, and delegation reads the answer from both. - Reply text. Every artifact part is read, not only the first artifact's text: data parts become compact JSON, links stay links, binary is named but not inlined. An empty artifact list falls back to the task's status message. Only when nothing anywhere is readable is the reply recorded as an explicit empty answer, and the tool tells the model not to invent one. - Interface choice. The first JSON-RPC interface on 1.0 is used, not the first interface listed, in import and delegation alike. A 1.0 card without JSON-RPC is refused at import with PEER_BINDING. - The card's own address. Import and external refresh now vet the chosen interface URL: SSRF-guarded, and refused when it points back into this installation. Rows saved before this fail delegation with PEER_ADDRESS_REFUSED or PEER_UNSUPPORTED instead of "it answered with an error". - Self-imports. "Is this our own agent" compares a normalized address (host case, trailing dot, port, decoded and collapsed path, scheme ignored) instead of a string prefix. Doubled slashes and %61gents no longer pass, and a card whose interface names our base is refused whatever host served it. - Honest causes. A 0.3 card reports its version instead of "not an agent card". A JSON-RPC error sent with a 4xx status passes the peer's reason on instead of "could not be reached". Redirects are still never followed, but are now reported with their target, so the operator knows what to paste. - Card URLs that already name a .json document are kept as they are, so /.well-known/agent.json and custom card paths are no longer mangled. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The card address line showed the first interface a card lists. The API now calls the first JSON-RPC interface on 1.0, so a card that prefers HTTP+JSON showed one address while delegations went to another. Both the card view and the A2A tab header use the same rule as the API now. The delegation feed also names the two new causes: a private interface address that was refused before anything was sent, and a card with no JSON-RPC interface. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 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.
Jira: CLEAN-97
External A2A agents mostly did not work with Ranch. The import and delegation circuit was fine; the interop was not. This fixes the four critical and three minor defects found by running real public agents through the real code, plus two more honesty gaps the same run surfaced.
Before and after
The same 41 public A2A 1.0 agents from a2aregistry.org, no auth, through the real
PeerService.previewByUrlandDelegationService.runwith production SSRF guards on:The 4 remaining failures are agents that demand structured input instead of text, and they now say exactly that. The five spellings of our own agent's URL that previously slipped past the self-import check on production are all refused now, before any request.
What changed
Critical
SendMessagemay return a Message instead of a Task; most public agents do. The client returns either and delegation reads both.PEER_ADDRESS_REFUSEDinstead of "it answered with an error".PEER_BINDING; an existing one fails withPEER_UNSUPPORTED.Minor
.jsondocument are kept as is, so/.well-known/agent.jsonand custom paths are no longer mangled.Found during verification, same class
redirect: 'manual'reports them with their target, so the operator knows which address to paste instead of seeing "fetch failed".Verification
a2a.types.spec.tstsc --noEmitnuxt typecheckagainst a freshly generated SDKNotes for review
prebuildandpretypecheckanyway.npx nuxt typecheckin admin against the committed SDK fails in the knowledge slice, because CLEAN-96 added theretryingstatus without regenerating the committed client.bun run typecheckregenerates first and passes.🤖 Generated with Claude Code