Skip to main content

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

Responses API

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:
  1. If reasoning.effort is provided → use it directly
  2. Else if reasoning.max_tokens is provided → estimate effort from it
  3. The max_tokens field is cleared before sending to OpenAI
Conversion Examples:
Supported Effort Levels: 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 a thinking parameter with different structure.
Conversion Rules:
Critical Constraint: Anthropic requires reasoning.max_tokens >= 1024. Requests with lower values will fail with an error.
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.
The same 1024 minimum token budget constraint applies to Bedrock Anthropic models. Attempts to set max_tokens below 1024 will result in an error.
Code Reference: core/providers/bedrock/utils.go:34-47

Bedrock (Nova Models)

Bedrock Nova models use an effort-based approach similar to OpenAI.
Key Differences from Anthropic:
  • No minimum token budget constraint
  • Uses effort levels instead of token budgets
  • High effort mode automatically clears conflicting parameters
Code Reference: core/providers/bedrock/utils.go:48-89

Gemini

Gemini uses thinking_config with dual support for both token budgets and effort levels, depending on the model version.

Model Version Support

Important: Only ONE parameter (thinkingBudget or thinkingLevel) should be sent to Gemini at a time. When both reasoning.max_tokens and reasoning.effort are provided in a Bifrost request, max_tokens takes priority and is converted to thinkingBudget.

Priority Rules

When both reasoning.max_tokens and reasoning.effort are present:

Model-Specific Level Conversions

Gemini Pro models have stricter constraints on thinking levels: Example:

Special Values

Response Conversion

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 both effort 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)

Example (Cohere):
Result: Uses max_tokens: 2000 directly, ignores effort

For Effort-Based Providers (OpenAI, AWS Bedrock Nova)

Example (OpenAI Chat Completions):
Result: Uses effort: "high" directly, strips max_tokens from JSON
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:
Algorithm:
Conversion Examples (with minBudgetTokens=1024, maxTokens=4096):
*When result is below minimum, clamped to minBudgetTokens (for Anthropic minimum of 1024)
Error Handling:
Code Example:

Function 2: Max Tokens → Effort

Function: GetReasoningEffortFromBudgetTokens() File: core/providers/utils/utils.go:1308-1345 Signature:
Algorithm:
Conversion Examples (with minBudgetTokens=1024, maxTokens=4096): Defensive Defaults:
Code Example:

Provider-Specific Constants

Different providers have different constraints on reasoning budget:

Min Budget Constants

Default Completion Tokens (for ratio calculation)

When max_completion_tokens is not provided, these defaults are used for ratio calculations:

Effort-to-Token Conversion Examples

Example 1: Estimate tokens from effort (Anthropic)

Input:
Conversion Process:
  1. effort = "high"ratio = 0.80
  2. minBudgetTokens = 1024 (Anthropic)
  3. maxCompletionTokens = 2000
  4. budget = 1024 + (0.80 × (2000 - 1024))
  5. budget = 1024 + (0.80 × 976)
  6. budget = 1024 + 780
  7. Result: 1804 tokens
Anthropic Request Generated:

Example 2: Estimate effort from tokens (Bedrock Nova)

Input:
Conversion Process:
  1. budgetTokens = 2000
  2. minBudgetTokens = 1 (Nova)
  3. maxCompletionTokens = 4096
  4. ratio = (2000 - 1) / (4096 - 1)
  5. ratio = 1999 / 4095
  6. ratio = 0.488 (48.8%)
  7. Since 0.25 < 0.488 ≤ 0.60Result: “medium”
Bedrock Nova Request Generated:

Example 3: Both fields provided (priority used)

Input:
Logic for Max-Tokens-Based Provider:
  1. Check: Is max_tokens provided? → YES
  2. Use max_tokens directly (ignore effort)
  3. Validate: 2500 >= 1024? → YES
Anthropic Request Generated:
Note: The effort: "medium" is completely ignored because max_tokens takes priority.

Response Format

Bifrost Standard Response

All providers return reasoning in a normalized reasoning_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

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/Bedrock
Severity: Medium Behavior: reasoning.max_tokens = -1 converted to 1024 Impact: Dynamic budgeting not available on Anthropic/Bedrock Workaround: Set explicit token budget
Severity: Low Behavior: OpenAI’s minimal converted to low when routing to other providers Impact: Slightly different reasoning behavior
Severity: Low Behavior: signature field only present in Anthropic/Bedrock responses Impact: Signature-based verification only available for these providers
Severity: Low Behavior: Anthropic’s thinking.type always set to "enabled" regardless of effort Impact: Cannot disable thinking once reasoning param is present
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 use
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 conversion
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, high

Complete Provider Comparison

Reasoning Model

Parameter Support


Troubleshooting

Anthropic: “reasoning.max_tokens must be >= 1024”

Cause: Attempting to use reasoning with max_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