Summary
Any investigation using a Gemini 3.x model fails on the second model turn with 400 INVALID_ARGUMENT. Gemini 3 requires a thought_signature to be replayed on functionCall parts in conversation history; internal/model/gemini never captures or replays one.
This blocks the entire current Gemini generation (3.x). Gemini 2.5 is unaffected.
Error
demo: investigation failed: model: streamGenerateContent status 400 (request-id ""):
INVALID_ARGUMENT: Function call is missing a thought_signature in functionCall parts.
This is required for tools to work correctly, and missing thought_signature may lead to
degraded model performance. Additional data, function call `default_api:what_changed`,
position 2.
Reproduction
# /tmp/gem.yaml
model:
provider: gemini
model: gemini-3.5-flash
api_key_env: GEMINI_API_KEY
lore demo investigate --scenario harbor-chart-bump --config /tmp/gem.yaml
| model |
result |
gemini-3.5-flash |
first tool call (what_changed) succeeds; the next turn — which replays that call in history — fails with the 400 above. Investigation aborts, exit 1 |
gemini-2.5-flash-lite |
completes normally: 4 model calls, verify pass included, findings rendered |
The failure is at position 2, i.e. the first turn that sends a prior functionCall back as history — consistent with the signature being required on replay, not on the initial response.
Cause
grep -c 'thought_signature\|thoughtSignature' internal/model/gemini/*.go → 0.
The client neither reads the field from streamed functionCall parts nor writes it back when reconstructing history. providers.Message already carries an Opaque json.RawMessage field for exactly this class of provider-specific replay data — it is documented as "provider-specific content the client must replay verbatim", and the Anthropic client uses it to round-trip thinking blocks with their signatures. The Gemini client leaves it empty.
Impact
- Every Gemini 3.x model is unusable for investigations — hard failure, not degradation.
- Affects
lore investigate, lore serve, lore demo investigate, and any eval run configured with a Gemini 3.x model.
- Gemini 2.5 models still work, but they are the previous generation.
Suggested fix
Mirror the Anthropic client's approach: capture the thoughtSignature from streamed functionCall parts into Message.Opaque, and replay it verbatim when rebuilding request contents. Add a round-trip test asserting a signature survives response → history → next request.
Verified 2026-08-02 against generativelanguage.googleapis.com/v1beta.
Related: #391 (a different provider-compatibility failure, glm-4.6 + forced tool_choice).
Summary
Any investigation using a Gemini 3.x model fails on the second model turn with
400 INVALID_ARGUMENT. Gemini 3 requires athought_signatureto be replayed onfunctionCallparts in conversation history;internal/model/gemininever captures or replays one.This blocks the entire current Gemini generation (3.x). Gemini 2.5 is unaffected.
Error
Reproduction
gemini-3.5-flashwhat_changed) succeeds; the next turn — which replays that call in history — fails with the 400 above. Investigation aborts, exit 1gemini-2.5-flash-liteThe failure is at position 2, i.e. the first turn that sends a prior
functionCallback as history — consistent with the signature being required on replay, not on the initial response.Cause
grep -c 'thought_signature\|thoughtSignature' internal/model/gemini/*.go→0.The client neither reads the field from streamed
functionCallparts nor writes it back when reconstructing history.providers.Messagealready carries anOpaque json.RawMessagefield for exactly this class of provider-specific replay data — it is documented as "provider-specific content the client must replay verbatim", and the Anthropic client uses it to round-trip thinking blocks with their signatures. The Gemini client leaves it empty.Impact
lore investigate,lore serve,lore demo investigate, and any eval run configured with a Gemini 3.x model.Suggested fix
Mirror the Anthropic client's approach: capture the
thoughtSignaturefrom streamedfunctionCallparts intoMessage.Opaque, and replay it verbatim when rebuilding request contents. Add a round-trip test asserting a signature survives response → history → next request.Verified 2026-08-02 against
generativelanguage.googleapis.com/v1beta.Related: #391 (a different provider-compatibility failure, glm-4.6 + forced
tool_choice).