- MCP Server ToolsUpdated
- Managed MCP with chat()Updated
- Manual MCPUpdated
- MCP Type GenerationUpdated
- MCP Client InputUpdated
- MCP Server Tools: AdvancedNew
- MCP EventsNew
- MCP AppsUpdated
- Serve Tools over HTTPUpdated
- Serve Resources and PromptsUpdated
- Ask for InputUpdated
- Draft Text from a ToolUpdated
- MCP Server TasksUpdated
- MCP Server AuthUpdated
- MCP Server SessionsUpdated
- MCP Server on stdioUpdated
Persistence (Advanced)
- GenerationsUpdated
- Realtime Voice ChatUpdated
- Text-to-SpeechUpdated
- TranscriptionUpdated
- Transcription: AdvancedNew
- Voice CreationUpdated
- Audio RecordingUpdated
- Audio GenerationUpdated
- Image GenerationUpdated
- Image Generation: AdvancedNew
- Video GenerationUpdated
- Video Generation: AdvancedNew
- Live GenerationUpdated
- World GenerationUpdated
- Generation HooksUpdated
- Build your first harnessUpdated
- Host optionsNew
- Send and show mediaUpdated
- Connect clientsUpdated
- Write a client in any languageNew
- Access and tenantsNew
- Run in the terminalUpdated
- Deploy a harnessUpdated
- Send inputs safelyUpdated
- Run a tool without a model
- Durable sessionsUpdated
- Run background work on workersNew
- List, rename, and fork sessionsUpdated
- Lifecycle and retentionNew
- Run side effects onceUpdated
- Wait for a personNew
- Build on the session logUpdated
- Control how a turn endsUpdated
- Store settings per threadUpdated
- Compact a long sessionUpdated
- Fork and reset a threadUpdated
- One log for a session treeUpdated
- Write a pluginUpdated
- Track usage and costUpdated
- Ask before risky tool callsUpdated
- Give your agent coding toolsUpdated
- Sandbox and extend the coding toolsUpdated
- Run the coding tools for many threadsNew
- Undo a turnUpdated
- Build a coding agentUpdated
- Delegate to coding agentsUpdated
- Switch between agent profilesUpdated
- Auth and connectorsUpdated
- Share a thread between peopleUpdated
- Connect model providersUpdated
- Build your own UIUpdated
- Code mode in a harnessUpdated
- Work until a goal is metUpdated
- Run agents from a harnessUpdated
- Hand off a conversationNew
- Add skillsUpdated
- Use MCP serversUpdated
- Give your agent a computerNew
- Use from any MCP clientUpdated
- Use a harness from an editor (ACP)Updated
- OverviewUpdated
- Quick StartUpdated
- ProvidersUpdated
- HarnessesUpdated
- Harness AuthUpdated
- WorkspaceUpdated
- ToolsUpdated
- PolicyUpdated
- Lifecycle & SnapshotsUpdated
- Portable SnapshotsUpdated
- Keep Files After ReloadUpdated
- Save a Named VersionUpdated
- Branch From a VersionUpdated
- Send a Frozen FileUpdated
- Let the Agent Save and ForkUpdated
- Pick Which Files to KeepUpdated
- What a Snapshot StoresUpdated
- Instance DurabilityUpdated
- Durable RunsUpdated
- EventsUpdated
Sandboxes (Advanced)
- Runtime ContextUpdated
- Bring Your Own KeyUpdated
- Keep Keys on the ServerUpdated
- Debug LoggingUpdated
- Multimodal ContentUpdated
- Files APIUpdated
- Per-Model Type SafetyUpdated
- Runtime Adapter SwitchingUpdated
- Tree-ShakingUpdated
- Extend AdapterUpdated
- Extend Adapter: AdvancedNew
- Typed Pre-Configured OptionsUpdated
- Test with a Fake ModelUpdated
- Prompt CachingUpdated
- Mid-Conversation ChangesUpdated
- Approval Flow ProcessingUpdated
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#
- Delete the reasoning field from modelOptions.
- Set reasoning on chat(). Find the old field of your adapter in the table below.
- If you set a token budget, move it to budgetTokens. See Budgets.
- Run your type checker.
There is no codemod for this change.
// Before
chat({
adapter: openaiText("gpt-6.1-sol"),
messages,
modelOptions: { reasoning: { effort: "high", summary: "auto" } },
});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:
// Before
modelOptions: { thinking: { type: "enabled", budget_tokens: 8000 } }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:
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.