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

# Reasoning models

> Choose protocol-specific reasoning controls, validate final output, and preserve replayable state.

## Reasoning strength and visible output are separate

Reasoning models may perform additional computation before answering. Reasoning strength, returned summaries, and final-answer length are separate controls. No visible reasoning text does not prove that no reasoning occurred. A public summary is not the model's complete internal reasoning trace.

| API | Recognized representation | Boundary |
| - | - | - |
| Chat Completions | `reasoning_effort`; also an OpenRouter-style `reasoning` object | Native forwarding and conversion differ; avoid conflicting settings |
| Responses | `reasoning.effort`, `summary`, `mode`, `context` | Accepted values vary by model; the last two are conditional extensions |
| Claude | `thinking`, `output_config` | Native controls; budgets, modes, signatures, and tool loops require target support |
| Gemini | Thinking settings within native generation configuration | Chat fields are not interchangeable with Gemini-native fields |

The converter recognizes `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`; this is not an allowed-value list for every model. Some native paths preserve upstream fields, while conversion paths normalize or reject them. Model-name modifiers can override request settings, with mapped-name modifiers taking precedence over public-name modifiers. Use deployment-published IDs without inventing suffixes.

Chat's nested `reasoning` can express `enabled`, `effort`, `max_tokens`, and `exclude`. `exclude` controls reasoning visibility rather than disabling reasoning. The object is converted according to the channel dialect; exact field passthrough is not guaranteed. Responses reasoning uses a different structure.

## Budgets, streams, and failures

Reserve sufficient input and output capacity for the model. Some models count reasoning and visible output within the generation budget. Avoid combining `max_tokens`, `max_completion_tokens`, or unsupported sampling settings. `finish_reason=length`, Responses `status=incomplete`, or reasoning without final text is not a completed answer.

Handle reasoning, tool arguments, summaries, and text events separately in streams; do not treat reasoning deltas as the final reply. Tool calls require a complete loop; see [streaming tools](/en/guides/streaming-tools). Applications must not decrypt `encrypted_content` or rewrite Claude signatures.

## Runnable: single-turn Chat or stateless Responses continuation

Use the [REST runtime](/en/guides/http-runtime), keeping `examples/reasoning.mjs` and `http-client.mjs` together. Default Responses mode sends two requests with `store: false`, replaying all first-turn output in order. This mode requires a model and native path supporting replayable reasoning items. If a reasoning item lacks usable encrypted state, the example stops instead of silently discarding it. Completed text without any reasoning items is also accepted.

```sh theme={null}
export API_ROOT_URL='https://gateway.example.com'
export API_KEY='YOUR_API_KEY'
export API_MODEL='YOUR_REASONING_MODEL_ID'
export API_REASONING_EFFORT='medium'
export API_REASONING_MODE='responses'
node examples/reasoning.mjs
```

After selecting a Chat-capable model, switch to single-turn mode:

```sh theme={null}
API_REASONING_MODE=chat node examples/reasoning.mjs
```

```javascript theme={null}
import { requestJSON } from './http-client.mjs';

try {
  const model = process.env.API_MODEL;
  const mode = process.env.API_REASONING_MODE || 'responses';
  const effort = process.env.API_REASONING_EFFORT || 'medium';
  if (!model?.trim() || !['chat', 'responses'].includes(mode)
    || !['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'].includes(effort)) {
    throw new Error('Invalid model, protocol, or effort.');
  }
  const history = [{ role: 'user', content: 'Find the smallest positive integer divisible by both 6 and 8.' }];
  const answers = [];
  for (let turn = 0; turn < (mode === 'chat' ? 1 : 2); turn++) {
    const result = await requestJSON(mode === 'chat' ? '/v1/chat/completions' : '/v1/responses',
      mode === 'chat' ? { model, messages: history, reasoning_effort: effort }
        : { model, input: history, reasoning: { effort }, store: false,
            include: ['reasoning.encrypted_content'], instructions: 'Return a short final answer.' });
    if (mode === 'chat') {
      const choice = result.choices?.[0];
      const message = choice?.message;
      if (!Array.isArray(result.choices) || result.choices.length !== 1 || choice?.index !== 0
        || choice.finish_reason !== 'stop' || message?.role !== 'assistant'
        || message.refusal != null || message.tool_calls != null || message.function_call != null
        || typeof message.content !== 'string' || !message.content.trim()) {
        throw new Error('No complete final text.');
      }
      answers.push(message.content);
      continue;
    }
    if (result.status !== 'completed' || !Array.isArray(result.output) || !result.output.length) {
      throw new Error('Incomplete response.');
    }
    const text = [];
    for (const item of result.output) {
      if (item?.type === 'reasoning') {
        // This stateless replay example requires opaque state whenever a reasoning item exists.
        if (typeof item.encrypted_content !== 'string' || !item.encrypted_content.trim()) {
          throw new Error('Reasoning state is not replayable by this example.');
        }
      } else if (item?.type === 'message' && item.role === 'assistant' && item.status === 'completed'
        && Array.isArray(item.content) && item.content.length) {
        for (const part of item.content) {
          if (part?.type !== 'output_text' || typeof part.text !== 'string') throw new Error('Unexpected content.');
          text.push(part.text);
        }
      } else { throw new Error('Unexpected output item.'); }
    }
    if (!text.join('').trim()) throw new Error('No final text.');
    answers.push(text.join(''));
    // Preserve complete items and unknown metadata, including phase; never log encrypted state.
    history.push(...result.output, { role: 'user', content: 'Now find the smallest positive multiple also divisible by 5.' });
  }
  console.log(JSON.stringify({ answers }));
} catch {
  console.error('Reasoning example failed. Check model support, replayable state, and completion status. No automatic retry.');
  process.exitCode = 1;
}
```

The script does not set reasoning budgets or model-specific sampling parameters. Each request has a 60-second timeout and 1 MiB response limit, without automatic retries. Answers are printed only after all requests complete. It preserves `phase` and unknown metadata without printing reasoning text, summaries, or ciphertext. `include` is a compatibility request, not a guarantee that every channel returns encrypted state; `store: false` does not guarantee deployment-wide zero retention.

## Acceptance sequence

Verify supported effort values and actual outgoing parameters first, then completion status, tool loops, and second-turn state replay. Distinguish missing reasoning-token usage from zero; it is not answer length and cannot alone establish quality or cost. Revalidate replayability after model switching, protocol conversion, or compaction.

Sources: revision `30a6d88a4`, request DTOs, `relaykit/relayconvert/reasoning/intent.go`, `relay/channel/openai/adaptor.go`, and `relay/helper/reasoning_suffix.go`. References: [OpenRouter reasoning topic](https://openrouter.ai/docs/guides/best-practices/reasoning-tokens) and [OpenAI reasoning documentation](https://developers.openai.com/api/docs/guides/reasoning).

[Chat API](/en/api-reference/chat-completions) · [Responses API](/en/api-reference/responses) · [Context management](/en/guides/context-management)

[阅读中文](/zh/guides/reasoning-models)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.