feat(a2a): spec-compliant A2A v0.3 implementation#1
Merged
Conversation
Rewrites the A2A module to align with the Agent2Agent v0.3 specification. Server: - JSON-RPC 2.0 dispatch on single endpoint (replaces REST-style URL routing) - Agent card at /.well-known/agent-card.json (with legacy path fallback) - All spec methods: message/send, message/stream, tasks/get, tasks/cancel, tasks/resubscribe, push notification config CRUD, getAuthenticatedExtendedCard - SSE streaming with heartbeat and subscriber management - Authentication middleware support - contextFactory for wiring real AgentContext into task execution - Push notifications with Bearer/Basic auth - Multi-turn via input-required state and task resume - Proper JSON-RPC error codes (1001-1009) - CORS support Client: - Agent card discovery with canonical + legacy path fallback - Polling and SSE streaming execution modes - Multi-turn with onInputRequired callback - Bearer and API key authentication - cancelA2ATask helper - onStreamEvent callback for streaming updates Types: - Full spec-compliant type definitions in dedicated types.ts - AgentCard with kind, protocolVersion, provider, securitySchemes, security - All Part types: TextPart, FilePart (bytes + uri), DataPart - All task states: submitted, working, input-required, auth-required, completed, failed, canceled, rejected - Artifact schema with id, name, description, parts, metadata - contextId for conversation grouping - A2A error codes enum Agent Card: - ToAgentCardOptions for provider, security, streaming, push notifications - Spec-compliant card generation with all optional fields Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix resource leak in client SSE streaming: rewrite recursive .then() chain as async while loop with reader.cancel() in finally block (#2, #5) - Add timeout enforcement in server executeTask via Promise.race using agent.timeoutMs (default 5min), prevents tasks hanging forever (#3) - Add skillId-based agent resolution: when MessageSendParams includes skillId, server matches against agent capabilities; returns UNSUPPORTED_SKILL (1004) error if no match (#4) - Add test for multi-agent skill routing (correct dispatch + error case) Co-Authored-By: Claude Opus 4.6 (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.
Summary
Rewrites the A2A module to fully comply with the Agent2Agent v0.3 specification. The previous implementation was a functional skeleton with REST-style routing, missing methods, incomplete types, and no auth — this brings it to spec.
What changed
Server (
src/a2a/server.ts)/.well-known/agent-card.json(spec-correct path, with legacy fallback)message/send,message/stream(SSE),tasks/get,tasks/cancel,tasks/resubscribe, push notification config CRUD,agent/getAuthenticatedExtendedCardauthenticatecallbackcontextFactoryoption for wiring realAgentContextinto task executioninput-requiredstate + task resumeClient (
src/a2a/client.ts)onInputRequiredcallbackcancelA2ATask()helperonStreamEventcallback for real-time streaming updatesTypes (
src/a2a/types.ts— new file)AgentCardwithkind,protocolVersion,provider,securitySchemes,securityTextPart,FilePart(bytes + uri variants),DataPartauth-requiredandrejectedA2AArtifactschema withid,name,description,parts,metadatacontextIdfor conversation session groupingA2AErrorCodesenumAgent Card (
src/a2a/agent-card.ts)ToAgentCardOptionsfor configuring provider info, security schemes, streaming, push notificationsIssues addressed
agent.json→agent-card.json)POST /endpoint, method-based dispatchtasks/cancelmessage/stream)tasks/resubscribetasks/pushNotificationConfig/*id,name,description,parts,metadatakind,protocolVersion,provider,securitySchemes,securityinput-requiredstate + task resume viamessage/sendwithtaskIdcontextIdFilePartsupportTextPart,FilePart(bytes/uri),DataPartall typedAgentContextin servercontextFactoryconfig option for real agent wiringauth-required,rejectedagent/getAuthenticatedExtendedCardmethodTest plan
message/sendvia JSON-RPCtasks/getwith artifact verificationtasks/cancel+ not-cancelable errorcontextIdpropagation🤖 Generated with Claude Code