Skip to content

Feature request: per-turn sendReasoning control on Think #1417

@cgrdavies

Description

@cgrdavies

Gap

Think.toUIMessageStream(...) is called with no options on both the WebSocket path (_streamResult) and the sub-agent chat() path, so subclasses have no override point for the AI SDK's sendReasoning flag. Reasoning chunks reach clients because the SDK default is true, but that's an implicit dependency on an SDK default and there's no scoped control for subclasses that want to suppress reasoning, or vary it per turn.

Proposal

Two-level control, matching how the rest of TurnConfig flows over Think's class-field defaults:

  • sendReasoning: boolean = true on Think — subclass-wide default.
  • Optional sendReasoning?: boolean on TurnConfig returned from beforeTurn — per-turn override that wins for that turn only.

The resolved value (config.sendReasoning ?? this.sendReasoning) snapshots in a closure that wraps the StreamableResult returned from _runInferenceLoop, so neither stream path re-reads this.sendReasoning and the instance field can't drift between turns.

// Subclass-wide:
export class MyAgent extends Think<Env> {
  override sendReasoning = false;
}

// Per-turn:
override beforeTurn(ctx: TurnContext) {
  return { sendReasoning: ctx.continuation };
}

Use case

Running Claude 4.6 with adaptive thinking on a chat surface that streams both internal tool-use continuations and the final user-facing assistant message over the same WebSocket. We want reasoning visible on the final turn and hidden on the internal loop turns. Currently only "always on" or "always off" is expressible.

Reference implementation

A branch with the change is at https://github.com/cgrdavies/agents/tree/feat/think-send-reasoning. It includes:

  • The two-level knob + per-turn snapshot in _runInferenceLoop
  • Four test cases in packages/think/src/tests/hooks.test.ts covering default behavior, instance-field override, and both directions of TurnConfig precedence
  • Changeset (@cloudflare/think: patch)
  • README + docs/think/index.md Configuration tables updated

Local verification: 274/274 tests passing in packages/think; oxfmt --check, oxlint, and tsc --noEmit all clean on the modified files; package builds clean. Happy to revise the API shape if a different design fits the package better.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions