> ## 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.

# Claude JSON Protocol

> Use the Claude JSON protocol to connect Broker to Claude Code CLI

## Overview

The Claude adapter connects Broker to a
[Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) subprocess
running inside your Devbox. It launches Claude Code with
`--output-format stream-json` and forwards streaming JSONL messages between
Broker and the CLI.

For the full wire protocol specification, see the [Protocol Spec](/docs/axons/broker/claude-protocol).

## Getting started

To try out fully working code examples, check out the [axon-broker-agents example repo](https://github.com/runloopai/runloop-examples/tree/main/axon-broker-agents).

Clone the repo and run the test commands. The example will create a Devbox with Claude and start a "hello world" conversation by publishing an Axon event.

```bash theme={null}
git clone https://github.com/runloopai/runloop-examples \
  && cd runloop-examples/axon-broker-agents \
  && bun install \
  && bun run axon_claude_docs.ts
```

## Broker mount configuration

```json theme={null}
{
  "type": "broker_mount",
  "axon_id": "<axon-id>",
  "protocol": "claude_json"
}
```

| Field      | Type     | Description                                               |
| ---------- | -------- | --------------------------------------------------------- |
| `type`     | `string` | Must be `broker_mount`                                    |
| `axon_id`  | `string` | Required. The Axon stream Broker reads from and writes to |
| `protocol` | `string` | Must be `claude_json`                                     |

## How Broker uses Claude JSONL

* Broker launches Claude Code with `--output-format stream-json` when the Devbox starts
* Claude initializes and sets up the session
* Publish `query` to the Axon to start a turn
* Broker translates that event into Claude's `user` JSONL input
* Claude output is republished to Axon. Event `event_type` represents the [Claude message type](/docs/axons/broker/claude-protocol#output-types-claude--sdk) to deserialize.

## Send a simple message to Claude

Create a Devbox with a Claude Broker mount and send a 'hello world' message to Claude.

<Steps>
  <Step title="Create Devbox with Broker">
    Create an Axon for communication and launch a Devbox with Claude Code mounted via Broker:

    ```typescript theme={null}
    // Create Axon for agent communication
    const axon = await sdk.axon.create({ name: "claude-session" });

    // Create a Devbox with Claude Code agent
    const devbox = await sdk.devbox.create({
      mounts: [
        {
          type: "broker_mount",
          axon_id: axon.id,
          protocol: "claude_json",
          launch_args: [],
        },
      ],
      launch_parameters: {
        launch_commands: [
          'curl -fsSL https://claude.ai/install.sh | bash && echo \'export PATH="$HOME/.local/bin:$PATH"\' >> ~/.bash_profile',
        ],
      },
      environment_variables: {
        PATH: "/home/user/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY || "",
      },
    });
    ```
  </Step>

  <Step title="Connect to Claude">
    Open the client connection and complete the handshake before calling `send()` in the next step so response listeners can be registered first:

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

    const conn = new ClaudeAxonConnection(axon, devbox);

    await conn.connect();
    await conn.initialize();
    ```
  </Step>

  <Step title="Print Assistant Response">
    Subscribe to the Axon stream and print agent responses:

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

    conn.onTimelineEvent((event) => {
      if (isClaudeAssistantEvent(event)) {
        for (const block of event.data.message.content) {
          if (block.type === "text") {
            process.stdout.write(block.text);
          }
        }
      }

      if (isClaudeResultEvent(event)) {
        console.log(`\nTurn complete: ${event.data.subtype}`);
      }
    });

    await conn.send(userPrompt);
    ```
  </Step>
</Steps>

## Handling control requests from Claude

During a session, Claude may ask the user a question or request permission
before taking an action - these arrive as control request events on the Axon
stream. When you receive one, you can either prompt your user for input or
respond automatically by publishing a control response.

<CodeGroup>
  ```json Control Request theme={null}
  {
    "type": "control_request",
    "request_id": "b0225af1-13c1-4897-9197-49a9f776fe20",
    "request": {
      "subtype": "can_use_tool",
      "tool_name": "AskUserQuestion",
      "input": {
        "questions": [
          {
            "header": "Fave foods",
            "multiSelect": true,
            "options": [
              { "label": "Pizza", "description": "A classic choice — hard to go wrong" },
              { "label": "Sushi", "description": "Fresh fish and rice, endless variety" },
              { "label": "Tacos", "description": "Versatile, flavorful, always a good time" },
              { "label": "Pasta", "description": "Comfort food at its finest" }
            ],
            "question": "What are your favorite foods?"
          }
        ]
      },
      "permission_suggestions": [],
      "tool_use_id": "toolu_019EVn3FjnenHfCsPFhFLFAR"
    }
  }
  ```

  ```json Control Response theme={null}
  {
    "type": "control_response",
    "response": {
      "subtype": "success",
      "request_id": "b0225af1-13c1-4897-9197-49a9f776fe20",
      "response": {
        "behavior": "allow",
        "updatedInput": {
          "questions": [
            {
              "header": "Fave foods",
              "question": "What are your favorite foods?",
              "multiSelect": true,
              "options": [
                { "label": "Pizza", "description": "A classic choice — hard to go wrong" },
                { "label": "Sushi", "description": "Fresh fish and rice, endless variety" },
                { "label": "Tacos", "description": "Versatile, flavorful, always a good time" },
                { "label": "Pasta", "description": "Comfort food at its finest" }
              ]
            }
          ],
          "answers": {
            "What are your favorite foods?": "Sushi"
          }
        }
      }
    }
  }
  ```
</CodeGroup>

<Note>
  There are many types of control responses for responding to Claude. See the [Protocol Spec](/docs/axons/broker/claude-protocol) for complete details on all available response types and structures.
</Note>

## Interrupt a turn

Stop Claude's current response by sending an interrupt control request:

```typescript theme={null}
await axon.publish({
  event_type: "control_request",
  origin: "USER_EVENT",
  source: "axon_claude",
  payload: JSON.stringify({
    type: "control_request",
    request_id: crypto.randomUUID(),
    request: {
      subtype: "interrupt",
    },
  }),
});
```

## Building a complete integration

The examples above cover basic messaging and interrupts. To build a production-ready integration, you should become familiar with the full set of Claude control request and response types — these are the building blocks for handling every interaction Claude can initiate during a session.

Claude may emit control requests for a variety of reasons, including:

* **Permission requests** — Claude asks for approval before executing commands, writing files, or taking other actions
* **User questions** — Claude asks the user for input or clarification
* **MCP server interactions** — Claude requests access to MCP tool servers

Each control request type has a corresponding response structure that your application needs to handle. You can respond automatically (e.g., auto-approving safe commands) or route requests to a human for review.

See the [Claude JSONL Protocol Spec](/docs/axons/broker/claude-protocol) for the complete reference on all control request and response types, output message formats, and session lifecycle events.
