Skip to content

fix(gemini): a current Gemini model as the pilot - #13

Open
Bayway wants to merge 1 commit into
rokbenko:mainfrom
Bayway:fix/gemini-3-thought-signatures
Open

fix(gemini): a current Gemini model as the pilot#13
Bayway wants to merge 1 commit into
rokbenko:mainfrom
Bayway:fix/gemini-3-thought-signatures

Conversation

@Bayway

@Bayway Bayway commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Pointing a duck at gemini-3.5-flash with thought summaries on found three things between the provider and a current Gemini model.

  1. clean_schema did not strip exclusiveMinimum / exclusiveMaximum. pydantic writes gt=0 that way, so every verb with a timeout_s or a duration_s carried one, and google-genai 2.x validates the function declaration and refuses the keyword outright. The executor still enforces the bound on the way in, so dropping it loses nothing.
  2. The default model 404s. gemini-2.5-pro now answers "no longer available to new users". I set the default to the gemini-pro-latest alias — same tier, but a default that moves seemed better than one that 404s. If you would rather pin, gemini-3.1-pro-preview is what the error message recommends; happy to change it.
  3. Gemini 3 signs function calls. Each function_call part carries a thought_signature, and the next request is refused with a 400 unless the same call comes back with it. ToolCall grows a signature: str = "" (base64; every other provider leaves it empty and nothing reads it), parse_response fills it, render_contents puts the bytes back on the part.

Three tests: the cleaner on both keywords, the signature round trip (bytes in, text in the transcript, bytes out), and that an unsigned call is replayed without growing an empty one. The existing model-name assertion is updated. ruff, format, mypy and the full suite are green here. Verified live with a two-step run to success on gemini-3.5-flash.

Three faults between the provider and Gemini 3, found by pointing a duck at
gemini-3.5-flash.

The schema cleaner did not strip exclusiveMinimum/exclusiveMaximum. pydantic
writes gt=0 that way, so every verb with a timeout_s or a duration_s carried one,
and google-genai 2.x validates the declaration and refuses the keyword. The
executor still enforces the bound on the way in.

The default model, gemini-2.5-pro, answers 'no longer available to new users'.
The default is now the gemini-pro-latest alias, on purpose: a default that 404s
is worse than one that moves.

Gemini 3 signs each function call with a thought_signature that the next turn
must hand back on that same call, or the request is refused with a 400. ToolCall
carries it as base64 text (signature, empty for every other provider) and
render_contents puts the bytes back on the function_call part.

Verified with a two-step run to success on gemini-3.5-flash with thought
summaries on; ruff, mypy and the full suite are green.

Co-Authored-By: Claude Opus 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