980fcabc48
CI / push-validation (pull_request) Successful in 28s
CI / lint (pull_request) Successful in 32s
CI / helm (pull_request) Successful in 36s
CI / build (pull_request) Successful in 43s
CI / quality (pull_request) Successful in 55s
CI / typecheck (pull_request) Successful in 1m18s
CI / security (pull_request) Successful in 1m19s
CI / unit_tests (pull_request) Successful in 6m51s
CI / integration_tests (pull_request) Successful in 10m33s
CI / docker (pull_request) Failing after 12m6s
CI / coverage (pull_request) Failing after 12m22s
CI / status-check (pull_request) Failing after 3s
444 lines
18 KiB
Markdown
444 lines
18 KiB
Markdown
# 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
|
|
|
|
- [A2A (Agent-to-Agent Protocol) Reference](#a2a-agent-to-agent-protocol-reference)
|
|
- [Overview](#overview)
|
|
- [Table of Contents](#table-of-contents)
|
|
- [Agent Card](#agent-card)
|
|
- [Transport Modes](#transport-modes)
|
|
- [Standard A2A Operations](#standard-a2a-operations)
|
|
- [Extension Methods](#extension-methods)
|
|
- [Plan Operations](#plan-operations)
|
|
- [Registry Operations](#registry-operations)
|
|
- [Context Operations](#context-operations)
|
|
- [Sync Operations](#sync-operations)
|
|
- [Namespace Operations](#namespace-operations)
|
|
- [Health and Diagnostics](#health-and-diagnostics)
|
|
- [Streaming Events](#streaming-events)
|
|
- [Task Lifecycle States](#task-lifecycle-states)
|
|
- [Example Streaming Event](#example-streaming-event)
|
|
- [Multi-Turn Interactions](#multi-turn-interactions)
|
|
- [Local Facade](#local-facade)
|
|
- [Constructor](#constructor)
|
|
- [Methods](#methods)
|
|
- [Service Wiring](#service-wiring)
|
|
- [Service Keys](#service-keys)
|
|
- [Error Code Taxonomy](#error-code-taxonomy)
|
|
- [Example Error Response](#example-error-response)
|
|
- [Authentication](#authentication)
|
|
- [Client Architecture](#client-architecture)
|
|
- [Components](#components)
|
|
- [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
|
|
from cleveragents.a2a.models import A2aRequest
|
|
|
|
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 (synchronous)
|
|
response = facade.dispatch(A2aRequest(
|
|
method="_cleveragents/plan/status",
|
|
params={"plan_id": "01J..."}
|
|
))
|
|
```
|
|
|
|
### Constructor
|
|
|
|
| Parameter | Type | Default | Description |
|
|
|------------|----------------------------|---------|-------------------------------|
|
|
| `services` | `dict[str, Any] \| None` | `None` | Named services for routing |
|
|
|
|
### Methods
|
|
|
|
| Method | Returns | Description |
|
|
|---------------------------------|-------------------|--------------------------------------|
|
|
| `dispatch(request: A2aRequest)` | `A2aResponse` | Route extension method to handler |
|
|
| `register_service` | `None` | Register a named service |
|
|
| `list_operations()` | `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 |
|
|
| `-32009` | `ConfigurationError` | Configuration 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 |
|
|
|
|
---
|
|
|
|
## ACP to A2A Migration
|
|
|
|
> **v3.6.0 breaking change.** The `cleveragents.acp` module was renamed to
|
|
> `cleveragents.a2a` and all `Acp*` symbols were renamed to `A2a*`. The
|
|
> request/response wire format was updated to comply with JSON-RPC 2.0.
|
|
|
|
For a complete migration guide including symbol rename tables, field name
|
|
changes, operation name mapping, and YAML configuration updates, see
|
|
[`docs/development/acp-to-a2a-migration.md`](../development/acp-to-a2a-migration.md).
|
|
|
|
### Quick Reference: Deprecated Legacy Operations
|
|
|
|
The following ACP operation names are accepted by `A2aLocalFacade.dispatch()`
|
|
in `cleveragents.a2a.facade.A2aLocalFacade` (commit `449c33b7`) for backward
|
|
compatibility but are **deprecated**:
|
|
|
|
| Deprecated (ACP) | Replacement (A2A) |
|
|
|---|---|
|
|
| `session.create` | `_cleveragents/session/create` |
|
|
| `session.close` | `_cleveragents/session/close` |
|
|
| `plan.create` | `_cleveragents/plan/use` |
|
|
| `plan.execute` | `_cleveragents/plan/execute` |
|
|
| `plan.status` | `_cleveragents/plan/status` |
|
|
| `plan.diff` | `_cleveragents/plan/diff` |
|
|
| `plan.apply` | `_cleveragents/plan/apply` |
|
|
| `registry.list_tools` | `_cleveragents/registry/tool/list` |
|
|
| `registry.list_resources` | `_cleveragents/registry/resource/list` |
|
|
| `context.get` | `_cleveragents/context/show` |
|
|
|
|
See [ADR-047](../adr/ADR-047-acp-standard-adoption.md) for the architectural
|
|
rationale behind this change.
|