17 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 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 26 | Agent-to-Agent Protocol (A2A) |
|
4 |
|
null |
|
|
Context
CleverAgents is accessed through multiple presentation-layer clients — CLI, TUI, and an IDE plugin — and can operate in both local (single-process) and server (multi-user) modes. Without a shared, versioned contract between clients and the backend, each client would require bespoke integration code that drifts from the core domain model, making interoperability fragile and third-party client development impractical. The architecture needs a single protocol surface that all clients rely on regardless of deployment mode.
Decision Drivers
- Multiple presentation-layer clients (CLI, TUI, IDE plugin) must share a single, versioned contract to avoid bespoke integration code that drifts from the core domain model
- Local (in-process) and server (remote) deployment modes must expose identical operational semantics to all clients
- Third-party client development must be practical without knowledge of internal domain or infrastructure services
- Long-running operations (plan execution, tool invocations) require real-time streaming with causal ordering guarantees
- The protocol must support backward-compatible evolution so existing clients are not broken by new features
- Alignment with the emerging agent interoperability ecosystem is preferred over a bespoke protocol
Decision
CleverAgents adopts the Agent-to-Agent (A2A) Protocol — the open standard from a2a-protocol.org — as the sole communication protocol for all client-to-backend interaction. A2A is built on JSON-RPC 2.0 (with additional gRPC and REST bindings available) and provides standard operations for agent communication plus an extensibility mechanism for platform-specific operations. In local mode A2A flows over stdio via the JSON-RPC binding (agent as subprocess); in server mode over HTTP.
Design
Architectural Role
A2A defines the fundamental boundary between the Presentation and Application layers in the CleverAgents layered architecture (ADR-001). Every arrow from a Presentation-layer component (CLI, TUI, IDE plugin, A2A server endpoint) to the Application-layer Service Facade represents an A2A operation. No Presentation-layer module is permitted to bypass A2A and access Domain or Infrastructure services directly.
This boundary role makes A2A the single most architecturally significant protocol in the system — MCP and Agent Skills plug into the Infrastructure and Domain layers respectively, LSP provides actor-attached language intelligence in the Infrastructure layer (see ADR-027), but A2A is the protocol surface through which every client operation flows.
Agent Discovery: Agent Card
A2A introduces Agent Cards — JSON metadata documents served at /.well-known/agent.json — that describe an agent's identity, capabilities, skills, supported protocol bindings, authentication requirements, and extensions. The CleverAgents Agent Card declares:
- Skills: Plan lifecycle, registry CRUD, context management, entity sync, namespace management, diagnostics
- Extensions:
_cleveragents/platform-specific methods (declared via the A2A extension mechanism with URIurn:cleveragents:extensions:v1) - Supported interfaces:
jsonrpc(primary), optionallyrest - Security schemes: OAuth2, API key, or HTTP bearer — published in the Agent Card so clients can authenticate without protocol-level handshakes
In server mode, the Agent Card is served at the well-known URI. An authenticated extended Agent Card with additional detail is available via the getExtendedAgentCard operation. In local mode, the Agent Card is provided during initialization.
Protocol Scope
A2A communication is organized into two categories:
Standard A2A operations (defined by the external specification) handle the core agent interaction lifecycle:
| Operation Category | Operations | Service(s) |
|---|---|---|
| Messaging | message/send, message/stream |
SessionWorkflow, PlanService |
| Task lifecycle | tasks/get, tasks/list, tasks/cancel |
TaskService |
| Task subscriptions | tasks/subscribe |
TaskService, event delivery |
| Push notifications | pushNotificationConfig/create, get, list, delete |
Notification service |
| Discovery | getExtendedAgentCard |
Agent Card service |
CleverAgents extension methods (_cleveragents/-prefixed per the A2A extensibility mechanism) handle platform operations:
| Extension Group | Methods | Service(s) |
|---|---|---|
| Plan lifecycle | _cleveragents/plan/use, execute, apply, cancel, status, tree, explain, correct, diff, artifacts, prompt, rollback, list |
PlanService, PlanLifecycle, CorrectionFlow |
| Registries | _cleveragents/registry/{entity}/list, show, add, update, remove |
ActorService, ToolService, SkillService, ResourceService, ProjectService |
| Context | _cleveragents/context/show, inspect, simulate, set |
ContextService |
| Sync | _cleveragents/sync/pull, push, status |
SyncService |
| Namespace | _cleveragents/namespace/list, show, members |
NamespaceService |
| Health | _cleveragents/health/check, _cleveragents/diagnostics/run |
Health/diagnostic services |
Every CLI command maps to an A2A operation. When a user runs agents plan status <ID>, the CLI sends a _cleveragents/plan/status JSON-RPC request through the active transport and renders the response.
Wire Format: JSON-RPC 2.0
The primary A2A protocol binding uses JSON-RPC 2.0 (A2A specification Section 9):
Request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "_cleveragents/plan/status",
"params": { "plan_id": "01HXRCF1..." }
}
Successful response:
{
"jsonrpc": "2.0",
"id": 1,
"result": { "plan_id": "01HXRCF1...", "phase": "execute", "state": "running" }
}
Error response:
{
"jsonrpc": "2.0",
"id": 1,
"error": { "code": -32001, "message": "Plan not found", "data": { "plan_id": "01HXRCF1..." } }
}
Transport Modes
A2A is transport-agnostic at the specification level, defining abstract operations with multiple protocol bindings. CleverAgents uses the JSON-RPC binding (A2A Section 9) with two transports:
Local Mode — A2A JSON-RPC over stdio
CLI ──stdio──→ Agent Subprocess ──→ A2aLocalFacade ──→ ServiceFacade.method()
The client spawns the agent as a subprocess. JSON-RPC messages flow over stdin/stdout. Extension methods are intercepted by A2aLocalFacade and routed to in-process Application-layer services. No network, no authentication.
Server Mode — A2A JSON-RPC over HTTP
CLI ──HTTP──→ CleverAgents A2A Server ──→ ServiceFacade.method()
The client connects to the CleverAgents server via the A2A SDK's HTTP transport. All operations (standard + extensions) flow through the single A2A JSON-RPC 2.0 endpoint. Authentication uses the security schemes declared in the Agent Card.
Architectural enforcement of transport parity:
- The same A2A test suite runs over both transports (contract tests).
- No Presentation-layer module imports from Infrastructure (import-linter CI checks).
- The Service Facade is the sole Application-layer entry point from Presentation.
Streaming
A2A streaming uses Server-Sent Events (SSE) via the message/stream operation. The stream delivers typed events:
| Event Type | Emitted When |
|---|---|
TaskStatusUpdateEvent |
Task state changes (submitted → working → completed, etc.) |
TaskArtifactUpdateEvent |
Agent produces output artifacts (response chunks, plan entries, tool results) |
In local mode, events flow as JSON-RPC notifications over stdout. In server mode, the A2A SDK manages the HTTP SSE connection. Both modes deliver the same event types with the same payload shapes.
Causal ordering guarantee: Events within a single task lifecycle are delivered in causal order.
Multi-Turn Interactions
A2A natively supports multi-turn interactions through the Task lifecycle. When a server-hosted agent requires client-side input or approval:
- The Task enters the
input-requiredstate (delivered viaTaskStatusUpdateEvent) - The client displays the request to the user (permission prompt, file access request, etc.)
- The client responds via
message/sendwith the task's context ID, providing the requested input - The Task resumes processing
This pattern replaces the need for protocol-level callbacks. Platform-specific client-side operations (file access, terminal commands) use _cleveragents/ extension methods that the client handles locally.
Error Taxonomy
A2A uses JSON-RPC 2.0 integer error codes (per the JSON-RPC binding, A2A Section 9.5):
| Code | Meaning | Domain Exception(s) |
|---|---|---|
-32700 |
Parse error | — |
-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 |
Versioning and Compatibility
- The JSON-RPC protocol version is always
"2.0"in thejsonrpcfield - The A2A protocol version is communicated via the
A2A-VersionHTTP header in server mode - CleverAgents extension version is declared in the Agent Card's
extensionsfield underurn:cleveragents:extensions:v1 - Servers support the current extension version plus one prior minor version
- Backward-compatible additions (new optional params, new extension methods) are permitted within a major version; breaking changes require a major version bump
Authentication and Authorization
- Server mode: Standard HTTP authentication using security schemes declared in the Agent Card (OAuth2, API key, HTTP bearer). The Agent Card's
securitySchemesfield advertises which mechanisms are supported. Authorization is enforced per namespace. - Local mode: Authentication is bypassed — the agent subprocess runs with the user's local permissions.
Service Facade Mapping
Each A2A operation group maps to an Application-layer service. The complete method-to-service routing is documented in the specification's A2A Integration Architecture and Server and Client Architecture sections.
| A2A Category | Service |
|---|---|
| Standard message operations | SessionWorkflow |
| Task lifecycle operations | TaskService |
| Plan extension methods | PlanService, PlanLifecycle, CorrectionFlow |
| Registry extension methods | ActorService, ToolService, SkillService, ResourceService, ProjectService |
| Context extension methods | ContextService |
| Sync extension methods | SyncService |
| Namespace extension methods | NamespaceService |
Constraints
- Clients must not bypass A2A to access storage, repositories, or internal domain services directly.
- All A2A operations must be implementable over both stdio and HTTP transports with identical semantics.
- All A2A operations in server mode must require valid authentication (via Agent Card-declared security schemes).
- A2A responses must use the JSON-RPC 2.0 envelope; ad-hoc response shapes are prohibited.
- Standard A2A operations must not be modified — use
_cleveragents/extension methods for platform-specific operations. - Streaming events must preserve causal ordering within a single task lifecycle.
Consequences
Positive
- Clients are interchangeable — new clients (e.g., mobile, third-party dashboards) can be built against the A2A standard.
- Local and server modes share the same protocol surface, eliminating behavioral drift.
- Alignment with the A2A standard (Linux Foundation, Apache 2.0, multi-language SDKs) enables interoperability with the broader agent ecosystem.
- Agent Card discovery allows third-party agents and clients to discover CleverAgents capabilities dynamically.
- The A2A Python SDK provides production-quality transport implementations.
- JSON-RPC 2.0 is a mature, widely-tooled standard; gRPC and REST bindings are available for future adoption.
Negative
- The protocol adds upfront design and versioning overhead.
- Some client-specific optimizations (e.g., batching, caching) are harder when constrained to a shared contract.
Risks
- Protocol evolution could lag feature development if versioning discipline is not maintained.
Alternatives Considered
Per-client bespoke APIs — Faster initial development but leads to drift, duplicated logic, and higher long-term maintenance costs. Rejected.
Direct database access for local clients — Faster reads in local mode but breaks parity with server mode and tightly couples clients to storage schema. Rejected.
Bespoke REST API with custom JSON envelopes — Functional but isolated from the ecosystem. No interoperability with third-party agents or editors. Ongoing maintenance of custom envelope format. Rejected.
ACP (Agent Client Protocol) — The predecessor to A2A, also built on JSON-RPC 2.0. Lacked Agent Card discovery, had a smaller ecosystem, and is now deprecated in favor of A2A. A2A retains backward compatibility with ACP's JSON-RPC foundation. Rejected in favor of A2A's broader ecosystem, Linux Foundation governance, and multi-language SDK support.
gRPC — Strong typing and streaming but adds a code-generation dependency and is less accessible for browser-based clients than JSON-RPC over HTTP. A2A includes a gRPC binding (Section 10) that may be adopted for high-throughput server-to-server communication in the future.
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 A2A test suite over stdio and HTTP transports, asserting identical results.
- Authentication tests: Verify Agent Card-declared security schemes and namespace-scoped authorization in server mode.
- Streaming tests: Ensure event ordering and schema compliance for
TaskStatusUpdateEventandTaskArtifactUpdateEventpayloads. - Agent Card tests: Validate the generated Agent Card conforms to the A2A specification schema.
- Bypass detection: Architecture tests verify that no Presentation-layer module imports from the Infrastructure layer directly.