feat: serve and resolve the canonical agent-card.json path, adopt A2A 0.3 kind discriminators with legacy compatibility - #6
Open
brainsparker wants to merge 1 commit into
Conversation
… with legacy fallback, kind part discriminators Co-Authored-By: Claude Fable 5 <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.
What this does
Brings youagent A2A wire format up to spec 0.3.x and fixes agent card discovery interop in both directions:
/.well-known/agent-card.json(A2A spec >= 0.3.0). The legacy/.well-known/agent.jsonand the/agent-cardalias are kept for older clients, following the dual-path pattern the ecosystem converged on.A2AClient.discoverandRegistryClient.registerExternalnow resolve remote cards through a sharedfetchAgentCardJsonhelper: canonical path first, legacy fallback second, with a clear combined error when both fail.kinddiscriminator (text/file/data) instead oftype, which was never in the A2A spec at any version. Messages carrykind: "message", tasks carrykind: "task", and artifacts carry the requiredartifactId.message/send, client task responses) runs new normalizers (src/a2a/compat.ts) that accept legacytype-discriminated parts from pre-0.2 youagent peers, so nothing already deployed breaks.protocolVersiondefault bumped0.2.1to0.3.0; newpreferredTransport(defaultJSONRPC) andadditionalInterfacescard fields per 0.3.x.A2AServeracceptsport: 0and exposeslisteningPort.Why this, why today (market rationale)
The A2A spec renamed the well-known card path from
agent.jsontoagent-card.jsonin v0.3.0 (July 2025, breaking change): https://github.com/a2aproject/A2A/releases/tag/v0.3.0. youagent still speaks only the pre-0.3 path, and itstypepart discriminator predates even that (the spec usedkindfrom v0.1 on). The ecosystem has moved and it is actively breaking implementations that lag:Note on v1.0: the spec released 1.0 in spring 2026 with larger breaking changes (enum renames, supportedInterfaces restructuring, removal of kind discriminators in favor of member presence: https://a2a-protocol.org/latest/whats-new-v1/). Most deployed clients still speak 0.3.x wire format and the official SDKs ship explicit v0.3 compat layers, so solid 0.3.x compliance plus dual-path discovery is the highest-interop target for youagent today. A v1.0 migration is a good future PR once the ecosystem tilts.
Runner-up candidates considered today: publishing MCP-Profiles to the official MCP registry (mechanical win, registry still preview-labeled, weaker urgency), and PromptLens work (paused: PRs #44, #45, #46, and #47 are four overlapping compare implementations that should be triaged before that repo gets anything new).
Implementation notes
src/a2a/discovery.ts: canonical and legacy path constants plusfetchAgentCardJson(canonical first, legacy fallback, combined error). Shared by the A2A client, the registry client, and the server route.src/a2a/compat.ts:normalizePart,normalizeParts,normalizeMessage,normalizeArtifact,normalizeTask. Legacytypefields are stripped,kindwins when both are present, malformed parts fail loudly at the boundary.registerExternalkeeps itsRegistryErrorcontract (statusCode 0 when discovery exhausted both paths, since no single HTTP status applies).Test status
src/a2a/compat.test.ts,src/a2a/a2a-server.test.ts,src/a2a/a2a-client.test.ts(28 assertions across normalizers, dual-path serving, legacy ingest, discovery fallback, and wire shape).Built by Daily Feature Builder.