18 KiB
adr_number, title, status_history, tier, authors, superseded_by, related_adrs, acceptance
| adr_number | title | status_history | tier | authors | superseded_by | related_adrs | acceptance | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 47 | A2A Standard Adoption |
|
4 |
|
|
|
Context
ADR-026 established the agent communication protocol as the sole Presentation-Application boundary for all CleverAgents clients. That initial design used a bespoke JSON envelope format transported over a RESTful API (FastAPI/uvicorn, URL-path routing, HTTP verbs, SSE streaming). Since then, the Agent-to-Agent (A2A) Protocol has emerged as an open standard (a2a-protocol.org) under the Linux Foundation (Apache 2.0 license), with official SDKs in Python, Go, JavaScript, Java, and .NET. The external standard provides:
- A protocol-binding-agnostic operation model with JSON-RPC 2.0, gRPC, and REST bindings
- Agent Cards (
/.well-known/agent.json) for dynamic capability discovery - Standard operations for messaging (
message/send,message/stream), task lifecycle (tasks/get,tasks/list,tasks/cancel), push notifications, and agent discovery - A rich Task lifecycle model with states:
submitted,working,input-required,completed,failed,canceled,rejected - An extensibility mechanism for platform-specific operations (custom methods declared in Agent Card)
- SSE streaming for real-time task status and artifact updates
- Multi-language SDK support with production-quality transport implementations
Adopting this external standard eliminates our bespoke protocol, provides SDK-quality transport implementations, Agent Card-based discovery, and positions CleverAgents within the broader agent interoperability ecosystem.
Decision Drivers
- The existing bespoke protocol (custom envelope, REST routing, SSE streaming) requires ongoing maintenance and has no ecosystem adoption outside CleverAgents
- The A2A standard covers the core agent interaction lifecycle (messaging, task management, streaming, discovery) which maps directly to CleverAgents SessionWorkflow and plan execution
- Platform operations (plan lifecycle, registry CRUD, entity sync, namespace management) are cleanly handled by A2A's extensibility mechanism
- The A2A Python SDK provides production-quality JSON-RPC and HTTP transports, eliminating the need for our stub transport and custom serialization code
- Agent Card discovery enables third-party agents and clients to dynamically discover CleverAgents capabilities
- IDE plugins, CLI, TUI, and external clients all benefit from speaking a standardized protocol that third parties can implement against
- A2A's Linux Foundation governance and broad industry adoption (22k+ GitHub stars, 140+ contributors) provide long-term ecosystem stability
Decision
CleverAgents adopts the external Agent-to-Agent (A2A) Protocol standard (a2a-protocol.org) as the sole communication protocol for all client-server interaction. This replaces the bespoke REST+JSON envelope protocol defined in the original ADR-026. The protocol role of A2A — as the Presentation-Application boundary — is unchanged; only the wire format, transport, and method vocabulary change.
No REST API. All communication uses A2A via the JSON-RPC 2.0 protocol binding. Standard A2A operations handle agent interactions. A2A extension methods (_cleveragents/-prefixed) handle all platform operations.
Design
Protocol Architecture
A2A is the only protocol between any client and the CleverAgents backend. There are two categories of operations:
Standard A2A operations (defined by the external specification):
| Operation | Direction | Purpose |
|---|---|---|
message/send |
Client → Server | Send a message to the agent, receive a Task or direct response |
message/stream |
Client → Server | Send a message with SSE streaming of task updates |
tasks/get |
Client → Server | Retrieve current state of a task |
tasks/list |
Client → Server | List tasks with optional filtering |
tasks/cancel |
Client → Server | Cancel a running task |
tasks/subscribe |
Client → Server | Subscribe to task updates via SSE |
pushNotificationConfig/* |
Client → Server | Manage push notification webhooks |
getExtendedAgentCard |
Client → Server | Fetch authenticated Agent Card with full detail |
Standard A2A streaming events (server → client via SSE):
| Event | Emitted When |
|---|---|
TaskStatusUpdateEvent |
Task state changes (submitted → working → completed, etc.) |
TaskArtifactUpdateEvent |
Agent produces output (response chunks, plan entries, tool results) |
Multi-turn interactions (replacing protocol-level callbacks):
| Pattern | Purpose |
|---|---|
Task enters input-required state |
Human-in-the-loop approval (maps to automation profile gates) |
Client responds via message/send |
Provides requested input, file content, or approval |
_cleveragents/fs/* extensions |
Agent accesses files on client machine (handled locally by client) |
_cleveragents/terminal/* extensions |
Agent runs commands in sandbox on client machine |
CleverAgents extension methods (declared in Agent Card via A2A extension mechanism):
All platform operations use the _cleveragents/ namespace. See the specification's Server and Client Architecture section for the complete method catalog with parameters and response schemas.
Mapping to CleverAgents Concepts
| A2A Standard Concept | CleverAgents Concept |
|---|---|
message/send |
SessionWorkflow.tell() — user talks to orchestrator actor |
TaskStatusUpdateEvent (plan updates) |
Plan with entries (content, priority, status) — direct mapping |
TaskArtifactUpdateEvent (tool output) |
Tool invocations during plan execution |
Task input-required state |
Automation profile human-in-the-loop approval gates |
_cleveragents/fs/* extensions |
Agent accesses client-local project resources |
_cleveragents/terminal/* extensions |
Agent runs commands in sandbox on client machine |
| Agent Card skills | Advertised plan lifecycle, registry, context, sync capabilities |
| Agent Card security schemes | Authentication methods (OAuth2, API key, bearer token) |
Agent Discovery: Agent Card
A2A introduces Agent Cards — JSON metadata documents that describe an agent's capabilities, skills, security requirements, and supported protocol bindings. The CleverAgents Agent Card is served at /.well-known/agent.json in server mode and declares:
- Skills: Plan lifecycle management, registry CRUD, context assembly, entity sync, namespace management, diagnostics
- Extensions:
_cleveragents/methods with URIurn:cleveragents:extensions:v1 - Supported interfaces:
jsonrpc(primary) - Security schemes: OAuth2, API key, or HTTP bearer
An authenticated extended Agent Card with additional detail is available via the getExtendedAgentCard operation.
Transport Modes
The system supports three transport configurations:
Local mode — A2A JSON-RPC over stdio:
Client Process ──stdio──→ Agent Subprocess (A2A server)
│
├── A2aLocalFacade (platform ops resolved in-process)
└── Actor Graph (LangGraph, local execution)
The client spawns the agent as a subprocess. A2A JSON-RPC messages flow over stdin/stdout. Platform operations (registry, plan lifecycle, etc.) are handled by A2aLocalFacade which routes to in-process Application-layer services. No network, no serialization beyond JSON-RPC framing.
Server mode — A2A JSON-RPC over HTTP (CleverAgents server):
Client ──HTTP──→ CleverAgents A2A Server
│
├── Standard A2A operations → SessionWorkflow, Actor Graphs (via LangGraph Platform RemoteGraph)
└── Extension methods → PlanService, RegistryServices, SyncService, NamespaceService
The client connects to the CleverAgents server via the A2A SDK's HTTP transport. All communication — both agent interactions and platform operations — flows through the single A2A endpoint. The server delegates actor execution to LangGraph Platform via RemoteGraph.
Server mode — External A2A agent + CleverAgents server:
Client ──HTTP──→ External A2A Server (agent interactions)
──HTTP──→ CleverAgents A2A Server (extension methods only)
When an agent is hosted on an external A2A-compatible server, the client sends standard A2A operations to that server and _cleveragents/ extension methods to the CleverAgents server. This enables interoperability with any A2A-compliant agent.
Wire Format: JSON-RPC 2.0
All A2A messages use JSON-RPC 2.0 framing (A2A specification Section 9):
Request (message/send):
{
"jsonrpc": "2.0",
"id": 1,
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [{ "text": "Refactor the auth module to use dependency injection" }]
}
}
}
Response (Task created):
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "task_01HXRCF1...",
"status": { "state": "working" }
}
}
SSE streaming event:
{
"jsonrpc": "2.0",
"method": "message/stream",
"params": {
"id": "task_01HXRCF1...",
"status": { "state": "working" },
"artifacts": [{ "parts": [{ "text": "I'll start by extracting the authentication..." }] }]
}
}
Error response:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32001,
"message": "Plan not found",
"data": { "plan_id": "01HXRCF1..." }
}
}
Extension method request:
{
"jsonrpc": "2.0",
"id": 42,
"method": "_cleveragents/plan/status",
"params": { "plan_id": "01HXRCF1..." }
}
Error Code Mapping
A2A uses JSON-RPC 2.0 integer error codes (per A2A Section 9.5):
| Code | Meaning | Domain Exception(s) |
|---|---|---|
-32700 |
Parse error (malformed JSON) | — |
-32600 |
Invalid request | — |
-32601 |
Method not found | A2aOperationNotFoundError |
-32602 |
Invalid params | ValidationError |
-32603 |
Internal error | Any unhandled Exception |
-32001 |
Entity not found | ResourceNotFoundError |
-32002 |
Authentication required | AuthenticationError |
-32003 |
Authorization forbidden | AuthorizationError |
-32004 |
Invalid state | BusinessRuleViolation |
-32005 |
Already exists | DuplicateEntityError |
-32006 |
Budget exceeded | BudgetExceededError |
-32007 |
Version mismatch | A2aVersionMismatchError |
-32008 |
Plan error | PlanError |
Application-specific error codes use the range -32001 to -32099 per JSON-RPC 2.0 convention.
Authentication
Authentication uses standard HTTP security schemes declared in the Agent Card:
- Client discovers the Agent Card at
/.well-known/agent.json - Agent Card's
securitySchemesfield declares supported auth mechanisms (OAuth2, API key, HTTP bearer) - Client authenticates using the declared mechanism (e.g.,
Authorization: Bearer <token>header) - All subsequent requests include the authentication credentials
For HTTP transport, the A2A-Version header communicates the protocol version.
Local mode (stdio transport) bypasses authentication entirely — the agent subprocess runs with the user's local permissions.
Versioning
- The JSON-RPC protocol version is always
"2.0"in thejsonrpcfield - A2A protocol version is communicated via the
A2A-VersionHTTP header - CleverAgents extension version is declared in the Agent Card's
extensionsfield underurn:cleveragents:extensions:v1 - Backward compatibility: servers support current extension version plus one prior minor version
- Breaking changes to extension methods require a major version bump of the
_cleveragentsextension namespace
Client-Side Architecture
The client uses an A2aClient wrapping the A2A Python SDK:
| Component | Role | Notes |
|---|---|---|
A2aLocalFacade |
Extension method dispatch | Routes _cleveragents/ methods to in-process Application-layer services in local mode |
| A2A SDK HTTP transport | Server mode transport | Production HTTP transport with SSE streaming |
| A2A SDK JSON-RPC types | Wire format types | SendMessageRequest, Task, Message, Part, TaskStatusUpdateEvent, etc. |
A2aEventQueue |
Local mode event delivery | In-process delivery of task update events |
| Agent Card | Discovery | Describes capabilities, skills, extensions, and security schemes |
Constraints
- All client-server communication must use A2A. No REST endpoints, no ad-hoc HTTP calls, no separate API surfaces.
- Standard A2A operations must not be modified or extended — use
_cleveragents/extension methods for platform-specific operations. - Extension method names must follow the
_cleveragents/{domain}/{operation}naming convention. - Clients must gracefully handle servers that do not advertise
_cleveragentscapabilities (indicating a non-CleverAgents A2A server).
Consequences
Positive
- Eliminates the bespoke REST protocol, reducing maintenance burden and protocol-specific code
- Aligns with the A2A interoperability ecosystem — any A2A-compatible client or agent can interact with CleverAgents
- Agent Card discovery enables dynamic capability advertisement and third-party integration
- The A2A Python SDK provides production-quality transports with proper connection lifecycle management
- JSON-RPC 2.0 is a mature, well-tooled standard with broad language support; gRPC and REST bindings are available for future adoption
- IDE plugins benefit from a standard protocol that editor developers may already support
- The extensibility mechanism cleanly separates standard agent operations from platform-specific operations
- Linux Foundation governance and multi-language SDK support provide long-term ecosystem stability
Negative
- Adopting the standard requires updating all existing protocol source code and tests
- JSON-RPC 2.0's error code scheme (integers) is less self-documenting than string-based codes (e.g.,
NOT_FOUNDvs-32001)
Risks
- The extension method namespace (
_cleveragents/) could collide with other implementations. Mitigation: the_cleveragentsprefix is unique and registered.
Alternatives Considered
Keep the bespoke REST protocol — Functional but isolated. No ecosystem interoperability, ongoing maintenance of custom envelope format, and no path to IDE-native agent protocol support. Rejected.
Adopt standard for agent conversations only, keep REST for platform operations — Simpler initial approach but creates two protocol surfaces, complicating client implementation and authentication. The A2A extensibility mechanism makes this unnecessary. Rejected.
ACP (Agent Client Protocol) — The predecessor to A2A. Also built on JSON-RPC 2.0, but lacked Agent Card discovery, had a smaller single-language SDK ecosystem, and is now deprecated. The ecosystem (including ACP's originating platform) has converged on A2A. Rejected in favor of A2A.
gRPC for platform operations — Strong typing and streaming but adds code generation dependency, a second protocol surface, and is harder to debug. A2A includes a gRPC binding (Section 10) that can be adopted later if needed. Rejected as the primary binding.
Compliance
- Protocol conformance tests: Validate all standard A2A operation signatures and response schemas against the A2A specification test suite.
- Extension method tests: Validate all
_cleveragents/methods against documented parameter and response schemas. - Transport parity tests: Execute the same test suite over stdio transport (local mode) and HTTP transport (server mode), asserting identical results.
- SDK integration tests: Verify A2A Python SDK transport works correctly for both transport modes.
- Agent Card tests: Validate the generated Agent Card conforms to the A2A specification schema.
- Discovery tests: Verify
/.well-known/agent.jsonis served correctly andgetExtendedAgentCardreturns authenticated detail. - Bypass detection: Architecture tests verify no Presentation-layer module bypasses A2A to access Domain or Infrastructure services.