Skip to content

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
mainfrom
feature/2026-08-20-a2a-discovery-compat
Open

feat: serve and resolve the canonical agent-card.json path, adopt A2A 0.3 kind discriminators with legacy compatibility#6
brainsparker wants to merge 1 commit into
mainfrom
feature/2026-08-20-a2a-discovery-compat

Conversation

@brainsparker

Copy link
Copy Markdown
Owner

What this does

Brings youagent A2A wire format up to spec 0.3.x and fixes agent card discovery interop in both directions:

  • Server: the agent card is now served at the canonical /.well-known/agent-card.json (A2A spec >= 0.3.0). The legacy /.well-known/agent.json and the /agent-card alias are kept for older clients, following the dual-path pattern the ecosystem converged on.
  • Client + registry: A2AClient.discover and RegistryClient.registerExternal now resolve remote cards through a shared fetchAgentCardJson helper: canonical path first, legacy fallback second, with a clear combined error when both fail.
  • Parts: message parts now use the spec kind discriminator (text / file / data) instead of type, which was never in the A2A spec at any version. Messages carry kind: "message", tasks carry kind: "task", and artifacts carry the required artifactId.
  • Compatibility: every ingest boundary (server message/send, client task responses) runs new normalizers (src/a2a/compat.ts) that accept legacy type-discriminated parts from pre-0.2 youagent peers, so nothing already deployed breaks.
  • Card defaults: protocolVersion default bumped 0.2.1 to 0.3.0; new preferredTransport (default JSONRPC) and additionalInterfaces card fields per 0.3.x.
  • Testability: A2AServer accepts port: 0 and exposes listeningPort.

Why this, why today (market rationale)

The A2A spec renamed the well-known card path from agent.json to agent-card.json in 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 its type part discriminator predates even that (the spec used kind from 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

  • New src/a2a/discovery.ts: canonical and legacy path constants plus fetchAgentCardJson (canonical first, legacy fallback, combined error). Shared by the A2A client, the registry client, and the server route.
  • New src/a2a/compat.ts: normalizePart, normalizeParts, normalizeMessage, normalizeArtifact, normalizeTask. Legacy type fields are stripped, kind wins when both are present, malformed parts fail loudly at the boundary.
  • registerExternal keeps its RegistryError contract (statusCode 0 when discovery exhausted both paths, since no single HTTP status applies).
  • README, example, and CHANGELOG updated to match. No new dependencies.

Test status

  • 3 new vitest suites following the repo convention of co-located tests: 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).
  • Sandbox note: the build environment could not reach the npm registry, so vitest and tsc could not run locally. The same coverage was verified against the real sources with a node:test mirror harness on Node 24: 14/14 passing, including a live client-to-server loop over HTTP and a full interop test against a simulated pre-0.3 legacy server (legacy card path, type parts, no artifactId). Please rely on CI for the vitest suite, typecheck, and build.

Built by Daily Feature Builder.

… with legacy fallback, kind part discriminators

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant