Skip to content
skyl

Thinking

Requests reasoning. The least uniform field in the library.

Thinking asks the model to reason before answering. Support varies more here than anywhere else in skyl, so the per-provider table below is the important part of this page.

Reference#

type Thinking struct { Enabled bool Effort Effort }

Parameters

  • Enabled — requests reasoning.
  • Effort — hints at depth: low, medium, high, max. Empty means the provider's default.

Caveats

  • A nil *Thinking and &Thinking{} mean different things. Nil is "provider default"; the zero value is "explicitly off".
  • On Anthropic, Effort does nothing. The SDK's adaptive thinking config has no budget or effort field, so there is nothing to map it onto.
  • On OpenAI and openaicompat, Thinking is ignored unless both Enabled and Effort are set. So &Thinking{Enabled: false} does nothing there.
  • Effort: max is sent literally to OpenAI, which does not define that value — expect a 400.
  • Only Gemini maps every case, including a zero budget.

What each adapter does#

Valueanthropicopenai / compatgemini
nilnothing sentnothing sentnothing sent
{Enabled: true}thinking: adaptiveignoredbudget -1 (model decides)
{Enabled: false}thinking: disabledignoredbudget 0
… Effort: loweffort ignoredreasoning_effort: lowbudget 1024
… Effort: mediumeffort ignoredmediumbudget 8192
… Effort: higheffort ignoredhighbudget 16384
… Effort: maxeffort ignoredsent — undefined by OpenAIbudget 24576

Usage#

Asking for deep reasoning

goCompiles
req.Thinking = &skyl.Thinking{Enabled: true, Effort: skyl.EffortHigh}
req.Thinking = &skyl.Thinking{Enabled: true, Effort: skyl.EffortHigh}

Turning reasoning off, portably

goCompiles
req.Thinking = &skyl.Thinking{Enabled: false} // works on anthropic and gemini

if provider == "openai" || provider == "openai-compatible" {
	// The adapter ignores Thinking without an Effort, so reach the wire field.
	if req.ProviderOptions == nil {
		req.ProviderOptions = map[string]any{}
	}
	req.ProviderOptions["reasoning_effort"] = "minimal"
}
req.Thinking = &skyl.Thinking{Enabled: false} // works on anthropic and gemini

if provider == "openai" || provider == "openai-compatible" {
	// The adapter ignores Thinking without an Effort, so reach the wire field.
	if req.ProviderOptions == nil {
		req.ProviderOptions = map[string]any{}
	}
	req.ProviderOptions["reasoning_effort"] = "minimal"
}

Setting a precise budget on Anthropic

goCompiles
// Effort is ignored there, but the budget is reachable by JSON path —
// which only Anthropic supports.
req.ProviderOptions = map[string]any{"thinking.budget_tokens": 4096}
// Effort is ignored there, but the budget is reachable by JSON path —
// which only Anthropic supports.
req.ProviderOptions = map[string]any{"thinking.budget_tokens": 4096}

Troubleshooting#

Turning reasoning off had no effect on cost

You are on OpenAI, where &Thinking{Enabled: false} is ignored entirely. Send reasoning_effort through ProviderOptions.

Effort makes no difference on Anthropic

It is dropped. Use ProviderOptions with thinking.budget_tokens.

Where is the reasoning in the response?

Dropped from Message by every adapter; it stays in Response.Raw. Streaming on Anthropic emits EventThinkingDelta, and is the only structured access skyl offers.

Edit this page on GitHub