Files
cleveragents-core/docs/api/protocols.md
HAL9000 236d1abd80
CI / push-validation (pull_request) Successful in 16s
CI / build (pull_request) Successful in 24s
CI / helm (pull_request) Successful in 28s
CI / quality (pull_request) Successful in 32s
CI / lint (pull_request) Successful in 34s
CI / typecheck (pull_request) Successful in 48s
CI / security (pull_request) Successful in 59s
CI / e2e_tests (pull_request) Successful in 3m3s
CI / integration_tests (pull_request) Successful in 3m54s
CI / unit_tests (pull_request) Successful in 5m0s
CI / docker (pull_request) Successful in 11s
CI / coverage (pull_request) Successful in 10m50s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Successful in 57m42s
docs: add API documentation (CLI reference, Python API, protocols) [AUTO-DOCS-2]
2026-04-13 05:09:31 +00:00

597 lines
17 KiB
Markdown

# Protocols
CleverAgents deliberately adopts open, versioned protocols so that clients,
tools, and skills can interoperate without bespoke integrations.
| Protocol | Role |
|----------|------|
| [A2A](#a2a-agent-to-agent-protocol) | Versioned client-server contract (JSON-RPC 2.0) |
| [MCP](#mcp-model-context-protocol) | Tool discovery and invocation over a server boundary |
| [LSP](#lsp-language-server-protocol) | Language intelligence for actors and agents |
| [AgentSkills.io](#agentskillsio) | Packaging instruction-driven, multi-step workflows |
> **Guiding principles:**
> 1. **Prefer open protocols** — align with community standards to keep integrations portable.
> 2. **Keep adapters at the edge** — standards map into stable internal domain models so core logic remains protocol-agnostic.
---
## A2A — Agent-to-Agent Protocol
**Standard:** [a2a-protocol.org](https://a2a-protocol.org)
**ADRs:** [ADR-026](../adr/ADR-026-agent-client-protocol.md), [ADR-047](../adr/ADR-047-acp-standard-adoption.md), [ADR-048](../adr/ADR-048-server-application-architecture.md)
**Python API:** [`cleveragents.a2a`](a2a.md)
### Overview
A2A is the **sole** communication protocol for all client-server interaction in
CleverAgents. It is built on **JSON-RPC 2.0** and defines the fundamental
boundary between the Presentation and Application layers. Every CLI command,
TUI action, and IDE plugin operation flows through A2A regardless of deployment
mode.
A2A is the successor to the Agent Client Protocol (ACP), which is now
deprecated. A2A retains backward compatibility with ACP's JSON-RPC 2.0
foundation.
### Wire Format
All A2A messages follow the JSON-RPC 2.0 specification:
```json
// Request
{
"jsonrpc": "2.0",
"id": "req-001",
"method": "session.create",
"params": {
"actor": "openai/gpt-4o"
}
}
// Success response
{
"jsonrpc": "2.0",
"id": "req-001",
"result": {
"session_id": "sess-abc123",
"actor": "openai/gpt-4o",
"created_at": "2026-04-13T10:00:00Z"
}
}
// Error response
{
"jsonrpc": "2.0",
"id": "req-001",
"error": {
"code": -32000,
"message": "Actor not found: openai/gpt-4o",
"data": {"actor": "openai/gpt-4o"}
}
}
```
> **Breaking change (v3.7.0+):** Fields were renamed to comply with JSON-RPC 2.0.
> `a2a_version` → `jsonrpc`, `request_id` → `id`, `operation` → `method`,
> `data` → `result`. See the [CHANGELOG](../../CHANGELOG.md) for the full
> migration table.
### Standard A2A Operations
| Method | Description |
|--------|-------------|
| `message/send` | Send a message to an agent |
| `message/stream` | Stream a message response via SSE |
| `tasks/get` | Get task status |
| `tasks/cancel` | Cancel a running task |
| `agent/authenticatedExtendedCard` | Retrieve the Agent Card (capability discovery) |
### CleverAgents Extension Methods
CleverAgents extends A2A with `_cleveragents/`-prefixed methods (declared via
the A2A extension mechanism):
| Method | Description |
|--------|-------------|
| `session.create` | Create a new conversation session |
| `session.close` | Close an existing session |
| `plan.create` | Instantiate a plan from an action |
| `plan.execute` | Execute a plan |
| `plan.status` | Query plan status |
| `plan.diff` | Retrieve the sandbox diff |
| `plan.apply` | Apply the sandbox changeset |
| `plan.correct` | Correct a decision |
| `registry.list_tools` | List available tools |
| `registry.list_resources` | List available resources |
| `registry.list_actors` | List available actors |
| `registry.list_skills` | List available skills |
| `event.subscribe` | Subscribe to the event stream |
| `diagnostics.run` | Run diagnostics |
### Deployment Modes
| Mode | Transport | Description |
|------|-----------|-------------|
| **Local** | stdio (JSON-RPC) | Agent runs as a subprocess; A2A flows in-process via `A2aLocalFacade` |
| **Server** | HTTP | A2A flows over HTTP to the CleverAgents server |
```python
from cleveragents.a2a import A2aLocalFacade, A2aRequest
# Local mode — no network, no serialization overhead
facade = A2aLocalFacade(container)
response = await facade.dispatch(
A2aRequest(method="session.create", params={"actor": "openai/gpt-4o"})
)
session_id = response.result["session_id"]
```
### Agent Card Discovery
The A2A Agent Card (`agent/authenticatedExtendedCard`) exposes the platform's
capabilities for ecosystem interoperability:
```json
{
"name": "CleverAgents",
"version": "1.0.0",
"description": "Unified AI agent orchestration platform",
"capabilities": {
"streaming": true,
"pushNotifications": true,
"stateTransitionHistory": true
},
"extensions": [
{
"uri": "https://cleverthis.com/a2a/extensions/plan-lifecycle",
"methods": ["plan.create", "plan.execute", "plan.apply", "plan.diff", "plan.correct"]
},
{
"uri": "https://cleverthis.com/a2a/extensions/registry",
"methods": ["registry.list_tools", "registry.list_resources", "registry.list_actors"]
}
]
}
```
### Event Streaming
Subscribe to plan and session events via the A2A event stream:
```python
from cleveragents.a2a import A2aEventQueue
queue = A2aEventQueue()
async for event in queue.subscribe("plan-01JXYZ..."):
print(event.type, event.payload)
if event.type == "plan.applied":
break
queue.close() # release resources on shutdown
```
### Error Codes
| Code | Name | Description |
|------|------|-------------|
| `-32700` | Parse error | Invalid JSON |
| `-32600` | Invalid request | Not a valid JSON-RPC 2.0 request |
| `-32601` | Method not found | Unknown A2A method |
| `-32602` | Invalid params | Invalid method parameters |
| `-32603` | Internal error | Internal server error |
| `-32000` | Application error | CleverAgents domain error |
| `-32001` | Not available | Operation not available in current mode |
| `-32002` | Version mismatch | Incompatible A2A protocol versions |
---
## MCP — Model Context Protocol
**Standard:** [modelcontextprotocol.io](https://modelcontextprotocol.io)
**ADR:** [ADR-029](../adr/ADR-029-model-context-protocol.md)
**Python API:** [`cleveragents.mcp`](mcp.md)
### Overview
MCP is the standard for discovering and invoking external tools over a server
boundary via JSON-RPC. CleverAgents bridges MCP servers into the Tool Registry
via the `MCPToolAdapter`, giving actors plug-and-play access to a growing
ecosystem of tool providers.
### Supported Transports
| Transport | Description |
|-----------|-------------|
| `stdio` | Spawn a subprocess and communicate over stdin/stdout |
| `sse` | Server-Sent Events over HTTP |
| `streamable-http` | Streamable HTTP (MCP 1.1+) |
### Connecting an MCP Server
```python
from cleveragents.mcp import MCPToolAdapter, MCPServerConfig
from cleveragents.tool import ToolRegistry
# Configure the MCP server
config = MCPServerConfig(
name="bash-tools",
transport="stdio",
command="uvx",
args=["mcp-server-bash"],
)
# Connect and discover tools
adapter = MCPToolAdapter(config)
await adapter.connect()
tools = await adapter.discover_tools()
# Register tools into the CleverAgents Tool Registry
registry = ToolRegistry()
adapter.register_tools(registry)
# Invoke a tool
result = await adapter.invoke("bash", {"command": "ls -la"})
print(result.content)
await adapter.disconnect()
```
### MCP Server Configuration Reference
| Field | Type | Description |
|-------|------|-------------|
| `name` | `str` | Server identifier (used as tool namespace prefix) |
| `transport` | `str` | `"stdio"` \| `"sse"` \| `"streamable-http"` |
| `command` | `str \| None` | Spawn command (stdio only) |
| `args` | `list[str]` | Command-line arguments |
| `env` | `dict[str, str]` | Environment variables passed to the server process |
| `url` | `str \| None` | Server URL (sse/http only) |
| `headers` | `dict[str, str]` | HTTP headers (sse/http only) |
### Tool Discovery
MCP tools are discovered via the `tools/list` method and registered in the
Tool Registry with `source="mcp"`. Each discovered tool becomes a
`MCPToolDescriptor`:
```python
class MCPToolDescriptor(BaseModel):
name: str
description: str
input_schema: dict[str, Any] # JSON Schema
annotations: dict[str, Any]
```
### Sandbox Path Rewriting
When running tools inside a sandbox, the `SandboxPathRewriter` rewrites
absolute host paths in tool arguments and results to sandbox-relative paths,
preventing path traversal outside the sandbox root:
```python
from cleveragents.mcp import SandboxPathRewriter, SandboxPathRewriterConfig
rewriter = SandboxPathRewriter(
SandboxPathRewriterConfig(
sandbox_root="/sandbox",
host_root="/home/user/project",
)
)
rewritten_args = rewriter.rewrite_args(tool_args)
```
### Skill Refresh Notifications
When an MCP server's tool list changes at runtime, `MCPRefreshHook` wires
`notifications/tools/list_changed` events to `SkillRegistry.refresh_all()`:
```python
from cleveragents.mcp import MCPRefreshHook
hook = MCPRefreshHook(skill_registry)
adapter.on_tools_changed(hook.on_tools_changed)
```
### MCP Client Lifecycle
```
STOPPED → STARTING → RUNNING → STOPPING → STOPPED
↘ ERROR
```
The `McpClient` manages lazy start (server is only started when first needed)
and auto-stop after a configurable idle timeout:
```python
from cleveragents.mcp import McpClient, McpClientConfig
client_config = McpClientConfig(server=server_config, auto_stop_idle_secs=60)
client = McpClient(client_config)
async with client:
tools = await client.list_tools()
result = await client.call_tool("bash", {"command": "echo hello"})
```
---
## LSP — Language Server Protocol
**Standard:** [microsoft.github.io/language-server-protocol](https://microsoft.github.io/language-server-protocol/)
**ADR:** [ADR-027](../adr/ADR-027-language-server-protocol.md)
### Overview
LSP is the standard for attaching language intelligence to actors and agents.
CleverAgents registers LSP servers in the global **LSP Registry** and binds
them to actor graph nodes via YAML configuration. When an actor activates,
the LSP Runtime starts the appropriate language servers for the actor's bound
languages and workspace resources.
### Capabilities Exposed to Actors
LSP capabilities are exposed to actors in two ways:
1. **As callable tools** via `LSPToolAdapter` — actors can invoke LSP
operations (diagnostics, completions, references, rename, code actions)
as regular tool calls.
2. **As automatic context enrichment** — diagnostics and type annotations
are injected into the ACMS hot context automatically.
| LSP Capability | Tool Name | Description |
|----------------|-----------|-------------|
| `textDocument/diagnostic` | `lsp.diagnostics` | Get diagnostics for a file |
| `textDocument/hover` | `lsp.hover` | Get type info and documentation at a position |
| `textDocument/definition` | `lsp.definition` | Go to definition |
| `textDocument/references` | `lsp.references` | Find all references |
| `textDocument/completion` | `lsp.completion` | Get completions at a position |
| `textDocument/rename` | `lsp.rename` | Rename a symbol |
| `textDocument/codeAction` | `lsp.code_action` | Get available code actions |
| `textDocument/signatureHelp` | `lsp.signature_help` | Get function signature help |
### Registering an LSP Server
```bash
# Register a Python LSP server
agents lsp add --config examples/lsp/pyright.yaml
# List registered LSP servers
agents lsp list --language python
# Show LSP server details
agents lsp show local/pyright
```
LSP server YAML configuration:
```yaml
name: local/pyright
language: python
command: pyright-langserver
args: ["--stdio"]
env: {}
workspace_mapping: auto # auto | explicit
```
### Actor YAML Binding
Bind LSP servers to actor graph nodes in the actor YAML:
```yaml
name: local/my-python-actor
entry_node: analyze
nodes:
analyze:
type: llm
lsp_binding:
language: python # bind by language (auto-selects server)
# or:
server: local/pyright # bind by explicit server name
```
Different nodes in an actor's graph can have different LSP bindings, enabling
fine-grained control over which agents receive which language intelligence.
### LSP Runtime
The LSP Runtime in the Infrastructure layer manages:
- **Server lifecycle** — start, stop, health monitoring
- **Workspace mapping** — maps project resources to LSP workspace folders
- **File synchronization** — keeps LSP server in sync with resource changes
- **Capability negotiation** — negotiates supported capabilities during initialization
### Auto-Discovery
Actors can bind LSP servers automatically based on the languages detected in
their project's resources:
```yaml
lsp_binding:
mode: auto # detect languages from project resources
```
---
## AgentSkills.io
**Standard:** [AgentSkills.io](https://AgentSkills.io)
**ADRs:** [ADR-028](../adr/ADR-028-agent-skills-standard.md), [ADR-030](../adr/ADR-030-skill-abstraction-definition.md)
**Python API:** [`cleveragents.skills`](skills.md)
### Overview
AgentSkills.io is the standard for packaging instruction-driven, multi-step
workflows as `SKILL.md` files with progressive disclosure. Agent Skills
complement MCP tools by teaching agents *how* to accomplish complex tasks
rather than simply exposing callable functions.
### Skill Bundle Structure
An AgentSkills-compatible skill bundle is a directory with the following layout:
```
my-skill/
├── SKILL.md # Required: skill definition with progressive disclosure
├── scripts/ # Optional: executable scripts referenced by steps
│ └── deploy.sh
├── references/ # Optional: reference documents
│ └── api-spec.md
└── assets/ # Optional: static assets
└── schema.json
```
### `SKILL.md` Format
```markdown
# Deploy to Staging
## Description
Deploys the application to the staging environment.
## Steps
### 1. Run tests
Execute the test suite and verify all tests pass.
```bash
scripts/run-tests.sh
```
### 2. Build artifacts
Build the deployment artifacts.
### 3. Deploy
Deploy to the staging environment using the deployment script.
```bash
scripts/deploy.sh --env staging
```
## Definition of Done
- All tests pass
- Application is accessible at the staging URL
- Health check returns 200
```
### Loading a Skill Bundle
```python
from pathlib import Path
from cleveragents.skills import AgentSkillLoader
loader = AgentSkillLoader.from_folder(Path("./skills/deploy-to-staging"))
spec = loader.load()
print(spec.name) # "deploy-to-staging"
print(spec.version) # "1.0.0"
for step in spec.steps:
print(f" Step: {step.title}")
```
### Discovering Skills
```python
from cleveragents.skills import discover_agent_skills, register_discovered_skills
result = discover_agent_skills([Path("./skills/")])
for skill in result.skills:
print(f"Found: {skill.name} v{skill.version}")
# Register all discovered skills
register_discovered_skills(result, skill_registry)
```
### Registering via CLI
```bash
# Register a skill from a YAML config
agents skill add --config examples/skills/deploy.yaml
# Or discover from a directory (set CLEVERAGENTS_SKILLS_PATH)
export CLEVERAGENTS_SKILLS_PATH=/path/to/skills:/another/path
agents skill list # shows all discovered skills
```
### Progressive Disclosure
AgentSkills.io uses a three-tier progressive disclosure model:
| Tier | Description |
|------|-------------|
| **Discover** | Actor learns the skill exists and its high-level description |
| **Activate** | Actor loads the full `SKILL.md` and step details |
| **Deactivate** | Actor releases the skill when no longer needed |
This keeps the actor's context window lean — skills are only fully loaded
when the actor decides to use them.
### `AgentSkillSpec`
The parsed representation of a skill bundle:
```python
class AgentSkillSpec(BaseModel):
name: str
version: str
steps: list[SkillStep]
tools: list[AgentSkillToolDescriptor]
resource_slots: list[AgentSkillResourceSlot]
```
### Inline Executor
Skills can define steps as inline Python callables rather than external tool
calls. The `InlineToolExecutor` handles these:
```python
from cleveragents.skills import InlineToolExecutor
executor = InlineToolExecutor()
result = await executor.execute(step, context)
```
### Skill Context
The `SkillContext` carries runtime state during skill execution:
```python
class SkillContext:
session_id: str
plan_id: str
bound_resources: list[BoundResource]
cancellation_token: CancellationToken
invocation_history: list[ToolInvocationRecord]
```
---
## Protocol Interoperability
The four protocols work together in a layered fashion:
```
User / IDE / CI
A2A (JSON-RPC 2.0) ← all client-server communication
CleverAgents Application
┌───────────────────────────────────────┐
│ MCP Adapter LSP Runtime Skills │ ← tool/intelligence/skill sources
└───────────────────────────────────────┘
Tool Registry ← all tools unified here
Actor (LangGraph) ← executes plans using tools
```
- **A2A** is the outer boundary — all clients speak A2A.
- **MCP** brings external tools into the Tool Registry.
- **LSP** brings language intelligence into actor context and as tools.
- **AgentSkills.io** brings instruction-driven workflows as activatable skills.
All four integrate into the same internal domain model, so actors see a
unified surface regardless of where a tool or skill originated.