Skip to documentation
Documentation navigation

Documentation navigation

Documentation / guides

Thinking translation

Preserve or omit provider reasoning according to model capabilities and dialect rules.

developer

model.Effort is intent, not a wire field. Each codec maps it only when the model advertises Caps.Thinking, except OpenAI Chat Completions, which sends reasoning_effort whenever an effort is set. The Anthropic codec additionally requires a declared Caps.ThinkingDialect and fails closed with UndeclaredThinkingDialectError without one.

Mapping

DialectEnabled request fieldsEffortMax behaviorResponse block
OpenAI Chatreasoning_effortmaxreasoning_content to ThinkingBlock
OpenAI Responsesreasoning.effort, summary: automaxreasoning item summary
Anthropicthinking: {type: adaptive} plus output_config.effort under the adaptive dialect; thinking: {type: enabled, budget_tokens: N} and no effort field under the budget dialectmax under the adaptive dialect; a token budget under the budget dialectthinking block with signature
GeminithinkingConfig.thinkingBudget, includeThoughtsUnsupportedEffortErrorthought: true part
Bedrocknone; any non-empty effort is rejectedUnsupportedEffortErrorreasoningContent

When capability or effort is unset, request-side reasoning fields are omitted, except in OpenAI Chat Completions, which consults the effort alone. Anthropic also omits temperature and top_p while thinking is enabled under either dialect, because both request shapes reject those fields alongside thinking.

Replay

Responses encrypted reasoning and Gemini thought signatures are opaque provider state. They are carried only for a same-dialect replay; the codecs do not interpret or cross-replay them. Anthropic signatures remain on the neutral ThinkingBlock.Signature, labelled SignatureFormat: "anthropic". Replaying a signature minted by another dialect — Bedrock Converse serves the same Claude models — is a fatal ForeignThinkingSignatureError, not a dropped field.

req.Model.Caps.Thinking = true
req.Override = &model.Sampling{Effort: model.EffortMedium}
body, err := openairesponses.EncodeRequest(req, false)
if err != nil {
	return err
}
_ = body // includes reasoning and encrypted-content inclusion only when supported.

Source and proof

Run go test ./codec/....

← back to documentation