Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Dependency: This skill builds on ai-core. Read it first for critical rules.
Before implementing: Ask the user which provider and model they want.
Then fetch the latest available models from the provider's source code
(check the adapter's model metadata file, e.g. packages/ai-openai/src/model-meta.ts)
or from the provider's API/docs to recommend the most current model.
The model lists in this skill and its reference files may be outdated.
Always verify against the source before recommending a specific model.
The adapter factory function takes the model name as a string literal and an
optional config object (API key, base URL, etc.). The model name is passed
into the factory, not into chat().
Sampling options (temperature, token limits, top_p/topP, etc.) live
inside modelOptions using each provider's native key — they are not
top-level options on chat(). See the per-provider table in
Configuring Sampling below.
Core Patterns
1. Adapter Selection
Each provider has a dedicated package with tree-shakeable adapter factories.
The text adapter is the primary one for chat/completions:
Provider
Package
Factory
Env Var
OpenAI
@tanstack/ai-openai
openaiText
OPENAI_API_KEY
Anthropic
@tanstack/ai-anthropic
anthropicText
ANTHROPIC_API_KEY
Gemini
@tanstack/ai-gemini
geminiText
GOOGLE_API_KEY or GEMINI_API_KEY
Grok (xAI)
@tanstack/ai-grok
grokText
XAI_API_KEY
Groq
@tanstack/ai-groq
groqText
GROQ_API_KEY
OpenRouter
@tanstack/ai-openrouter
openRouterText
OPENROUTER_API_KEY
Ollama
@tanstack/ai-ollama
ollamaText
OLLAMA_HOST (default: http://localhost:11434)
Bedrock
@tanstack/ai-bedrock
bedrockText
BEDROCK_API_KEY or AWS_BEARER_TOKEN_BEDROCK
BytePlus
@tanstack/ai-byteplus
byteplusText
ARK_API_KEY (falls back to BYTEPLUS_API_KEY)
OpenAI-compatible
@tanstack/ai-openai/compatible
openaiCompatible / openaiCompatibleText
provider-specific (passed via apiKey)
BytePlus uses two keys.byteplusText / byteplusVideo /
byteplusImage read ARK_API_KEY (ModelArk, Authorization: Bearer), but
byteplusSpeech / byteplusTranscription are a separate product and read
BYTEPLUS_VOICE_API_KEY (Seed Speech, X-Api-Key). Ark keys are also
region-isolated — the default base URL is the ap-southeast endpoint.
// Each factory takes model as first arg, optional config as secondimport { openaiText } from'@tanstack/ai-openai'import { anthropicText } from'@tanstack/ai-anthropic'import { geminiText } from'@tanstack/ai-gemini'import { grokText } from'@tanstack/ai-grok'import { groqText } from'@tanstack/ai-groq'import { openRouterText } from'@tanstack/ai-openrouter'import { ollamaText } from'@tanstack/ai-ollama'import { bedrockText } from'@tanstack/ai-bedrock'import { byteplusText } from'@tanstack/ai-byteplus'// Model string is passed to the factory, NOT to chat()const adapter = openaiText('gpt-5.2')
const adapter2 = anthropicText('claude-sonnet-4-6')
const adapter3 = geminiText('gemini-2.5-pro')
const adapter4 = grokText('grok-4')
const adapter5 = groqText('llama-3.3-70b-versatile')
const adapter6 = openRouterText('anthropic/claude-sonnet-4')
const adapter7 = ollamaText('llama3.3')
const adapter8 = bedrockText('us.anthropic.claude-3-7-sonnet-20250219-v1:0')
const adapter9 = byteplusText('seed-2-0-lite-260428')
// Optional: pass explicit API keyconst adapterWithKey = openaiText('gpt-5.2', {
apiKey: 'sk-...',
})
@tanstack/ai-bedrock (Amazon Bedrock) branches on config.api:
bedrockText(model) or bedrockText(model, { api: 'converse' }) (the default) — Bedrock's native Converse API via @aws-sdk/client-bedrock-runtime (adapter name bedrock-converse). Reaches the broad catalog: Claude, Nova, Llama, Mistral, DeepSeek, and more.
bedrockText(model, { api: 'chat' }) — OpenAI-compatible Chat Completions endpoint (adapter name bedrock). Open-weight models only (gpt-oss, DeepSeek V3.x, Gemma, Qwen, etc.). Does NOT reach Claude, Nova, or Llama.
bedrockText(model, { api: 'responses' }) — OpenAI-compatible Responses API, mantle-only (adapter name bedrock-responses). Currently gpt-oss family.
Use createBedrockText(model, apiKey, config?) to pass the key explicitly. Auth resolves from BEDROCK_API_KEY / AWS_BEARER_TOKEN_BEDROCK, or SigV4 via the standard AWS credential chain (no extra packages needed — handled by @aws-sdk/client-bedrock-runtime).
2. Runtime Adapter Switching
Use an adapter factory map to switch providers dynamically based on user
input or configuration:
Use extendAdapter() and createModel() to add custom or fine-tuned models
while preserving type safety for the original models:
import { extendAdapter, createModel } from'@tanstack/ai'import { openaiText } from'@tanstack/ai-openai'// Define custom modelsconst customModels = [
createModel('ft:gpt-5.2:my-org:custom-model:abc123', ['text', 'image']),
createModel('my-local-proxy-model', ['text']),
] asconst// Create extended factory - original models still fully typedconst myOpenai = extendAdapter(openaiText, customModels)
// Use original models - full type inference preservedconst gpt5 = myOpenai('gpt-5.2')
// Use custom models - accepted by the type systemconst custom = myOpenai('ft:gpt-5.2:my-org:custom-model:abc123')
// Type error: 'nonexistent-model' is not a valid model// myOpenai('nonexistent-model')
At runtime, extendAdapter simply passes through to the original factory.
The _customModels parameter is only used for type inference.
5. Configuring Sampling
Sampling controls (temperature, token limits, nucleus sampling) are passed
inside modelOptions using each provider's native key. They are not
top-level fields on chat()/ai()/generate().
Per-provider sampling keys (all live inside modelOptions):
Provider
Temperature
Nucleus
Max output tokens
OpenAI
temperature
top_p
max_output_tokens
Anthropic
temperature
top_p
max_tokens
Gemini
temperature
topP
maxOutputTokens
Grok (xAI)
temperature
top_p
max_tokens
Groq
temperature
top_p
max_completion_tokens
OpenRouter (chat)
temperature
topP
maxCompletionTokens
Ollama
temperature
top_p
num_predict (nested in options)
BytePlus
temperature
top_p
max_tokens (or max_completion_tokens)
temperature is the one key every provider names identically; token limits and
some sampling options use provider-native names. Ollama nests all sampling under
modelOptions.options.
Anthropic max_tokens default: Anthropic's API requiresmax_tokens,
so the adapter always sends one. When you omit modelOptions.max_tokens, it
defaults to the selected model's full output ceiling (its max_output_tokens
from model metadata — e.g. 64K for Sonnet, 128K for Opus), not a low constant.
max_tokens is a ceiling, not a reservation (billing is per token generated),
so leaving it unset is the right default for codegen / agentic / long-form
output and avoids silent stop_reason: "max_tokens" truncation. Set it only to
cap output below the model ceiling. Other providers treat token limits as
optional and don't apply this flooring.
When true, the engine wires outputSchema into the regular
chatStream call alongside tools and harvests the schema-constrained
JSON from the agent loop's final-turn text — skipping the separate
structuredOutput / structuredOutputStream finalization round-trip.
When false (or the method is omitted), the legacy finalization path
runs.
Current per-adapter status (#605):
Adapter
Returns
openaiText / openaiChatCompletions
true (all supported models)
anthropicText
true for Claude 4.5+ (gated by ANTHROPIC_COMBINED_TOOLS_AND_SCHEMA_MODELS), false otherwise
geminiText
true for Gemini 3.x (gated by GEMINI_COMBINED_TOOLS_AND_SCHEMA_MODELS), false otherwise
grokText
true for Grok 4 family (gated by GROK_COMBINED_TOOLS_AND_SCHEMA_MODELS), false otherwise
groqText
false (Groq API rejects schema + tools + stream)
openRouterText / openRouterResponsesText
false (per-call resolution is a follow-up)
ollamaText
false (constrained-decoding vs tool-call grammar conflict)
byteplusText
Per model — true only for the 10 ids in BYTEPLUS_STRUCTURED_OUTPUT_CHAT_MODELS, false otherwise
Subclasses can override to narrow the capability. When extending an
adapter for a custom model that doesn't support the combination, return
false explicitly.
BytePlus has no JSON-mode fallback. On the 8 chat models outside
BYTEPLUS_STRUCTURED_OUTPUT_CHAT_MODELS, Ark rejects json_schemaandjson_object, so false here does not buy a degraded path — it only keeps
response_format out of the streaming chat request. structuredOutput()
throws and structuredOutputStream() emits RUN_ERROR on those models.
Note seed-2-0-lite-260428 (the obvious default) is one of them; use
seed-2-0-lite-260228 or dola-seed-2-1-turbo-260628 for typed output.
6. OpenAI-Compatible Providers
Any provider that implements the OpenAI Chat Completions API (DeepSeek,
Moonshot/Kimi, Together, Fireworks, Cerebras, Qwen/DashScope, Perplexity,
NVIDIA NIM, LM Studio, etc.) can be used through the generic
openaiCompatible factory from @tanstack/ai-openai/compatible — no
dedicated package required.
import { openaiCompatible } from'@tanstack/ai-openai/compatible'import { createModel } from'@tanstack/ai'// Provider-factory: configure baseURL + apiKey + models ONCE,// then select a model per call (the model arg is a type-safe union).const deepseek = openaiCompatible({
name: 'deepseek', // optional label for devtools/errors (default 'openai-compatible')baseURL: 'https://api.deepseek.com/v1',
apiKey: process.env.DEEPSEEK_API_KEY!,
models: [
'deepseek-chat', // bare string → optimistic defaults: text/image in, streaming, tools, structured outputcreateModel('deepseek-reasoner', {
// rich def → precise per-model capabilitiesinput: ['text'],
features: ['reasoning', 'structured_outputs'],
}),
],
})
chat({ adapter: deepseek('deepseek-chat'), messages })
chat({ adapter: deepseek('deepseek-reasoner'), messages })
config also accepts any OpenAI SDK ClientOptions (notably defaultHeaders
and defaultQuery) for providers that need extra auth headers or query params.
Pass api: 'responses' to target the OpenAI Responses API instead of Chat
Completions (only for the rare compatible provider that implements it, e.g.
Azure OpenAI); the default is 'chat-completions', which is what nearly all
compatible providers speak.
Verify the provider's current baseURL and model ids against its live docs —
they drift. See docs/adapters/openai-compatible.md for the full provider table.
Common Mistakes
a. HIGH: Confusing legacy monolithic with tree-shakeable adapter
The legacy openai() (and anthropic(), etc.) monolithic adapters are
deprecated. They take the model in chat(), not in the factory.
HIGH Tension: Type safety vs. quick prototyping -- Per-model type safety
requires specific model string literals. Quick prototyping wants dynamic
selection with string variables. Agents optimizing for quick setup silently
lose type safety. If model names come from user input or config files, use
extendAdapter() to add custom names.
Cross-References
See also: ai-core/chat-experience/SKILL.md -- Adapter choice affects chat setup
See also: ai-core/structured-outputs/SKILL.md -- outputSchema handles provider differences transparently