[DOCS] Headless stream-json control protocol does not document `set_model` validation or error responses

Open 💬 0 comments Opened Jul 15, 2026 by coygeek

Documentation Type

Missing documentation (feature not documented)

Documentation Location

https://code.claude.com/docs/en/headless

Section/Topic

The stream-json input and control-message protocol for bidirectional headless sessions, including model changes sent through control_request messages. The related --input-format stream-json entry in the CLI reference and the Agent SDK setModel() documentation should cross-reference the same contract.

Current Documentation

The headless guide describes stream-json only as an output format:

stream-json: newline-delimited JSON for real-time streaming

It then says:

Use --output-format stream-json with --verbose and --include-partial-messages to receive tokens as they're generated. Each line is a JSON object representing an event:

The CLI reference documents the input flag only as:

--input-format — Specify input format for print mode (options: text, stream-json)

The Agent SDK TypeScript reference documents the related high-level operation as:

setModel() | Changes the model (only available in streaming input mode)

None of these pages documents the control_request envelope, the set_model request payload, the accepted type for its model value, or the error response returned when that payload is invalid.

What's Wrong or Missing?

Claude Code v2.1.208 fixed a user-visible failure mode in headless stream-json integrations: when a control_request carries a non-string set_model payload, the CLI now answers with an error response instead of leaving the session hanging permanently.

The current documentation exposes both stream-json input and mid-session model changes, but gives protocol clients no way to construct or validate this control request and no guidance on handling its error response. An integration that sends a malformed model value cannot distinguish a rejected request from a stalled session, and a custom stream-json host cannot rely on the documented output descriptions to implement the control channel correctly.

Suggested Improvement

Add a bidirectional stream-json control-message subsection to the headless guide, and link to it from the CLI reference and Agent SDK references. Document:

  1. The exact control_request and control_response envelope and the request identifier that correlates them.
  2. The set_model request shape, including the accepted model-value type and how resetting to the default is represented.
  3. The structured error response produced when set_model receives a non-string value, including whether the session remains usable for subsequent input.
  4. A minimal newline-delimited JSON example and guidance to treat protocol errors as request failures rather than waiting for another stream event.

Add a version note that this error-response behavior requires Claude Code v2.1.208 or later.

Impact

Medium - Makes feature difficult to understand

Additional Context

Affected Pages:

| Page | Context |
|------|---------|
| https://code.claude.com/docs/en/headless | Stream-json output is documented, but the input/control protocol is not |
| https://code.claude.com/docs/en/cli-reference | --input-format stream-json is listed without the input message schema or control-request errors |
| https://code.claude.com/docs/en/agent-sdk/typescript | setModel() and the control_request envelope are documented separately, without the set_model payload validation contract |
| https://code.claude.com/docs/en/agent-sdk/python | set_model(model) is documented without the corresponding protocol error behavior |

Total scope: 4 pages affected

The behavior changed in v2.1.208. The documentation should distinguish the public SDK setter APIs from the lower-level stream-json control protocol used by custom headless and SDK hosts.

View original on GitHub ↗