Files
cleveragents-core/docs/reference/acp.md
T
freemo 4b9df961f0
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 15s
CI / build (pull_request) Successful in 14s
CI / quality (pull_request) Successful in 19s
CI / security (pull_request) Successful in 32s
CI / unit_tests (pull_request) Successful in 1m59s
CI / integration_tests (pull_request) Successful in 2m49s
CI / lint (push) Successful in 13s
CI / build (push) Successful in 14s
CI / quality (push) Successful in 18s
CI / security (push) Successful in 29s
CI / typecheck (push) Successful in 44s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Successful in 1m59s
CI / docker (push) Successful in 41s
CI / integration_tests (push) Successful in 2m56s
CI / coverage (push) Successful in 3m54s
CI / benchmark-publish (push) Successful in 13m52s
CI / typecheck (pull_request) Successful in 31s
CI / coverage (pull_request) Has been cancelled
CI / docker (pull_request) Has been cancelled
CI / benchmark-regression (pull_request) Has been cancelled
feat(acp): wire ACP local facade handlers to live services
Wire all AcpLocalFacade operation handlers to their corresponding
application services via constructor-injected service dependencies:

- session.create/close delegate to SessionService
- plan.create/execute/status/diff/apply delegate to PlanLifecycleService
- registry.list_tools delegates to ToolRegistry
- registry.list_resources delegates to ResourceRegistryService
- event.subscribe delegates to AcpEventQueue
- context.get returns stub pending ACMS ContextAssemblyPipeline

Add domain-to-ACP error code mapping via map_domain_error() translating
ResourceNotFoundError to NOT_FOUND, ValidationError to VALIDATION_ERROR,
PlanError to PLAN_ERROR, BusinessRuleViolation to INVALID_STATE, and
other domain exceptions to their corresponding ACP error codes.

Handlers gracefully fall back to stub responses when services are absent.

Includes 21 Behave scenarios (features/acp_facade_wiring.feature) and
9 Robot Framework integration tests (robot/acp_facade_wiring.robot).
Updated docs/reference/acp.md with wired operation details, service
key table, and error code taxonomy.

ISSUES CLOSED: #501
2026-03-02 22:45:55 -05:00

12 KiB

ACP (Agent Communication Protocol) Reference

Overview

The ACP package provides the boundary layer between the CleverAgents application core and any external orchestrator or UI. It defines a request/response envelope, a set of named operations, and an event streaming interface.

Module: cleveragents.acp
ACP Version: 1.0

Table of Contents


Modes of Operation

Mode Class Behaviour
Local AcpLocalFacade Routes operations to in-process service calls
Server AcpHttpTransport Stub — raises AcpNotAvailableError on all ops

In local mode the facade translates each ACP operation into a direct Python method call. No serialization, no network, no authentication overhead.


Local Facade

from cleveragents.acp import AcpLocalFacade, AcpRequest

facade = AcpLocalFacade()
response = facade.dispatch(AcpRequest(operation="session.create"))
assert response.status == "ok"

Constructor

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

Methods

Method Returns Description
dispatch(request) AcpResponse Route request to handler
register_service None Register a named service
list_operations list[str] All supported operation names

Service Wiring

Each ACP operation is wired to a concrete application service. Services are injected via the services dict at construction time or registered later with register_service(). When a service key is absent, the handler falls back to a safe stub response.

Service Keys

Key Type Wired Operations
session_service SessionService session.create, session.close
plan_lifecycle_service PlanLifecycleService plan.create, plan.execute, plan.status, plan.diff, plan.apply
tool_registry ToolRegistry registry.list_tools
resource_registry_service ResourceRegistryService registry.list_resources
event_queue AcpEventQueue event.subscribe

Wired Operation Details

Operation Service Service Method Required Params
session.create SessionService create(actor_name=…) actor_name (optional)
session.close SessionService delete(session_id) session_id
plan.create PlanLifecycleService use_action(…) action_name
plan.execute PlanLifecycleService execute_plan(plan_id) plan_id
plan.status PlanLifecycleService get_plan(plan_id) plan_id
plan.diff PlanLifecycleService get_plan(plan_id) plan_id
plan.apply PlanLifecycleService apply_plan(plan_id) plan_id
registry.list_tools ToolRegistry list_tools(namespace=…) namespace (optional)
registry.list_resources ResourceRegistryService list_resources(type_name=…) type_name (optional)
context.get (stub) N/A
event.subscribe AcpEventQueue subscribe_local(cb)

!!! note "context.get" context.get currently returns a stub response ({"context": {}, "stub": true}) pending the completion of the ACMS ContextAssemblyPipeline.

Example: Wired Facade

from cleveragents.acp.facade import AcpLocalFacade
from cleveragents.acp.events import AcpEventQueue
from cleveragents.acp.models import AcpRequest

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,
    "event_queue": AcpEventQueue(),
})

response = facade.dispatch(
    AcpRequest(operation="plan.status", params={"plan_id": "01J…"})
)
assert response.status == "ok"
assert "phase" in response.data

Operation Routing Table

Operation Response Keys
session.create session_id, status
session.close status
plan.create plan_id, status
plan.execute plan_id, status
plan.status plan_id, phase, state
plan.diff plan_id, changes, phase
plan.apply plan_id, status
registry.list_tools tools (list of {name, description})
registry.list_resources resources (list of {resource_id, name, type_name})
context.get context, stub, message
event.subscribe subscription_id, status

Unknown operations raise AcpOperationNotFoundError.


Error Code Taxonomy

Domain exceptions are mapped to ACP error codes via map_domain_error():

ACP Error Code Domain Exception(s) Meaning
NOT_FOUND ResourceNotFoundError Requested entity does not exist
VALIDATION_ERROR ValidationError Input failed validation
PLAN_ERROR PlanError Plan lifecycle fault
INVALID_STATE BusinessRuleViolation State precondition not met
AUTH_ERROR AuthenticationError Authentication failure
FORBIDDEN AuthorizationError Insufficient permissions
CONFIGURATION_ERROR ConfigurationError Configuration missing or invalid
INTERNAL_ERROR Any other CleverAgentsError or Exception Unexpected server error

Error details are returned in the AcpResponse.error field as an AcpErrorDetail with the code and message fields populated.


Server Transport Stub

All methods on AcpHttpTransport raise AcpNotAvailableError:

Method Description
send(request) Would send request over HTTP
connect(url) Would open HTTP connection
disconnect() Would close connection
is_connected() Returns False (does not raise)

Event Queue

AcpEventQueue provides an in-memory event queue for local mode:

Method Mode Description
publish(event) Local Append event and notify callbacks
subscribe_local(cb) Local Register callback, return sub ID
unsubscribe(id) Local Remove subscription
get_events(limit) Local Return recent events
subscribe_remote(ep) Server Raises AcpNotAvailableError

Version Negotiation

AcpVersionNegotiator validates protocol version compatibility:

from cleveragents.acp import AcpVersionNegotiator

negotiator = AcpVersionNegotiator()
version = negotiator.negotiate("1.0")  # returns "1.0"
negotiator.negotiate("2.0")            # raises AcpVersionMismatchError

Supported versions: ["1.0"]


Models

AcpRequest

Field Type Default
acp_version str "1.0"
request_id str Auto-generated ULID
operation str required
params dict[str, Any] {}
auth dict[str, Any] | None None

AcpResponse

Field Type Default
acp_version str "1.0"
request_id str required
status str ("ok" or "error") required
data dict[str, Any] {}
error AcpErrorDetail | None None
timing_ms float | None None

AcpErrorDetail

Field Type Default
code str required
message str required
details dict[str, Any] {}

AcpEvent

Field Type Default
event_id str Auto-generated ULID
event_type str required
plan_id str | None None
data dict[str, Any] {}
timestamp str Auto-generated ISO UTC

Error Hierarchy

CleverAgentsError
  └── AcpError
        ├── AcpNotAvailableError
        ├── AcpVersionMismatchError
        └── AcpOperationNotFoundError
Exception When Raised
AcpNotAvailableError Server-mode operation in local mode
AcpVersionMismatchError Unsupported ACP version requested
AcpOperationNotFoundError Unknown operation dispatched