# 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.