Files
cleveragents-core/docs/adr/ADR-026-agent-client-protocol.md

289 lines
17 KiB
Markdown

---
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 <Jeffrey.Freeman@CleverThis.com>
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 <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:**
```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.