Skip to main content

Overview

ACP is the Agent Client Protocol, a JSON-RPC based protocol for communication between clients and AI coding agents. When using Broker with the ACP protocol, Broker will launch your agent binary and exchange bidirectional JSON-RPC messages over stdin / stdout. For the full specification and official TypeScript SDK: Open source agents that support ACP include OpenCode and Goose.

Getting started

To try out fully working code examples, check out the axon-broker-agents example repo. Clone the repo and run the test commands. The example will create a Devbox with OpenCode and start a “hello world” conversation by publishing an Axon event.
git clone https://github.com/runloopai/runloop-examples \
  && cd runloop-examples/axon-broker-agents \
  && uv run axon_acp_docs.py

Broker mount configuration

Create a Devbox with a broker_mount to bind an Axon stream to the ACP adapter:
{
  "type": "broker_mount",
  "axon_id": "<axon-id>",
  "protocol": "acp",
  "agent_binary": "opencode",
  "launch_args": ["acp"]
}
FieldTypeDescription
typestringMust be broker_mount
axon_idstringRequired. The Axon stream Broker reads from and writes to
protocolstringMust be acp
agent_binarystringRequired. Binary to launch for the ACP agent
launch_argsstring[]Optional. Extra arguments passed to the agent process, such as ["acp"]

How Broker uses ACP

  1. Broker launches your registered binary with arguments
  2. Your client initializes and sets up the agent for the interaction
  3. Your client starts and initiates the session by publishing ACP session events to the Axon
  4. Broker forwards those messages to your running agent
  5. Agent output streams back through Axon as <update_type> events

Send a simple message to an ACP agent

Create a Devbox with an ACP Broker mount and send a ‘hello world’ message to the agent.
1

Create Devbox with Broker

Create an Axon for communication and launch a Devbox with an ACP-compatible agent (OpenCode) mounted via Broker:
# Create Axon for agent communication
axon = await sdk.axon.create(name="acp-tutorial-axon")

# Create a Devbox with an ACP-compliant agent, OpenCode
devbox = await sdk.devbox.create(
    name="acp-tutorial-opencode-devbox",
    mounts=[
        {
            "type": "broker_mount",
            "axon_id": axon.id,
            "protocol": "acp",
            "agent_binary": "opencode",
            "launch_args": ["acp"],
        }
    ],
    launch_parameters={
        "launch_commands": ["npm i -g opencode-ai"],
    },
)
2

Initialize and Create Session

Send the ACP initialize and session/new requests to set up the agent:
await axon.publish(
    event_type="initialize",
    origin="USER_EVENT",
    source="axon_acp",
    payload=json.dumps({
        "protocolVersion": "1",
        "clientInfo": {"name": "agentflow", "version": "1.0.0"},
    }),
)

await axon.publish(
    event_type="session/new",
    origin="USER_EVENT",
    source="axon_acp",
    payload=json.dumps({
        "cwd": "/home/user",
        "mcpServers": [],
    }),
)
3

Send Prompt

Wait for the session to be created, then send a prompt to the agent:
# Wait for session/new response to get the session ID
async for ev in stream:
    if ev.event_type == "session/new" and ev.origin == "AGENT_EVENT":
        session_id = json.loads(ev.payload)["sessionId"]
        break

# Send a prompt to the agent
await axon.publish(
    event_type="session/prompt",
    origin="USER_EVENT",
    source="axon_acp",
    payload=json.dumps({
        "sessionId": session_id,
        "prompt": [{"type": "text", "text": "hi! where are you?"}],
    }),
)
4

Stream Agent Response

Subscribe to the Axon stream and print agent responses:
async for ev in stream:
    # Check for session/update events with agent_message_chunk
    if ev.event_type == "session/update" and ev.origin == "AGENT_EVENT":
        parsed = json.loads(ev.payload)
        if parsed.get("update", {}).get("sessionUpdate") == "agent_message_chunk":
            text_part = parsed.get("update", {}).get("content", {}).get("text")
            if text_part:
                print(text_part, end="", flush=True)
    if ev.event_type == "turn.completed":
        break

Cancel a turn

Often, you’ll want to interrupt an in-progress turn or conversation.
await axon.publish(
    event_type="session/cancel",
    origin="USER_EVENT",
    source="axon_acp",
    payload=json.dumps({
        "sessionId": session_id,
    }),
)

Handling agent plans and permissions

ACP agents can propose plans for structured, multi-step work. Agents also request permissions for actions like file access or command execution. Currently, Broker automatically accepts all ACP permission requests, allowing agents to proceed with their planned operations.

Building a complete integration

The examples above cover the basics of launching an ACP agent and exchanging messages. To build a production-ready integration, you should become familiar with the full ACP state machine — understanding how sessions transition between states like idle, working, and completed will help you handle edge cases and build reliable orchestration logic. ACP also supports advanced features beyond simple prompting, including: All of these capabilities are fully supported over ACP + Broker. See the ACP specification for complete protocol details.