Skip to content

Agent Client Protocol (ACP)

chimera.acp implements the Agent Client Protocol — a JSON-RPC 2.0 interface for communicating with external AI agents over subprocess stdio. It lets a Chimera agent delegate tasks to any ACP-compatible agent (other Chimera instances, IDE-shaped coding agents, or custom servers) and collect their responses, tool calls, and cost data as first-class objects.

from chimera.acp import ACPClient, ACPSessionConfig
config = ACPSessionConfig(
command=["python", "-m", "my_agent_server"],
working_dir="/path/to/project",
)
with ACPClient(config) as client:
response = client.send_message("Refactor the auth module")
print(response.text)
print(f"Cost: ${response.cost:.4f}")
print(f"Tool calls: {len(response.tool_calls)}")
ClassDescription
ACPSessionConfigDataclass configuring the subprocess command, args, env, working directory, and notification drain delay
ACPToolCallDataclass representing a tool call made by the external agent, with id, title, kind, status, input/output, and error flag
ACPResponseDataclass accumulating the full response: text, thoughts, tool calls, cost, and token usage
ACPClientJSON-RPC 2.0 client that spawns and communicates with an ACP server subprocess
ExternalAgentToolWraps an ACPClient as a Chimera BaseTool so external agents appear as regular tools

Configure how the ACP server subprocess is spawned:

from chimera.acp import ACPSessionConfig
config = ACPSessionConfig(
command=["npx", "-y", "<acp-bridge-pkg>"],
args=["--model", "claude-sonnet-4-6"],
env={"ANTHROPIC_API_KEY": "sk-ant-..."},
working_dir="/path/to/repo",
notification_drain_delay=0.1,
)
FieldTypeDefaultDescription
commandlist[str][]Command to spawn the ACP server
argslist[str][]Additional CLI arguments
envdict[str, str]{}Extra environment variables (merged with os.environ)
working_dirstr | NoneNoneWorking directory for the subprocess
notification_drain_delayfloat0.1Seconds to wait for trailing notifications

The client manages the subprocess lifecycle and JSON-RPC communication:

from chimera.acp import ACPClient, ACPSessionConfig
config = ACPSessionConfig(command=["python", "-m", "my_agent"])
client = ACPClient(config)
# Manual lifecycle
client.start() # Spawns subprocess, creates session
response = client.send_message("Write unit tests for utils.py")
client.stop() # Terminates subprocess
# Context manager (recommended)
with ACPClient(config) as client:
response = client.send_message("Fix the failing CI tests")

Pass an on_chunk callback to send_message() for real-time streaming:

def print_chunk(chunk: str):
print(chunk, end="", flush=True)
with ACPClient(config) as client:
response = client.send_message(
"Explain the architecture",
on_chunk=print_chunk,
)

Fork a session to run parallel queries that share the same conversation history up to the fork point:

with ACPClient(config) as client:
client.send_message("Read the codebase and understand the architecture")
# Fork for parallel exploration
fork_id = client.fork_session()
# The new session_id can be used with the same subprocess

The response object accumulates all data from a send_message() call:

FieldTypeDescription
textstrFull text response from the external agent
thoughtslist[str]Reasoning/thought chunks (if the agent emits them)
tool_callslist[ACPToolCall]Tool calls made during the response
costfloatTotal cost of the response in USD
input_tokensintNumber of input tokens consumed
output_tokensintNumber of output tokens generated

Each tool call made by the external agent is captured as an ACPToolCall:

FieldTypeDescription
tool_call_idstrUnique identifier
titlestrHuman-readable title
tool_kindstrKind/category of tool
statusstr"running", "completed", or "error"
raw_inputstr | NoneRaw input sent to the tool
raw_outputstr | NoneRaw output from the tool
is_errorboolWhether the tool call failed

ExternalAgentTool wraps an ACP agent as a standard Chimera BaseTool. This means you can add external agents to any agent’s tool list and the model will be able to delegate tasks to them.

from chimera.acp import ExternalAgentTool, ACPSessionConfig
from chimera.core.agent import Agent
from chimera.providers import create_provider
# Configure the external agent
config = ACPSessionConfig(
command=["npx", "-y", "<acp-bridge-pkg>"],
working_dir="/path/to/frontend",
)
# Create the tool
frontend_agent = ExternalAgentTool(
config=config,
agent_name="frontend_expert",
)
# Add it to an agent's tool list
provider = create_provider("anthropic")
agent = Agent(
provider=provider,
tools=[frontend_agent], # model sees "frontend_expert" as a callable tool
)

The tool accepts a single task argument and returns a ToolResult whose output is the agent’s text response. The metadata dict contains thoughts, tool_calls, cost, input_tokens, and output_tokens.

Lifecycle methods:

MethodDescription
setup()Starts the ACP client subprocess (called automatically on first execute())
execute(args, env)Sends args["task"] to the agent and returns a ToolResult
cleanup()Stops the ACP client subprocess

Under the hood, ACPClient uses these JSON-RPC 2.0 methods:

RPC MethodPurpose
session/createCreate a new session with a working directory
session/sendMessageSend a message and receive response + notifications
session/forkFork an existing session for parallel work

Notifications received during sendMessage:

NotificationData
agent/messageChunkStreaming text chunk
agent/thoughtChunkReasoning/thought chunk
agent/toolCallStartTool call initiated (id, title, kind)
agent/toolCallCompleteTool call finished (output, is_error)
agent/usageUpdateCost and token usage update

ACP connects to the rest of Chimera in several ways:

  • ExternalAgentTool as BaseTool: Any loop or agent that accepts tools can use external agents. This is the primary integration path.

  • Supervisor composition: The Supervisor composition pattern can use ExternalAgentTool instances as worker agents, enabling multi-agent orchestration across process boundaries.

  • EventBus: When an ExternalAgentTool is used within a loop that has an EventBus, the framework publishes ExternalAgentStartEvent, ExternalAgentToolCallEvent, and ExternalAgentCompleteEvent:

from chimera.events.types import (
ExternalAgentStartEvent, # agent_name, task
ExternalAgentToolCallEvent, # agent_name, tool_call_id, title, status
ExternalAgentCompleteEvent, # agent_name, response_text, cost, tool_calls_count
)
from chimera.acp import (
ACPSessionConfig,
ACPToolCall,
ACPResponse,
ACPClient,
ExternalAgentTool,
)
  • Agent Spawner — in-process sub-agent dispatch
  • MCP — alternative protocol for tool/server integration
  • EventsExternalAgentStartEvent / …ToolCallEvent / …CompleteEvent