# Moving reasoning into chat()

Move `reasoning`, `thinking`, and `thinkingConfig` out of `modelOptions`. Pass `reasoning` to `chat()` as a level, or as `{ level, summary, budgetTokens }`.

## Upgrade

1. Delete the reasoning field from `modelOptions`.
2. Set `reasoning` on `chat()`. Find the old field of your adapter in the [table below](#adapter-by-adapter).
3. If you set a token budget, move it to `budgetTokens`. See [Budgets](#budgets).
4. Run your type checker.

There is no codemod for this change.

```typescript ignore
// Before
chat({
  adapter: openaiText("gpt-6.1-sol"),
  messages,
  modelOptions: { reasoning: { effort: "high", summary: "auto" } },
});
```

```typescript
import { chat } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";

const messages = [{ role: "user" as const, content: "Hello" }];

// After
chat({
  adapter: openaiText("gpt-6.1-sol"),
  messages,
  threadId: "thread-1",
  reasoning: "high",
});
```

The thinking text streams by default. To hide it, pass `reasoning: { level: "high", summary: false }`.

## Adapter by adapter

| Adapter | Old `modelOptions` field | Now |
| --- | --- | --- |
| `openaiText`, `openaiChatCompletions`, `azureOpenaiText` | `reasoning: { effort, summary }` | `reasoning: "high"` |
| `anthropicText` | `thinking`, `effort`, `output_config.effort` | `reasoning: "high"`, or `{ level, budgetTokens }` on budget models |
| `geminiText` | `thinkingConfig` | `reasoning: "high"`, or `{ level, budgetTokens }` on Gemini 2.5 |
| `geminiTextInteractions` | `generation_config.thinking_level`, `thinking_summaries` | `reasoning: "high"` |
| `grokText`, `openRouterText` | `reasoning: { effort }` | `reasoning: "high"` |
| `vercelGatewayText`, `lovableText` | `reasoning`, `include_reasoning` | `reasoning: "high"` |
| `bedrockText` | `reasoning_effort` (chat), `reasoning` (Responses) | `reasoning: "high"` |
| `groqText`, `llmGatewayText`, `cloudflareText` | `reasoning_effort` | `reasoning: "high"` |
| `byteplusText` | `thinking`, `reasoning_effort` | `reasoning: "high"`, or `"off"` |
| `ollamaText` | `think` | `reasoning: "high"`, or `"off"` |
| `codexText` | `modelReasoningEffort` | `reasoning: "high"` |

`"high"` is an example. Use any level that your model has. The types show the levels of your model.

## Budgets

An Anthropic or Gemini 2.5 budget moves to `budgetTokens`:

```typescript ignore
// Before
modelOptions: { thinking: { type: "enabled", budget_tokens: 8000 } }
```

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";

const messages = [{ role: "user" as const, content: "Hello" }];

// After
chat({
  adapter: anthropicText("claude-haiku-4-5"),
  messages,
  threadId: "thread-1",
  reasoning: { level: "high", budgetTokens: 8000 },
});
```

The adapter raises `max_tokens` when it is below the budget.

## Azure

`azureOpenaiText` and `createAzureOpenaiText` read the levels of the OpenAI model name that you pass, not of your deployment name:

```typescript
import { chat } from "@tanstack/ai";
import { createAzureOpenaiText } from "@tanstack/ai-openai";

const messages = [{ role: "user" as const, content: "Hello" }];

chat({
  adapter: createAzureOpenaiText("gpt-6.1-sol", "azure-key", {
    resourceName: "my-resource",
    deploymentName: "prod-chat",
  }),
  messages,
  threadId: "thread-1",
  reasoning: "high",
});
```

If you pass only a deployment name as the model, the adapter has no levels for it, and `reasoning` is a type error. Pass the OpenAI model name, and set `deploymentName`.

## Codex

`modelReasoningEffort` stays on the `codexText` config. It is the default for a call without `reasoning`.

## Removed types

- `@tanstack/ai-openai`: `OpenAIReasoningOptions`, `OpenAIReasoningOptionsWithConcise`.
- `@tanstack/ai-anthropic`: `AnthropicThinkingOptions`, `AnthropicAdaptiveThinkingOptions`, `AnthropicAdaptiveOnlyThinkingOptions`, `AnthropicAdaptiveOrDisabledThinkingOptions`, `AnthropicEffortOptions`, `AnthropicOutputConfigOptions`.
- `@tanstack/ai-gemini`: `GeminiThinkingOptions`.
- `@tanstack/ai-grok`: `GrokReasoning`, `GrokReasoningEffort`, `GrokBuildProviderOptions`.
- `@tanstack/ai-openrouter`: `ReasoningOptions`. `@tanstack/ai-byteplus`: `BytePlusThinkingOption`, `BytePlusReasoningEffort`.

## Done

Your type checker passes, and no `modelOptions` has a reasoning field. One `reasoning` option now sets reasoning on every provider. For levels, budgets, and middleware, see [Reasoning](../chat/reasoning).
