# A2A (Agent-to-Agent Protocol) Reference

## Overview

CleverAgents adopts the external **Agent-to-Agent (A2A) Protocol** standard
([a2a-protocol.org](https://a2a-protocol.org)) as the sole communication
protocol for all client-server interaction. A2A provides the boundary layer
between the Presentation and Application layers.

**Module:** `cleveragents.a2a`
**Protocol:** JSON-RPC 2.0 binding (A2A specification Section 9)
**SDK:** `a2a-sdk` package ([a2aproject/a2a-python](https://github.com/a2aproject/a2a-python))

## Table of Contents

- [Agent Card](#agent-card)
- [Transport Modes](#transport-modes)
- [Standard A2A Operations](#standard-a2a-operations)
- [Extension Methods](#extension-methods)
- [Streaming Events](#streaming-events)
- [Multi-Turn Interactions](#multi-turn-interactions)
- [Local Facade](#local-facade)
- [Service Wiring](#service-wiring)
- [Error Code Taxonomy](#error-code-taxonomy)
- [Authentication](#authentication)
- [Client Architecture](#client-architecture)
- [Error Hierarchy](#error-hierarchy)

---

## Agent Card

A2A uses **Agent Cards** for capability discovery. The CleverAgents Agent Card
is served at `/.well-known/agent.json` in server mode:

```json
{
  "name": "CleverAgents",
  "description": "AI agent orchestration platform",
  "url": "https://server.example.com",
  "version": "1.0",
  "capabilities": {
    "streaming": true,
    "pushNotifications": true
  },
  "skills": [
    { "id": "plan-lifecycle", "name": "Plan Lifecycle Management" },
    { "id": "registry-crud", "name": "Entity Registry Operations" },
    { "id": "context-mgmt", "name": "Context Assembly" },
    { "id": "entity-sync", "name": "Entity Synchronization" },
    { "id": "namespace-mgmt", "name": "Namespace Management" }
  ],
  "extensions": [
    {
      "uri": "urn:cleveragents:extensions:v1",
      "description": "CleverAgents platform operations"
    }
  ],
  "securitySchemes": [
    { "type": "http", "scheme": "bearer" }
  ],
  "interfaces": [
    { "protocol": "jsonrpc", "url": "https://server.example.com/a2a" }
  ]
}
```

An authenticated extended Agent Card with additional detail is available
via the `getExtendedAgentCard` operation.

---

## Transport Modes

| Mode   | Transport              | Class / SDK Component              | Behaviour                                              |
|--------|------------------------|------------------------------------|--------------------------------------------------------|
| Local  | A2A JSON-RPC over stdio | `A2aLocalFacade` + JSON-RPC stdio  | Agent as subprocess; extensions resolved in-process |
| Server | A2A JSON-RPC over HTTP  | A2A SDK HTTP transport             | JSON-RPC 2.0 to CleverAgents server               |

In local mode the agent runs as a subprocess. JSON-RPC messages flow over
stdin/stdout. Extension methods (`_cleveragents/*`) are intercepted by
`A2aLocalFacade` and routed to in-process Application-layer services.
No network, no authentication.

In server mode the client connects via the A2A SDK's HTTP transport.
All operations — standard A2A and extensions — flow through the single
A2A JSON-RPC 2.0 endpoint on the server.

---

## Standard A2A Operations

These operations are defined by the external A2A specification and handle
the core agent interaction lifecycle:

| Operation | Direction | Purpose |
|-----------|-----------|---------|
| `message/send` | Client -> Server | Send a message to the agent; returns a Task or direct Message |
| `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 and pagination |
| `tasks/cancel` | Client -> Server | Cancel a running task |
| `tasks/subscribe` | Client -> Server | Subscribe to task updates via SSE |
| `pushNotificationConfig/create` | Client -> Server | Create push notification webhook |
| `pushNotificationConfig/get` | Client -> Server | Get push notification config |
| `pushNotificationConfig/list` | Client -> Server | List push notification configs |
| `pushNotificationConfig/delete` | Client -> Server | Delete push notification config |
| `getExtendedAgentCard` | Client -> Server | Fetch authenticated Agent Card |

---

## Extension Methods

Platform operations use `_cleveragents/`-prefixed extension methods
(declared in the Agent Card via the A2A extension mechanism):

### Plan Operations

| Method | Service Method | Required Params |
|--------|---------------|-----------------|
| `_cleveragents/plan/use` | `PlanService.create_plan()` | `action_name`, `project_names` |
| `_cleveragents/plan/execute` | `PlanLifecycle.execute()` | `plan_id` |
| `_cleveragents/plan/apply` | `PlanLifecycle.apply()` | `plan_id` |
| `_cleveragents/plan/cancel` | `PlanService.cancel()` | `plan_id` |
| `_cleveragents/plan/status` | `PlanService.get_status()` | `plan_id` |
| `_cleveragents/plan/tree` | `PlanService.get_tree()` | `plan_id` |
| `_cleveragents/plan/explain` | `PlanService.explain_decision()` | `plan_id`, `decision_id` |
| `_cleveragents/plan/correct` | `CorrectionFlow.correct()` | `plan_id`, `decision_id`, `correction` |
| `_cleveragents/plan/diff` | `PlanService.get_diff()` | `plan_id` |
| `_cleveragents/plan/artifacts` | `PlanService.get_artifacts()` | `plan_id` |
| `_cleveragents/plan/prompt` | `PlanService.inject_guidance()` | `plan_id`, `message` |
| `_cleveragents/plan/rollback` | `PlanLifecycle.rollback()` | `plan_id` |
| `_cleveragents/plan/list` | `PlanService.list()` | *(optional filters)* |

### Registry Operations

Pattern applies to all entity types (`actor`, `skill`, `tool`, `validation`,
`resource`, `resource_type`, `project`, `action`, `automation_profile`,
`invariant`, `lsp`):

| Method Pattern | Service Method Pattern | Required Params |
|---------------|----------------------|-----------------|
| `_cleveragents/registry/{entity}/list` | `{Entity}Service.list()` | `namespace` (optional) |
| `_cleveragents/registry/{entity}/show` | `{Entity}Service.show()` | `name` |
| `_cleveragents/registry/{entity}/add` | `{Entity}Service.add()` | Entity-specific fields |
| `_cleveragents/registry/{entity}/update` | `{Entity}Service.update()` | `name`, updated fields |
| `_cleveragents/registry/{entity}/remove` | `{Entity}Service.remove()` | `name` |

### Context Operations

| Method | Service Method | Required Params |
|--------|---------------|-----------------|
| `_cleveragents/context/show` | `ContextService.show()` | `project_name` |
| `_cleveragents/context/inspect` | `ContextService.inspect()` | `project_name` |
| `_cleveragents/context/simulate` | `ContextService.simulate()` | `project_name`, simulation params |
| `_cleveragents/context/set` | `ContextService.set()` | `project_name`, context data |

### Sync Operations

| Method | Service Method | Required Params |
|--------|---------------|-----------------|
| `_cleveragents/sync/pull` | `SyncService.pull()` | `namespace` |
| `_cleveragents/sync/push` | `SyncService.push()` | `namespace`, `entities` |
| `_cleveragents/sync/status` | `SyncService.status()` | `namespace` (optional) |

### Namespace Operations

| Method | Service Method | Required Params |
|--------|---------------|-----------------|
| `_cleveragents/namespace/list` | `NamespaceService.list()` | -- |
| `_cleveragents/namespace/show` | `NamespaceService.show()` | `namespace` |
| `_cleveragents/namespace/members` | `NamespaceService.members()` | `namespace` |

### Health and Diagnostics

| Method | Purpose |
|--------|---------|
| `_cleveragents/health/check` | Server health check |
| `_cleveragents/diagnostics/run` | Run diagnostic suite |

---

## Streaming Events

A2A streaming uses SSE via the `message/stream` operation, delivering typed
events as the task progresses:

| Event Type | Emitted When |
|-----------|-------------|
| `TaskStatusUpdateEvent` | Task state changes (submitted -> working -> completed, etc.) |
| `TaskArtifactUpdateEvent` | Agent produces output (response chunks, plan entries, tool results) |

### Task Lifecycle States

| State | Meaning |
|-------|---------|
| `submitted` | Task created, awaiting processing |
| `working` | Agent is actively processing |
| `input-required` | Agent needs client input (human-in-the-loop) |
| `completed` | Task finished successfully |
| `failed` | Task failed with error |
| `canceled` | Task was canceled by client |
| `rejected` | Task was rejected by agent |

### Example Streaming Event

```json
{
  "jsonrpc": "2.0",
  "method": "message/stream",
  "params": {
    "id": "task_01HXR...",
    "status": { "state": "working" },
    "artifacts": [{
      "parts": [{ "text": "I'll start by extracting..." }]
    }]
  }
}
```

---

## Multi-Turn Interactions

A2A replaces protocol-level callbacks with multi-turn interactions via the
Task lifecycle:

| Interaction | How It Works |
|-------------|-------------|
| Human-in-the-loop approval | Task enters `input-required` state; client displays prompt; client responds via `message/send` |
| File access (read/write) | `_cleveragents/fs/*` extension methods handled locally by client |
| Terminal access | `_cleveragents/terminal/*` extension methods handled locally by client |

When a server-hosted agent needs client-side resources, the Task enters
`input-required` state. The client handles the request and responds,
resuming the task.

---

## Local Facade

`A2aLocalFacade` handles extension method dispatch in local mode:

```python
from cleveragents.a2a import A2aLocalFacade

facade = A2aLocalFacade(services={
    "session_service": my_session_service,
    "plan_lifecycle_service": my_plan_lifecycle_service,
    "tool_registry": my_tool_registry,
    "resource_registry_service": my_resource_registry_service,
})

# Extension methods are dispatched to in-process services
result = await facade.dispatch("_cleveragents/plan/status", {"plan_id": "01J..."})
```

### Constructor

| Parameter  | Type                       | Default | Description                   |
|-----------|----------------------------|---------|-------------------------------|
| `services` | `dict[str, Any] \| None` | `None`  | Named services for routing    |

### Methods

| Method              | Returns           | Description                          |
|---------------------|-------------------|--------------------------------------|
| `dispatch(method, params)` | `dict`     | Route extension method to handler    |
| `register_service`  | `None`            | Register a named service             |
| `list_methods`      | `list[str]`       | All supported extension method names |

---

## Service Wiring

Each A2A extension method is wired to a concrete application service.
Services are injected via the `services` dict at construction time or
registered later with `register_service()`.

### Service Keys

| Key                          | Type                        | Wired Methods                      |
|------------------------------|-----------------------------|-------------------------------------|
| `session_service`            | `SessionWorkflow`           | Standard message operations        |
| `plan_lifecycle_service`     | `PlanLifecycleService`      | `_cleveragents/plan/*`             |
| `tool_registry`              | `ToolRegistry`              | `_cleveragents/registry/tool/*`    |
| `resource_registry_service`  | `ResourceRegistryService`   | `_cleveragents/registry/resource/*` |
| `sync_service`               | `SyncService`               | `_cleveragents/sync/*`             |
| `namespace_service`          | `NamespaceService`          | `_cleveragents/namespace/*`        |
| `context_service`            | `ContextService`            | `_cleveragents/context/*`          |

---

## Error Code Taxonomy

Domain exceptions are mapped to JSON-RPC 2.0 error codes:

| JSON-RPC Code     | Domain Exception(s)                    | Meaning                          |
|-------------------|----------------------------------------|----------------------------------|
| `-32700`          | --                                     | Parse error (malformed JSON)     |
| `-32600`          | --                                     | Invalid request                  |
| `-32601`          | `A2aOperationNotFoundError`            | Method not found                 |
| `-32602`          | `ValidationError`                      | Invalid params                   |
| `-32603`          | Any unhandled `Exception`              | Internal error                   |
| `-32001`          | `ResourceNotFoundError`                | Entity not found                 |
| `-32002`          | `AuthenticationError`                  | Authentication required          |
| `-32003`          | `AuthorizationError`                   | Authorization forbidden          |
| `-32004`          | `BusinessRuleViolation`                | Invalid state                    |
| `-32005`          | `DuplicateEntityError`                 | Already exists                   |
| `-32006`          | `BudgetExceededError`                  | Budget exceeded                  |
| `-32007`          | `A2aVersionMismatchError`              | Version mismatch                 |
| `-32008`          | `PlanError`                            | Plan lifecycle error             |

### Example Error Response

```json
{
  "jsonrpc": "2.0",
  "id": 42,
  "error": {
    "code": -32001,
    "message": "Plan not found",
    "data": { "plan_id": "01HXRCF1..." }
  }
}
```

---

## Authentication

Authentication uses standard HTTP security schemes declared in the Agent Card:

1. Client discovers Agent Card at `/.well-known/agent.json`
2. Agent Card's `securitySchemes` declares supported auth mechanisms
3. Client authenticates using the declared scheme (e.g., `Authorization: Bearer <token>`)
4. All subsequent requests include authentication credentials

Local mode (stdio) bypasses authentication -- the agent subprocess runs
with the user's local permissions.

---

## Client Architecture

The client uses an `A2aClient` wrapping the A2A Python SDK:

```python
from cleveragents.a2a import A2aClient, TransportSelector

# TransportSelector picks stdio or HTTP based on configuration
transport = TransportSelector().get_transport()
client = A2aClient(transport)

# Standard A2A operation
await client.send_message(message="Add pagination", context_id="ctx_01HXR...")

# Extension method
result = await client.plan_status(plan_id="01HXRCF1...")
```

### Components

| Component | Role | Notes |
|-----------|------|-------|
| `A2aLocalFacade` | Extension dispatch in local mode | Routes `_cleveragents/` methods to in-process services |
| A2A SDK HTTP transport | Server mode transport | Production HTTP transport with SSE streaming |
| A2A SDK JSON-RPC types | Wire format | `SendMessageRequest`, `Task`, `Message`, `Part`, etc. |
| `A2aEventQueue` | Local mode event delivery | In-process task update event delivery |
| Agent Card | Discovery | Capability advertisement and auth scheme declaration |

---

## Error Hierarchy

```
CleverAgentsError
  └── A2aError
        ├── A2aNotAvailableError
        ├── A2aVersionMismatchError
        └── A2aOperationNotFoundError
```

| Exception                   | When Raised                               |
|-----------------------------|-------------------------------------------|
| `A2aNotAvailableError`      | Server-mode operation attempted without connection |
| `A2aVersionMismatchError`   | Unsupported A2A version                           |
| `A2aOperationNotFoundError` | Unknown method dispatched                         |
