--- adr_number: 26 title: Agent-to-Agent Protocol (A2A) status_history: - - '2026-02-17' - Proposed - Jeffrey Phillips Freeman - - '2026-02-17' - Accepted - Jeffrey Phillips Freeman tier: 4 authors: - Jeffrey Phillips Freeman superseded_by: null related_adrs: - number: 1 title: Layered Architecture relationship: A2A defines the fundamental boundary between the Presentation and Application layers in the four-layer architecture - number: 6 title: Plan Lifecycle relationship: A2A extension methods expose the full plan lifecycle (use, execute, apply, cancel, correct, rollback) to all clients - number: 20 title: Session Model relationship: A2A message operations (message/send, message/stream) map directly to SessionWorkflow operations - number: 21 title: CLI and Output Rendering relationship: Every CLI command maps to an A2A method (standard or extension); the CLI is a thin rendering layer over A2A - number: 23 title: Server Mode relationship: A2A is the sole client-server protocol; server mode uses A2A over HTTP, local mode uses A2A JSON-RPC over stdio - number: 25 title: Observability and Logging relationship: A2A task update events deliver structured plan state changes and tool call events to subscribed clients - number: 27 title: Language Server Protocol (LSP) Integration relationship: LSP servers are Infrastructure-layer components attached to actors; the IDE plugin (Presentation layer) communicates through A2A independently of LSP - number: 47 title: A2A Standard Adoption relationship: ADR-047 defines the adoption of the external A2A standard that this ADR's protocol boundary implements - number: 48 title: Server Application Architecture relationship: ADR-048 defines the server that implements the A2A endpoint; this ADR defines the protocol boundary role acceptance: votes_for: - voter: Jeffrey Phillips Freeman comment: A2A provides the standardized agent-to-agent communication layer needed for multi-actor orchestration votes_against: [] abstentions: [] --- ## 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](https://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 URI `urn:cleveragents:extensions:v1`) - **Supported interfaces**: `jsonrpc` (primary), optionally `rest` - **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 `, 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:** ```json { "jsonrpc": "2.0", "id": 1, "method": "_cleveragents/plan/status", "params": { "plan_id": "01HXRCF1..." } } ``` **Successful response:** ```json { "jsonrpc": "2.0", "id": 1, "result": { "plan_id": "01HXRCF1...", "phase": "execute", "state": "running" } } ``` **Error response:** ```json { "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: 1. The Task enters the `input-required` state (delivered via `TaskStatusUpdateEvent`) 2. The client displays the request to the user (permission prompt, file access request, etc.) 3. The client responds via `message/send` with the task's context ID, providing the requested input 4. 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 the `jsonrpc` field - The A2A protocol version is communicated via the `A2A-Version` HTTP header in server mode - CleverAgents extension version is declared in the Agent Card's `extensions` field under `urn: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 `securitySchemes` field 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](../specification.md#a2a-integration-architecture) and [Server and Client Architecture](../specification.md#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 `TaskStatusUpdateEvent` and `TaskArtifactUpdateEvent` payloads. - **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.