Files
cleveragents-core/docs/reference/acp.md
T

14 KiB

ACP (Agent Client Protocol) Reference

Overview

CleverAgents adopts the external Agent Client Protocol standard (agentclientprotocol.org) as the sole communication protocol for all client-server interaction. ACP is built on JSON-RPC 2.0 and provides the boundary layer between the Presentation and Application layers.

Module: cleveragents.acp Protocol: JSON-RPC 2.0 (per ACP standard) SDK: acp package (agentclientprotocol/python-sdk)

Table of Contents


Transport Modes

Mode Transport Class / SDK Component Behaviour
Local ACP over stdio AcpLocalFacade + ACP SDK stdio transport Agent as subprocess; extensions resolved in-process
Server ACP over HTTP ACP SDK ClientSideConnection over HTTP 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 AcpLocalFacade and routed to in-process Application-layer services. No network, no authentication.

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


Standard ACP Methods

These methods are defined by the external ACP specification and handle the core agent conversation lifecycle:

Method Direction Purpose
initialize Client → Server Capability negotiation, version exchange
authenticate Client → Server Token-based authentication
session/new Client → Server Create a new conversation session
session/load Client → Server Resume an existing session
session/list Client → Server List available sessions
session/prompt Client → Server Send user message to agent
session/cancel Client → Server Cancel in-progress operation
session/set_mode Client → Server Switch automation profile
session/set_model Client → Server Switch LLM provider/model
session/fork Client → Server Fork a session
session/resume Client → Server Resume a paused session

Extension Methods

Platform operations use _cleveragents/-prefixed extension methods (per the ACP extensibility specification):

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 Notifications

ACP streaming uses JSON-RPC 2.0 notifications (session/update) — messages with no id field that expect no response:

Notification Type Emitted When
agent_message_chunk Agent produces response tokens
plan Plan state changes (entries with content, priority, status)
tool_call Tool execution begins
tool_call_update Tool execution progress/result
mode_change Automation profile switched

Example Notification

{
  "jsonrpc": "2.0",
  "method": "session/update",
  "params": {
    "session_id": "ses_01HXR...",
    "type": "tool_call",
    "data": { "tool_name": "local/git-diff", "arguments": { "resource": "local/platform-repo" } }
  }
}

ACP Callbacks

Server-to-client requests for operations requiring client-side resources:

Callback Direction Purpose
session/request_permission Server → Client Human-in-the-loop approval
fs/read_text_file Server → Client Agent reads file on client machine
fs/write_text_file Server → Client Agent writes file on client machine
terminal/create Server → Client Agent requests terminal on client
terminal/output Server → Client Terminal output streaming
terminal/release Server → Client Release terminal
terminal/wait_for_exit Server → Client Wait for process exit
terminal/kill Server → Client Kill terminal process

Local Facade

AcpLocalFacade handles extension method dispatch in local mode:

from cleveragents.acp import AcpLocalFacade

facade = AcpLocalFacade(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 ACP 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 session/* methods
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 AcpOperationNotFoundError 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 AcpVersionMismatchError Version mismatch
-32008 PlanError Plan lifecycle error

Example Error Response

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

Authentication

Authentication follows the ACP standard connection lifecycle:

  1. Client sends initialize with capabilities
  2. Server responds with its capabilities (including _cleveragents extensions)
  3. Client sends authenticate with { "token": "<server.token>" }
  4. Server validates and returns authentication status

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


Client Architecture

The client uses an AcpClient wrapping the ACP Python SDK:

from cleveragents.acp import AcpClient, TransportSelector

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

# Standard ACP method
await client.prompt(session_id="ses_01HXR...", message="Add pagination")

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

Component Evolution

Previous Component Current Replacement Notes
AcpLocalFacade Retained Adapts to ACP method signatures
AcpHttpTransport (stub) ACP SDK ClientSideConnection SDK provides production transport
AcpRequest / AcpResponse ACP SDK JSON-RPC types Native SDK types
AcpEvent session/update notifications Mapped to ACP notification types
AcpEventQueue Retained for local mode In-process notification delivery
AcpVersionNegotiator initialize handshake Per ACP standard

Error Hierarchy

CleverAgentsError
  └── AcpError
        ├── AcpNotAvailableError
        ├── AcpVersionMismatchError
        └── AcpOperationNotFoundError
Exception When Raised
AcpNotAvailableError Server-mode operation attempted without connection
AcpVersionMismatchError Unsupported ACP version during initialize
AcpOperationNotFoundError Unknown method dispatched