reasoning.effort knob onto Claude’s native
thinking and effort controls, which differ by model generation.
Configure
config.yaml:
Anthropic’s
/v1/messages requires max_tokens on every request. GoModel
injects ANTHROPIC_DEFAULT_MAX_TOKENS (default 4096) when a caller omits
it, keeping the OpenAI-compatible surface lenient.Claude subscription (OAuth token)
GoModel also accepts a Claude subscription OAuth token as the Anthropic credential. Generate one withclaude setup-token (requires a Claude
subscription — Pro, Max, Team, or Enterprise — and the Claude Code CLI) and
set it as the provider key:
sk-ant-oat prefix are detected automatically: GoModel sends
them as Authorization: Bearer with the oauth-2025-04-20 beta instead of
x-api-key. No extra configuration is needed.
Reasoning effort mapping
GoModel accepts the OpenAI-shaped"reasoning": {"effort": "..."} object as
well as the Chat Completions string form "reasoning_effort": "..." (a
non-empty reasoning.effort wins when both are present; an empty object falls
back to the string form) and translates them to Claude’s native controls. The
five accepted levels are low, medium, high, xhigh, and max; values
are matched case-insensitively and any other value is downgraded to low and
logged. The translation
depends on whether the model supports adaptive thinking.
Adaptive routing is an explicit allowlist, not a version comparison. New
model IDs are treated as legacy until added to the list. For pre-4.7 models
the legacy fallback keeps working via
budget_tokens; models from Opus 4.7
onward reject budget_tokens outright, so a new adaptive-only model ID
fails with an upstream 400 until it is added to the allowlist.max_tokens is
bumped above the budget when needed. xhigh and max are adaptive-only levels,
so on legacy models they are capped at the high budget rather than inflating
max_tokens past what those models can emit:
Omit
reasoning to leave thinking at the model’s default. GoModel only sets
thinking: {type: "adaptive"} when you pass reasoning.effort (or
reasoning_effort). Without it,
Opus 4.6 to 4.8 and Sonnet 4.6/5 do not engage extended thinking, while
Fable 5/5.1, Mythos 5/5.1, and Opus 5 think adaptively on their own (see the
always-on note below). Effort is a separate
control that governs overall token spend (text and tool calls) whether or not
thinking is engaged, and Anthropic defaults it to high when unset. It is a
behavioral signal for depth and verbosity, not a hard budget — actual usage
varies per request and is bounded by max_tokens.Effort levels are model-gated upstream:
xhigh is available on Fable 5/5.1,
Opus 5, Sonnet 5, and Opus 4.8/4.7; max on those plus Opus 4.6 and
Sonnet 4.6. GoModel forwards the level you send; Anthropic rejects it with a
400 if the target model does not support it. Manual budget_tokens thinking
is rejected from Opus 4.7 onward, which is why GoModel uses adaptive thinking
for those models.On Fable 5/5.1, Mythos 5/5.1, and Opus 5 thinking is always on, whether or
not you send
reasoning; reasoning.effort only tunes its depth. The tokens
it spends are reported as usage.completion_reasoning_tokens in Chat
Completions responses. The reasoning text itself is not returned; only the
token count is.Sampling parameters
Anthropic removedtemperature and top_p from Fable 5/5.1, Mythos 5/5.1,
Opus 5, Sonnet 5, and Opus 4.8/4.7 — any value, including the OpenAI SDK
default of temperature: 1, is rejected upstream with a 400. GoModel drops
both fields for those models and logs the discarded values, so clients that
always send a temperature keep working. Older models still receive them as
sent, with one exception below.
Anthropic treats temperature and top_p as mutually exclusive on every
model: a request carrying both is rejected with 400 "`temperature` and `top_p` cannot both be specified for this model". Since OpenAI-compatible
clients routinely fill in both defaults, GoModel forwards temperature and
drops top_p (logging the discarded value) when it sees both. Send only
top_p if that is the knob you want to control.
Independently of the model, when extended thinking is engaged Anthropic
requires temperature = 1. GoModel drops any other temperature value (and logs
it) rather than failing the request.
Structured output
response_format works on Anthropic models, mapped onto Claude’s native
structured outputs (output_config.format). The same applies to text.format
on /v1/responses, which GoModel translates into response_format first.
message.content is the JSON
text, with finish_reason: "stop" — the same shape OpenAI returns. Streaming is
unaffected: the JSON arrives as normal content deltas. Tools and
response_format can be sent together; Claude either calls a tool
(finish_reason: "tool_calls") or answers with schema-constrained JSON.
Anthropic’s schema compiler is stricter than OpenAI’s, so GoModel adapts the
schema before sending it:
- every object schema gets the mandatory
"additionalProperties": false, on eachallOfbranch too — Anthropic requires it and merges the branches itself - validation-only keywords Anthropic does not honor (
minimum,maximum,multipleOf,maxItems,uniqueItems,minLength,maxLength,propertyNames,not,if/then/else, …) are dropped patternis kept, because Anthropic does enforce it — except for the regex features its engine rejects (lookarounds, backreferences,\b/\B), which would 400 the request; those patterns are dropped and the loss is loggedminItemsis kept when it is0or1, the only values Anthropic accepts, and dropped otherwiseoneOfis relaxed toanyOf, and unknown stringformatvalues are dropped. A schema carrying bothoneOfandanyOfat the same level cannot be expressed — Anthropic rejects theallOfthat would hold the second one — sooneOfis dropped and the loss is loggedrequiredis left exactly as sent: Anthropic accepts optional properties, so a property you left out ofrequiredstays optional
enum, const, anyOf, allOf, and $ref/$defs
are passed through unchanged. $ref has limits GoModel cannot paper over, and
Anthropic returns a 400 naming each one: references must be local (#/$defs/…
— an external URL is refused), non-recursive (a definition that refers to
itself, directly or in a cycle, is refused), and outside allOf (resolve the
reference yourself before composing with allOf).
strict is not forwarded — Anthropic always enforces the schema it is given.
A non-strict schema is therefore enforced too, minus the constraints listed
above. Structured output is available on every Claude model GoModel can
currently reach.When the content is not schema-valid JSON
The schema constrains what the model generates, not how the turn ends. Check the completion before parsingmessage.content:
finish_reason: "length"— the answer hitmax_tokensand the JSON is cut off mid-value. Raisemax_tokensand retry.finish_reason: "tool_calls"— the model called a tool instead of answering, somessage.contentis empty.finish_reason: "refusal"— Claude declined the request; GoModel passes Anthropic’s refusal stop reason through unchanged and there is no JSON to parse.
finish_reason: "stop" with non-empty content is worth handing to a JSON
parser; treat anything else as an error rather than parsing it.
Verbosity
OpenAI’sverbosity (and text.verbosity on /v1/responses) has no Anthropic
equivalent. GoModel logs the requested value and drops it rather than failing
the request. Ask for shorter or longer answers in the prompt instead.
Forced tool choice on Fable 5.1
Fable 5.1 and Mythos 5.1 accept onlytool_choice: "auto" and "none";
forcing a call with "required" or {"type": "function", ...} returns a 400
from Anthropic. GoModel follows Anthropic’s documented replacement: the choice
is downgraded to auto and an instruction is appended to the system prompt —
“You must respond by calling one of the provided tools.” for required, or
“You must respond by calling the tool named <name>.” for a named function.
The downgrade is logged. parallel_tool_calls: false is still honored. Fable 5
and every other Claude model keep forced tool use unchanged.
Native passthrough
To send Claude-native request fields that have no OpenAI-compatible equivalent (for example inline mid-tasksystem entries in the messages array), use the
passthrough route /p/anthropic/messages, which forwards the body verbatim.