Overview
Reasoning (also called “thinking” in some providers) allows AI models to show their step-by-step thought process before providing a final answer. This feature is available across multiple providers with different implementations.Bifrost normalizes all provider-specific reasoning formats to a consistent OpenAI-compatible structure using
reasoning in requests and reasoning_details in responses.Provider Support Matrix
Request Configuration
Chat Completions API
- JSON
- Go SDK
Responses API
- JSON
- Go SDK
Responses API supports both
effort + max_tokens (like Chat Completions) and adds the optional summary parameter for output summarization.Parameter Reference
Chat Completions API Parameters
Responses API Parameters
Responses API accepts the same
effort and max_tokens parameters as Chat Completions, but adds an optional summary parameter for reasoning output summarization.Provider-Specific Conversions
OpenAI
OpenAI uses effort-based reasoning only. Bifrost applies priority logic:- If
reasoning.effortis provided → use it directly - Else if
reasoning.max_tokensis provided → estimate effort from it - The
max_tokensfield is cleared before sending to OpenAI
- Effort (JSON)
- Effort (Go)
- Max Tokens (JSON)
- Max Tokens (Go)
minimal, low, medium, high
When
minimal is encountered, it’s converted to low for non-OpenAI providers. OpenAI receives only: low, medium, high.Anthropic
Anthropic uses athinking parameter with different structure.
- Request Conversion (JSON)
- Request Conversion (Go)
- Response Conversion (JSON)
- Response Conversion (Go)
Dynamic Budget Handling:
Code Reference:
core/providers/anthropic/chat.go:104-134
Bedrock (Anthropic Models)
Bedrock uses the same structure as Anthropic for Claude models.- Request (JSON)
- Request (Go)
The same 1024 minimum token budget constraint applies to Bedrock Anthropic models. Attempts to set
max_tokens below 1024 will result in an error.core/providers/bedrock/utils.go:34-47
Bedrock (Nova Models)
Bedrock Nova models use an effort-based approach similar to OpenAI.- Request Conversion (JSON)
- Request Conversion (Go)
- Effort Levels
- No minimum token budget constraint
- Uses effort levels instead of token budgets
- High effort mode automatically clears conflicting parameters
core/providers/bedrock/utils.go:48-89
Gemini
Gemini usesthinking_config with dual support for both token budgets and effort levels, depending on the model version.
Model Version Support
Priority Rules
When bothreasoning.max_tokens and reasoning.effort are present:
- Budget Priority (JSON)
- Effort to Level (Gemini 3.0+)
- Effort to Budget (Gemini 2.5)
Model-Specific Level Conversions
Gemini Pro models have stricter constraints on thinking levels:
Example:
Special Values
- Dynamic Budget (JSON)
- Disable Reasoning (JSON)
- Go SDK Examples
Response Conversion
- Response (JSON)
- Response (Go)
Conversion Summary
Bifrost → Gemini (Request):
* Assumes
max_completion_tokens: 8192 (default), uses estimation formula** Pro models convert
"medium" to "high"
Gemini → Bifrost (Response):
Code References:
core/providers/gemini/utils.go(Chat Completions)core/providers/gemini/responses.go(Responses API)core/providers/gemini/types.go(Constants)
Two Reasoning Methods: Effort vs. Max Tokens
Bifrost supports two distinct reasoning models across different providers:Reasoning Model Types
Important: Both effort and max_tokens can be specified in a single request. Bifrost uses a priority hierarchy to determine which field is used.
Priority Logic: Native vs. Estimated
When botheffort and max_tokens are present in a request, Bifrost prioritizes the native compatible field for the target provider:
For Max-Tokens-Based Providers (Anthropic, Cohere, Gemini)
max_tokens: 2000 directly, ignores effort
For Effort-Based Providers (OpenAI, AWS Bedrock Nova)
effort: "high" directly, strips max_tokens from JSON
Why Priority Matters
Why Priority Matters
Reason 1: Accuracy - Native fields provide direct control without estimation lossReason 2: Consistency - Using native fields ensures the exact user intent is preservedReason 3: Performance - Avoids unnecessary conversions when native field is already provided
Estimator Functions
Bifrost provides two estimator functions to convert between reasoning methods. These are used when the native field is not available.Function 1: Effort → Max Tokens
Function:GetBudgetTokensFromReasoningEffort()
File: core/providers/utils/utils.go:1350-1387
Signature:
minBudgetTokens=1024, maxTokens=4096):
*When result is below minimum, clamped to minBudgetTokens (for Anthropic minimum of 1024)
Function 2: Max Tokens → Effort
Function:GetReasoningEffortFromBudgetTokens()
File: core/providers/utils/utils.go:1308-1345
Signature:
minBudgetTokens=1024, maxTokens=4096):
Defensive Defaults:
Provider-Specific Constants
Different providers have different constraints on reasoning budget:Min Budget Constants
Default Completion Tokens (for ratio calculation)
Whenmax_completion_tokens is not provided, these defaults are used for ratio calculations:
Effort-to-Token Conversion Examples
Example 1: Estimate tokens from effort (Anthropic)
- JSON
- Go SDK
Input:Conversion Process:
effort = "high"→ratio = 0.80minBudgetTokens = 1024(Anthropic)maxCompletionTokens = 2000budget = 1024 + (0.80 × (2000 - 1024))budget = 1024 + (0.80 × 976)budget = 1024 + 780- Result: 1804 tokens
Example 2: Estimate effort from tokens (Bedrock Nova)
- JSON
- Go SDK
Input:Conversion Process:
budgetTokens = 2000minBudgetTokens = 1(Nova)maxCompletionTokens = 4096ratio = (2000 - 1) / (4096 - 1)ratio = 1999 / 4095ratio = 0.488(48.8%)- Since
0.25 < 0.488 ≤ 0.60→ Result: “medium”
Example 3: Both fields provided (priority used)
- JSON
- Go SDK
Input:Logic for Max-Tokens-Based Provider:Note: The
- Check: Is
max_tokensprovided? → YES - Use
max_tokensdirectly (ignoreeffort) - Validate:
2500 >= 1024? → YES
effort: "medium" is completely ignored because max_tokens takes priority.Response Format
Bifrost Standard Response
All providers return reasoning in a normalizedreasoning_details array:
Reasoning Details Fields
Type Mappings
OpenAI Implementation: OpenAI (both Chat Completions and Responses API) is effort-based, following the standard priority logic: if
effort is provided, it’s used directly; if only max_tokens is provided, effort is estimated from it. The max_tokens field is then cleared before JSON serialization via MarshalJSON (core/providers/openai/types.go:383-453), since OpenAI’s APIs don’t accept it.Streaming
Stream Event Types
Anthropic Streaming Example
Bifrost Stream Response
Caveats Summary
Minimum Budget (Anthropic/Bedrock)
Minimum Budget (Anthropic/Bedrock)
Severity: High
Behavior:
reasoning.max_tokens must be >= 1024
Impact: Requests with lower values fail with error
Workaround: Always set max_tokens >= 1024 for Anthropic/BedrockDynamic Budget Not Supported
Dynamic Budget Not Supported
Severity: Medium
Behavior:
reasoning.max_tokens = -1 converted to 1024
Impact: Dynamic budgeting not available on Anthropic/Bedrock
Workaround: Set explicit token budgetEffort Level Normalization
Effort Level Normalization
Severity: Low
Behavior: OpenAI’s
minimal converted to low when routing to other providers
Impact: Slightly different reasoning behaviorSignature Field Provider-Specific
Signature Field Provider-Specific
Severity: Low
Behavior:
signature field only present in Anthropic/Bedrock responses
Impact: Signature-based verification only available for these providersThinking Type Always Enabled
Thinking Type Always Enabled
Severity: Low
Behavior: Anthropic’s
thinking.type always set to "enabled" regardless of effort
Impact: Cannot disable thinking once reasoning param is presentGemini: Only One Parameter Sent
Gemini: Only One Parameter Sent
Severity: Medium
Behavior: When both
effort and max_tokens are provided, only thinkingBudget is sent to Gemini (effort is dropped)
Impact: Effort value is completely ignored when max_tokens is present
Workaround: Provide only the parameter you want to useGemini: Model Version Differences
Gemini: Model Version Differences
Severity: Medium
Behavior: Gemini 2.5 only supports
thinkingBudget, while 3.0+ supports both thinkingBudget and thinkingLevel
Impact: Effort-only requests on 2.5 are converted to budget; on 3.0+ they use native levels
Note: Bifrost automatically detects version and uses appropriate conversionGemini Pro: Limited Level Support
Gemini Pro: Limited Level Support
Severity: Low
Behavior: Pro models only support “low” and “high” thinking levels
Impact:
"minimal" → "low", "medium" → "high" for Pro models
Note: Non-Pro models support all four levels: minimal, low, medium, highComplete Provider Comparison
Reasoning Model
Parameter Support
Troubleshooting
Anthropic: “reasoning.max_tokens must be >= 1024”
Cause: Attempting to use reasoning withmax_tokens < 1024
Solution: Ensure reasoning.max_tokens >= 1024 for Anthropic/Bedrock Anthropic models
OpenAI: Model doesn’t support reasoning
Cause: Using an older model that doesn’t support reasoning (e.g.,gpt-4-turbo)
Solution: Use models with reasoning support: gpt-4o, gpt-4o-mini (o1 series with native reasoning)
Bedrock Nova: max_tokens parameter being ignored
Expected Behavior: Bedrock Nova uses effort-based reasoning only
Solution: Provide effort parameter instead of max_tokens for Nova models

