> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runloop.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Broker

> Broker is the bridge between Axon event streams and agent processes running in Devboxes

## Overview

Broker sits between an Axon and an agent process running inside a Devbox. The Axon is the system of record and Broker is the bridge that turns stream events into serialized agent work - managing the agent lifecycle, forwarding events, and recording output back to the stream.

<CardGroup cols={3}>
  <Card title="Start an ACP Agent" icon="play" href="/docs/axons/broker/acp">
    Set up any agent that implements the Agent Client Protocol.
  </Card>

  <Card title="Launch and run Claude" icon="zap" href="/docs/axons/broker/claude">
    See how broker can launch and interface directly with Claude Code CLI.
  </Card>

  <Card title="Understand the Event Flow" icon="lightbulb" href="#event-flow">
    Understand how events move between Axon, Broker, and your agent.
  </Card>
</CardGroup>

Broker's job is to:

* start and manage the agent process
* receive user and external events from the Axon stream
* forward them to the agent through the configured protocol adapter
* publish agent output back to the same Axon stream
* enforce serial turn execution so only one turn runs at a time

This separation is what lets Axon act as the shared event bus while agents remain isolated behind a stable event interface.

## Supported Protocols

Runloop currently supports the following Broker protocols:

* [`acp`](/docs/axons/broker/acp) for agents that implement the Agent Client Protocol over stdin/stdout
* [`claude_json`](/docs/axons/broker/claude) for Claude Code CLI in streaming JSON Lines mode

Configure a `broker_mount` on your Devbox to select the protocol adapter and attach Broker to an Axon stream.

## Event Flow

```mermaid theme={null}
sequenceDiagram
    participant Client as External Client
    participant Axon as Axon Event Bus
    participant Devbox as Devbox (Broker + Agent)

    Client->>Axon: publish event
    Axon->>Devbox: inbound event
    Devbox->>Devbox: Broker forwards to Agent
    Devbox-->>Axon: Agent response events
    Axon-->>Client: SSE stream
    Devbox-->>Axon: turn.completed
```

Broker owns the turn lifecycle:

1. It reads inbound events from Axon.
2. It starts a turn when it receives a user or external event.
3. While that turn is running, additional inbound turn-starting events are queued.
4. It publishes turn output back into Axon as structured events.
5. When the turn completes, it moves back to idle and processes the next queued event.

## Responsibilities

### Message Forwarding

Broker consumes inbound events from Axon and forwards them to the attached agent. The `event_type` indicates the protocol method (e.g., `query` for Claude, `session/prompt` for ACP).

### Turn Serialization

Broker enforces one active turn at a time. This prevents overlapping agent turns and gives downstream consumers a clear ordered stream of turn output.

### Event Publishing

Broker republishes agent and turn lifecycle output back into Axon so clients can subscribe to the same stream they published into.

Each agent will publish events native to their Protocol schema. Separately, broker sends a set of standardized events:

| Event Type       | Origin         | Description           |
| ---------------- | -------------- | --------------------- |
| `turn.started`   | `SYSTEM_EVENT` | A new turn has begun  |
| `turn.completed` | `SYSTEM_EVENT` | The turn is completed |

### Loop Prevention

Broker ignores agent- and system-originated events when reading from Axon so it does not re-consume its own output.

### Protocol Forwarding

Broker is protocol-agnostic. It launches agent binaries, understands each protocol to manage turn lifecycle, and forwards protocol-specific messages between the Axon stream and the agent process. Events published to and from Axon remain protocol-specific—Broker does not normalize them into a common schema. Clients should send and receive events in the format defined by the agent's protocol.

## Suspend and Resume

<Tip>
  Agents can sleep when they're unused and wake up on demand. They recover their state automatically — no manual lifecycle management required.
</Tip>

Any Devbox can be configured to [suspend after a period of inactivity](/docs/devboxes/lifecycle#suspend_resume) and resume on demand. When combined with Broker, the Devbox automatically resumes when a new Axon event arrives, and the agent picks up where it left off.

### Configuration

Configure suspend and resume behavior in `launch_parameters.lifecycle` when creating the Devbox with `axon_event` set as a `resume_trigger`:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const devbox = await runloop.devbox.create({
    blueprint_name: "runloop/agents",
    mounts: [
      {
        type: "broker_mount",
        axon_id: axon.id,
        protocol: "claude_json",
        agent_binary: "claude",
      },
    ],
    launch_parameters: {
      launch_commands: ["npm install"],
      lifecycle: {
        after_idle: {
          idle_time_seconds: 60,
          on_idle: "suspend",
        },
        resume_triggers: {
          axon_event: true,
        },
      },
    },
  });
  ```

  ```python Python theme={null}
  devbox = await runloop.devbox.create(
      blueprint_name="runloop/agents",
      mounts=[
          {
              "type": "broker_mount",
              "axon_id": axon.id,
              "protocol": "claude_json",
              "agent_binary": "claude",
          },
      ],
      launch_parameters={
          "launch_commands": ["npm install"],
          "lifecycle": {
              "after_idle": {
                  "idle_time_seconds": 60,
                  "on_idle": "suspend",
              },
              "resume_triggers": {
                  "axon_event": True,
              },
          },
      },
  )
  ```
</CodeGroup>

* **`after_idle.idle_time_seconds`** — how long (in seconds) Broker waits after the last turn completes before suspending the Devbox.
* **`after_idle.on_idle`** — set to `"suspend"` to suspend the Devbox when the idle timer fires.
* **`resume_triggers.axon_event`** — set to `true` so the Devbox automatically resumes when a new event is published to the Axon.

### Transparent to Clients

Suspend and resume is invisible to event publishers. You can keep sending events to the Axon without knowing whether the Devbox is currently running or suspended:

1. A new event arrives on the Axon while the Devbox is suspended.
2. Runloop automatically resumes the Devbox.
3. Broker picks up the queued event and starts a new turn.
4. The agent continues where it left off — same disk state, same session history.

Your client code does not need to check Devbox status or call resume manually. It just publishes events and consumes responses as usual.

### DevboxLifecycle timeline events

If you want to reflect suspend and resume state in your UI, subscribe to `DevboxLifecycle` timeline events. These are `SYSTEM_EVENT` origin events that fire when the Devbox transitions between states:

```typescript theme={null}
import { isDevboxLifecycleEvent } from "@runloop/remote-agents-sdk/claude";

conn.onTimelineEvent((event) => {
  if (isDevboxLifecycleEvent(event)) {
    // event.data contains the lifecycle state: running, suspended, resuming, etc.
    console.log("Devbox state:", event.data);
  }
});
```

This lets you show loading indicators or status badges while the Devbox resumes, without changing your core event-handling logic.

## Related Documentation

* [Axons Overview](/docs/axons/overview) — Learn how Axons sequence and expose event streams
* [Devbox Overview](/docs/devboxes/overview) — Learn where agents and Broker run
* [Agent Gateways](/docs/devboxes/agent-gateways) — Securely proxy outbound API requests from a Devbox
