fix(conversation_loop): detect structured reasoning exhaustion from Ollama fallback models - #28133
Conversation
…llama fallback models Models like qwen3:8b via Ollama return reasoning in the structured `message.reasoning` / `message.reasoning_content` fields instead of inline `<think>` tags. The existing `_thinking_exhausted` detection only checked for inline think tags, so these responses fell through to 3 useless continuation retries + 2 prefills before returning "(empty)" to the user. This patch: 1. Extends `_thinking_exhausted` to also trigger when structured reasoning is present but content is empty (no think tags needed). 2. When exhaustion is detected via structured reasoning (not think tags), appends a 600-char preview of the captured reasoning to the user-facing error message, so the user sees what the model was thinking instead of getting a blank response. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
outsourc-e
left a comment
There was a problem hiding this comment.
The structured-reasoning exhaustion detection itself makes sense, but I’m uneasy about appending raw message.reasoning / reasoning_content back into the user-facing error. That can surface internal scratchpad / provider reasoning text directly to end users, which is a pretty different policy choice than just detecting exhaustion. I’d be more comfortable either (a) landing the detection without the preview, or (b) gating the preview behind an explicit debug/developer mode.
|
Closing — the bug you're chasing is real (Ollama qwen3 returns reasoning in The detector signature is wrong.
The inline The right fix needs an actual exhaustion signal — The 600-char reasoning preview is a separate good idea worth keeping, but it should be gated on the exhaustion signal once that's correct. If you'd like to take another pass with |
Summary
_thinking_exhausteddetection inconversation_loop.pyto recognize structured reasoning (message.reasoning/message.reasoning_content) in addition to inline<think>tagsProblem
Models like
qwen3:8bvia Ollama return reasoning in the structuredmessage.reasoningfield instead of inline<think>tags. The existing detection only checked for<think>tags, so these responses fell through to 3 useless continuation retries + 2 prefills before returning "(empty)" to the user — making the fallback appear "dumb."Changes
agent/conversation_loop.py— two blocks added:Detection (line ~1391): New
_has_structured_reasoningand_content_is_emptychecks._thinking_exhaustednow triggers on(has_think_tags AND no_visible_content) OR (has_structured_reasoning AND content_is_empty).Reasoning preview (line ~1431): When exhaustion is detected via structured reasoning (not think tags), the user sees the first 600 chars of what the model was thinking instead of a blank response.
Test plan
content=""+reasoning="..."(e.g.,qwen3:8bvia Ollama with/thinkonenabled)<think>tag exhaustion detection still works unchangedcontent=""without any reasoning (e.g., GLM-4.7 truncation) still get normal continuation retries, not false-positive exhaustionReproduction
🤖 Generated with Claude Code