Claude Opus 5.5

agents-0-24-0-6-b

Claude Code's read-only tools, web search on, ludion sync on

Question

How do I use Cap'n Web RPC with AgentClient in the Cloudflare Agents SDK?

Answer key

A correct answer says
`useAgent` and `AgentClient` take a `transport` option: "cf-websocket" (default, hibernating) or "capnweb" for a Cap'n Web session with native RPC stubs.
The stale answer
useAgent/AgentClient always use the JSON-over-WebSocket protocol; there is no transport choice.

The change's lesson

Answer

To use Cap'n Web, pass `transport: "capnweb"` when you create the client, e.g. `new AgentClient({ agent: "MyAgent", name: "room-1", transport: "capnweb" })`. The same option works on `useAgent`. If you leave it out, the client uses `"cf-websocket"`, a hibernating WebSocket where `call()` sends JSON `rpc` frames.

With `"capnweb"`, protocol frames travel over a Cap'n Web session. The host's `callables` (an `RpcTarget` set in the WebSockets capability options) are served as native Cap'n Web methods on the session root. That means `client.call()` and `client.stub.method()` invoke them directly, calls can pipeline, a returned `ReadableStream` streams, and a returned `RpcTarget` comes back as a live stub.

There are three caveats, all from the type definitions in your installed `agents` 0.27.0 (`node_modules/agents/dist/client-*.d.ts`, `options-*.d.ts`):
- The transport is marked **experimental**. It was added in agents 0.24.0.
- The Durable Object stays in memory, rather than hibernating, while a capnweb connection is open.
- A plain `Agent` answers its own decorated `@callable` methods over the JSON wire and doesn't set `callables`. You only get the native Cap'n Web method behaviour when the host supplies a `callables` `RpcTarget`.

Answering cost $0.14.

Grade

correct

The judge's reason: It states that useAgent/AgentClient take a transport option with "cf-websocket" as the hibernating default and "capnweb" for a Cap'n Web session with native RPC stubs, and it does not present the stale no-choice behavior as current.

The judge's log

Session log

What the agent wrote, the tools it called, and what they returned, from docs/bench/2026-10-11-done3/runs/B-project-sync/agents-0-24-0-6-b.jsonl. Thinking and the session's settings are left out. The raw log

  1. Tool call: Grep

    {
      "pattern": "capnweb",
      "path": "C:\\Users\\haya0\\AppData\\Local\\Temp\\ludion-bench-IAnkyG\\work\\node_modules\\agents\\dist",
      "glob": "*.d.ts",
      "output_mode": "content",
      "head_limit": 30
    }
  2. Tool output

    node_modules\agents\dist\client-DS3Dz9l0.d.ts:19://#region src/websockets/capnweb-socket.d.ts
    node_modules\agents\dist\client-DS3Dz9l0.d.ts:111:     * `"capnweb"` carries protocol frames over a Cap'n Web session whose
    node_modules\agents\dist\client-DS3Dz9l0.d.ts:114:     * The Durable Object stays in memory while a capnweb connection is open.
    node_modules\agents\dist\client-DS3Dz9l0.d.ts:115:     * @experimental The `"capnweb"` transport is experimental.
    node_modules\agents\dist\options-pwTNq9z6.d.ts:70:   * `capnweb` wire they are native Cap'n Web methods on the session root:
    node_modules\agents\dist\index-Ib_4dwOo.d.ts:39: * - **capnweb** (`?__agents_transport=capnweb`): protocol frames through
    node_modules\agents\dist\react.d.ts:81:     * `"capnweb"` carries protocol frames over a Cap'n Web session whose
    node_modules\agents\dist\react.d.ts:84:     * The Durable Object stays in memory while a capnweb connection is open.
    node_modules\agents\dist\react.d.ts:86:     * @experimental The `"capnweb"` transport is experimental.
    node_modules\agents\dist\transport-protocol-ZTew5Wso.d.ts:9:type AgentTransport = "cf-websocket" | "capnweb";
    node_modules\agents\dist\transport-protocol-ZTew5Wso.d.ts:12:declare const CAPNWEB_TRANSPORT_VALUE = "capnweb";
  3. Tool call: Read

    {
      "file_path": "C:\\Users\\haya0\\AppData\\Local\\Temp\\ludion-bench-IAnkyG\\work\\node_modules\\agents\\dist\\client-DS3Dz9l0.d.ts",
      "offset": 95,
      "limit": 40
    }
  4. Tool output

    95	  takeFinalClose: () => boolean;
    96	};
    97	type TerminalReconnectOptions = {
    98	  shouldReconnectOnClose?: (event: CloseEvent) => boolean;
    99	};
    100	/**
    101	 * Options for creating an AgentClient
    102	 */
    103	type AgentClientOptions<State = unknown> = Omit<
    104	  PartySocketOptions,
    105	  "party" | "room"
    106	> &
    107	  TerminalReconnectOptions & {
    108	    /**
    109	     * Wire the connection travels on. `"cf-websocket"` (default) is a
    110	     * hibernating WebSocket where `call()` sends JSON `rpc` frames.
    111	     * `"capnweb"` carries protocol frames over a Cap'n Web session whose
    112	     * root also serves the host's `callables` natively, so `call()` and
    113	     * `stub` invoke them directly and an `RpcTarget` result is a live stub.
    114	     * The Durable Object stays in memory while a capnweb connection is open.
    115	     * @experimental The `"capnweb"` transport is experimental.
    116	     */
    117	    transport?: AgentTransport /** Name of the agent to connect to (ignored if basePath is set) */;
    118	    agent: string /** Name of the specific Agent instance (ignored if basePath is set) */;
    119	    name?: string;
    120	    /**
    121	     * Full URL path - bypasses agent/name URL construction.
    122	     * When set, the client connects to this path directly.
    123	     * Server must handle routing manually (e.g., with getAgentByName + fetch).
    124	     * @example
    125	     * // Client connects to /user, server routes based on session
    126	     * useAgent({ agent: "UserAgent", basePath: "user" })
    127	     */
    128	    basePath?: string /** Called when the Agent's state is updated */;
    129	    onStateUpdate?: (
    130	      state: State,
    131	      source: "server" | "client"
    132	    ) => void /** Called when a state update fails (e.g., connection is readonly) */;
    133	    onStateUpdateError?: (error: string) => void;
    134	    /**
  5. Tool call: Read

    {
      "file_path": "C:\\Users\\haya0\\AppData\\Local\\Temp\\ludion-bench-IAnkyG\\work\\node_modules\\agents\\dist\\options-pwTNq9z6.d.ts",
      "offset": 55,
      "limit": 35
    }
  6. Tool output

    55	 * Configuration for the WebSockets capability.
    56	 *
    57	 * @experimental The API surface may change before stabilizing.
    58	 */
    59	interface WebSocketsOptions {
    60	  /**
    61	   * Connection handlers for WebSocket clients. The capability accepts and
    62	   * tracks every WebSocket upgrade either way; handlers add behavior on
    63	   * connect, message, close and error.
    64	   */
    65	  readonly handlers?: WebSocketHandlers;
    66	  /**
    67	   * An `RpcTarget` whose prototype methods are the host's complete remote
    68	   * interface, reached through `useAgent().call` and `.stub`. On the
    69	   * `cf-websocket` wire they are answered as JSON `rpc` frames. On the
    70	   * `capnweb` wire they are native Cap'n Web methods on the session root:
    71	   * an `RpcTarget` result becomes a live stub, a `ReadableStream` streams,
    72	   * and calls pipeline. Methods run through the host invocation boundary
    73	   * with the calling connection in scope. `Agent` answers its own
    74	   * decorated methods on the JSON wire and does not set this.
    75	   */
    76	  readonly callables?: RpcTarget;
    77	  /**
    78	   * Whether a new connection gets the connect-time protocol frames —
    79	   * identity (`cf_agent_identity`), then the current state when `state`
    80	   * is set — and whether protocol frames reach it at all.
    81	   *
    82	   * - `true` (default): every connection.
    83	   * - a function: decided per connection at accept time. `false` marks
    84	   *   the connection no-protocol: it gets no protocol text frames, on
    85	   *   connect or via `broadcastState()`, but can still send and receive
    86	   *   ordinary messages and use callables. For binary-only clients.
    87	   * - `false`: the host drives the connect sequence itself with
    88	   *   `sendConnectFrames()` (or `sendIdentity()` and `sendState()`
    89	   *   separately), and applies client state frames
  7. Agent

    To use Cap'n Web, pass `transport: "capnweb"` when you create the client, e.g. `new AgentClient({ agent: "MyAgent", name: "room-1", transport: "capnweb" })`. The same option works on `useAgent`. If you leave it out, the client uses `"cf-websocket"`, a hibernating WebSocket where `call()` sends JSON `rpc` frames.
    
    With `"capnweb"`, protocol frames travel over a Cap'n Web session. The host's `callables` (an `RpcTarget` set in the WebSockets capability options) are served as native Cap'n Web methods on the session root. That means `client.call()` and `client.stub.method()` invoke them directly, calls can pipeline, a returned `ReadableStream` streams, and a returned `RpcTarget` comes back as a live stub.
    
    There are three caveats, all from the type definitions in your installed `agents` 0.27.0 (`node_modules/agents/dist/client-*.d.ts`, `options-*.d.ts`):
    - The transport is marked **experimental**. It was added in agents 0.24.0.
    - The Durable Object stays in memory, rather than hibernating, while a capnweb connection is open.
    - A plain `Agent` answers its own decorated `@callable` methods over the JSON wire and doesn't set `callables`. You only get the native Cap'n Web method behaviour when the host supplies a `callables` `RpcTarget`.