Reasoning

Access the inner thoughts and chain-of-thought process of advanced reasoning models like DeepSeek R1 and OpenAI o1/o3.

Added in v1.7.0

Table of contents

  1. Configuring Thinking v1.7.0+
    1. Setting Effort Level
    2. Per-Request Configuration
    3. Claude Models
  2. Accessing Thinking Results v1.7.0+
    1. Streaming Thinking
  3. Backward Compatibility (Deprecated)
  4. Supported Capabilities

NodeLLM provides a unified way to access the “thinking” or “reasoning” process of models like DeepSeek R1, OpenAI o1/o3, and Claude 3.7/4. Many models now expose their internal chain of thought or allow configuring the amount of effort spent on reasoning.


Configuring Thinking v1.7.0+

You can control the reasoning behavior using the .withThinking() or .withEffort() methods. This is particularly useful for models like o3 or claude-sonnet-5.

Setting Effort Level

Effort levels (low, medium, high) allow you to balance between speed/cost and reasoning depth. Newer models also accept "xhigh" and "max". Pass "none" to explicitly disable thinking on models that support turning it off.

import { NodeLLM } from "@node-llm/core";

const chat = NodeLLM.chat("o3")
  .withEffort("high"); // Options: "low", "medium", "high", "xhigh", "max", "none"

const response = await chat.ask("Solve this complex architecture problem...");

Per-Request Configuration

If you prefer to be stateless or set configuration only for a specific request, you can pass the thinking configuration directly to ask() or stream().

const response = await chat.ask("Solve this puzzle", {
  thinking: { budget: 16000 }
});

Claude Models

Claude generations take thinking settings in one of two ways, and NodeLLM picks the request shape from the model registry:

  • Adaptive thinking (Claude Opus 4.7 and later, Sonnet 5 and later, Fable): the model decides how much to think. Set an effort; these models reject a fixed budget with a 400 error.
  • Budget thinking (Sonnet 4.5, Haiku 4.5, Opus 4.5, Opus 4.6, Sonnet 4.6): set a budget in tokens. On these models effort alone is not sent; pass a budget with it.

Newer Claude models hide their thinking text by default. Pass display: "summarized" to get a readable summary in response.thinking.text. Thinking is billed the same either way.

const chat = NodeLLM.chat("claude-sonnet-5")
  .withThinking({ effort: "high", display: "summarized" });

// Budget generations
const older = NodeLLM.chat("claude-haiku-4-5")
  .withThinking({ budget: 8000 });

Adaptive thinking may skip thinking on simple prompts, so response.thinking can be empty even when it is enabled. With a forced tool choice (withToolChoice("required") or a named tool), the thinking block is left out because Claude rejects the two together; the effort level is still sent.


Accessing Thinking Results v1.7.0+

The results of thinking are available via the .thinking property on the response object. This unified object contains the text, tokens used, and any cryptographic signatures provided by the model.

const response = await chat.ask("Prove that the square root of 2 is irrational.");

// High-level access via response.thinking
if (response.thinking) {
  console.log("Thought Process:", response.thinking.text);
  console.log("Tokens Spent:", response.thinking.tokens);
  console.log("Verification Signature:", response.thinking.signature);
}

// Show the final answer
console.log("Answer:", response.content);

Streaming Thinking

When using .stream(), thinking content is emitted in chunks. You can capture it by checking chunk.thinking.

const chat = NodeLLM.chat("deepseek-reasoner");

for await (const chunk of chat.stream("Explain quantum entanglement")) {
  if (chunk.thinking?.text) {
    process.stdout.write(`[Thinking] ${chunk.thinking.text}`);
  }
  if (chunk.content) {
    process.stdout.write(chunk.content);
  }
}

Backward Compatibility (Deprecated)

Previously, reasoning text was accessed via the response.reasoning property. While still supported for backward compatibility, it is recommended to transition to the structured response.thinking.text API.


Supported Capabilities

Currently, the following models have enhanced reasoning support in NodeLLM:

Model ID Provider Support Level
deepseek-reasoner DeepSeek Full text extraction
o1-*, o3-* OpenAI Effort configuration & token tracking
claude-sonnet-5, claude-opus-4-7+ Anthropic Adaptive thinking with effort & summarized text
claude-sonnet-4-5, claude-haiku-4-5 Anthropic Budget-based thinking & full text extraction
gemini-flash-thinking-* Gemini Full thinking text extraction
magistral-* Mistral Always-on thinking & full text extraction