You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
tagged mode injects this directive into the system prompt (via dist/system-prompt-mHpoeHEN.js:358-367):
ALL internal reasoning MUST be inside <think>...</think>.
Format every reply as <think>...</think> then <final>...</final>, with no other text.
But Gemini 2.5-pro / 2.5-flash also receive thinkingConfig: { includeThoughts: true, thinkingBudget|thinkingLevel: ... } from resolveGoogleThinkingConfig in dist/anthropic-vertex-stream-YyrYtvts.js:5385, which enables native thought parts in the response.
Failure mode
When prompts are long/persona-heavy (PM cron loops, devsecops loops), the model:
Emits a native thought:true part (3000+ chars)
Then opens a <think> text block per the directive
Pivots to a tool call before closing </think> and never emits <final>
Post-tool-result assistant turn comes back with content: []
Gateway then logs:
[agent/embedded] incomplete turn detected: stopReason=stop payloads=0 — surfacing error to user
The user sees an error message, but the model has already burned ~140K input tokens for nothing. In our environment this added up to ~$20 USD of wasted spend in a few hours on Gemini 2.5 Pro before we caught it.
Reproduction
OpenClaw 2026.4.14
google/gemini-2.5-pro or google/gemini-2.5-flash with thinkingDefault: medium
Long persona system prompt + a tool call request
We have several reproducible session jsonls if helpful — pattern is consistent: one thinking content block, then a text block beginning <think> (no closing tag, no <final>), then a toolCall, then an empty assistant turn.
Proposed fix
Drop google-generative-ai from BUILTIN_REASONING_OUTPUT_MODES. Gemini already exposes native thinking via thoughtSignature / thought:true parts and the thinkingConfig request field — there is no need for tagged reasoning, and combining both confuses the model.
We've patched the dist file locally ({"google-generative-ai": "native"}) and confirmed:
Smoke tests pass with clean text output
No `` text-tag pollution in cron sessions
Native thinking still works
No regression in other Gemini behaviour
Happy to send a PR if useful.
Workaround for others hit by this
If you can't patch the dist file:
Author a tiny provider plugin for `google-generative-ai` that returns `"native"` from `resolveReasoningOutputMode` (hook config: support clawdis.json path for rebranding #17 per docs/plugins/sdk-provider-plugins.md)
`dist/pi-embedded-utils-ZJNz7jk_.js:101` — `splitThinkingTaggedText` returns null on unclosed tag (the parser path that produces the empty visible text)
Summary
OpenClaw 2026.4.14 (and prior 2026.4.x) hardcodes
google-generative-aito tagged reasoning output mode indist/provider-utils-CWYcvxhN.js:taggedmode injects this directive into the system prompt (viadist/system-prompt-mHpoeHEN.js:358-367):But Gemini
2.5-pro/2.5-flashalso receivethinkingConfig: { includeThoughts: true, thinkingBudget|thinkingLevel: ... }fromresolveGoogleThinkingConfigindist/anthropic-vertex-stream-YyrYtvts.js:5385, which enables native thought parts in the response.Failure mode
When prompts are long/persona-heavy (PM cron loops, devsecops loops), the model:
thought:truepart (3000+ chars)<think>text block per the directive</think>and never emits<final>content: []Gateway then logs:
The user sees an error message, but the model has already burned ~140K input tokens for nothing. In our environment this added up to ~$20 USD of wasted spend in a few hours on Gemini 2.5 Pro before we caught it.
Reproduction
google/gemini-2.5-proorgoogle/gemini-2.5-flashwiththinkingDefault: mediumWe have several reproducible session jsonls if helpful — pattern is consistent: one
thinkingcontent block, then atextblock beginning<think>(no closing tag, no<final>), then atoolCall, then an empty assistant turn.Proposed fix
Drop
google-generative-aifromBUILTIN_REASONING_OUTPUT_MODES. Gemini already exposes native thinking viathoughtSignature/thought:trueparts and thethinkingConfigrequest field — there is no need for tagged reasoning, and combining both confuses the model.We've patched the dist file locally (
{"google-generative-ai": "native"}) and confirmed:Happy to send a PR if useful.
Workaround for others hit by this
If you can't patch the dist file:
Related code