Skip to content

Capture reasoning traces from OpenRouter's 'reasoning' field - #2

Open
oy2017 wants to merge 1 commit into
umich-foreseer:mainfrom
oy2017:fix/openrouter-reasoning-capture
Open

Capture reasoning traces from OpenRouter's 'reasoning' field#2
oy2017 wants to merge 1 commit into
umich-foreseer:mainfrom
oy2017:fix/openrouter-reasoning-capture

Conversation

@oy2017

@oy2017 oy2017 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

What

Extends the existing reasoning_content<think> reconstruction (present since the initial release, b9691bf) to also cover OpenRouter's field name for the same data: OpenRouter's OpenAI-compatible API returns reasoning traces in message.reasoning, not message.reasoning_content (the DeepSeek/GLM native convention the code currently reads). The storage format is unchanged — traces are prepended to raw_output as <think>\n…\n</think>\n exactly as the existing mechanism does; this PR only makes that mechanism reachable for one more API dialect.

Without the fallback, runs through OpenRouter silently drop the traces while still paying for them: reasoning tokens show up in usage.completion_tokens_details.reasoning_tokens, but the trace text never reaches raw_output. We hit this on full-benchmark runs of z-ai/glm-5.2 (~10.8M reasoning tokens billed, zero traces stored).

Changes

  • api_model.py (OpenAIModel._call_api): read message.reasoning_content, falling back to message.reasoning.
  • azure_batch_model.py: same fallback in the batch-results path (dict access). The or-chain also tolerates an explicit "reasoning_content": null.

Verification

  • Live call through OpenAIModel against OpenRouter z-ai/glm-5.2: returned output now begins with the full <think> trace.
  • 10-sample smoke run of game_behavior_dictator on tencent/hy3 via OpenRouter through the full CLI pipeline: traces stored in raw_output, 10/10 parsed, 0 failed parses, metrics computed normally.
  • Parser safety: the answer extractors (parse_numeric_output, parse_push_pull_output, boxed/bracket list parsing) all take the LAST match, so bracketed decoy values inside the trace (e.g. a trace quoting the [$x] format) cannot shadow the final answer — verified on trace-bearing outputs containing decoys.

No behavior change for backends that don't emit a reasoning field (OpenAI/Azure, DeepSeek-style native endpoints, self-hosted servers).

🤖 Generated with Claude Code

OpenRouter returns reasoning in message.reasoning; the harness only read
message.reasoning_content (DeepSeek/GLM native name), so traces were
silently dropped. Fall back to 'reasoning' so traces are stored as
<think> blocks in raw_output. Parsers are unaffected (all take the
last bracketed match).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant