Repository navigation
google (AI Studio): Codex tool continuation returns 400 — thought_signature replay is gated to vertex/cloud-code-assist only #1930
Description
Client or integration
Codex CLI
Provider or upstream service
google (Gemini AI Studio API, adapter: google)
OpenCodex version
2.20.0
Endpoint or capability
/v1/responses — tool calls, multi-turn continuation
Current behaviour
Any tool-using turn against the plain google provider fails on the continuation request with HTTP 400 from Gemini:
Function call is missing a thought_signature in functionCall parts.
The first turn succeeds and the tool executes. The follow-up request that replays the tool call is rejected. Plain chat turns (no tools) always work.
Root cause: every thought-signature replay call site in src/adapters/google.ts (2.20.0) is gated on provider.googleMode:
| Line | Call | Guard |
|---|---|---|
| 488 | applyAntigravityReplay |
inside googleMode === "cloud-code-assist" branch (opens L442) |
| 520 | applyAntigravityReplay |
inside googleMode === "vertex" branch (opens L509) |
| 673 | observeAntigravityReplay |
googleMode === "cloud-code-assist" || === "vertex" (L671) |
| 900 | observeAntigravityReplay |
googleMode === "cloud-code-assist" || === "vertex" (L898) |
The google registry entry (src/providers/registry.ts, ~L1444) declares no googleMode:
{ id: "google", label: "Google Gemini", adapter: "google",
baseUrl: "https://generativelanguage.googleapis.com", authKind: "key", ... }so provider.googleMode is undefined and none of the four branches run. Both halves are skipped: signatures are never observed from responses and never applied to continuations. Because the write half is also skipped, the failure cannot self-heal on retry.
antigravityUsesReplayCache() is not the gate — it only excludes Claude models and would accept a Gemini model; it is simply never reached on the AI Studio path.
Inbound-wire comparison (same provider, same model, same replay payload — only the inbound protocol differs):
| Inbound wire | Client | Result |
|---|---|---|
Responses (/v1/responses) |
Codex CLI / App | 400 |
Chat Completions (/v1/chat/completions) |
OpenAI-compatible clients | 200 |
Anthropic Messages (/v1/messages) |
Claude Code | 200 |
The Chat and Anthropic paths rebuild functionCall parts rather than carrying an upstream part that Gemini expects a signature on, so they are unaffected. This makes google unusable in Codex for anything agentic, while remaining fine for chat.
Affected models tested: gemini-3.5-flash, gemini-3.5-flash-lite.
Expected behaviour
The thought_signature returned on a functionCall part should be recorded and replayed verbatim on the continuation request, so a multi-turn tool loop against the google provider succeeds — matching the behaviour already implemented for google-vertex and google-antigravity.
Per Google's specification this is mandatory, not optional: Gemini 3 models enforce strict validation, signatures must be returned in subsequent requests even at MINIMAL thinking levels, and the part must be included exactly as returned by the model. Omitting it is documented to produce exactly the 400 seen here.
Minimal redacted request or reproduction
# Against a running proxy with a `google` provider configured (AI Studio API key).
# No Codex needed — a plain Responses request with a tool replay reproduces it.
curl -s http://127.0.0.1:10100/v1/responses \
-H 'content-type: application/json' \
-d '{
"model": "google/gemini-3.5-flash-lite",
"tools": [{"type":"function","name":"get_x","description":"d",
"parameters":{"type":"object","properties":{"a":{"type":"string"}},"required":["a"]}}],
"input": [
{"type":"message","role":"user","content":[{"type":"input_text","text":"list files"}]},
{"type":"function_call","call_id":"k1","name":"get_x","arguments":"{\"a\":\"1\"}"},
{"type":"function_call_output","call_id":"k1","output":"2"}
]
}'
# type:"custom" tools (custom_tool_call / custom_tool_call_output, what Codex 0.144
# actually emits for its exec tool) fail identically.
# Via Codex:
codex exec --skip-git-repo-check -m "google/gemini-3.5-flash-lite" \
-c 'sandbox_mode="read-only"' \
"Use the shell tool to list files in the current directory, then tell me how many there are."
# The shell command runs and returns successfully, then the continuation 400s.
# NOTE: if you instead get "User location is not supported for the API use."
# (FAILED_PRECONDITION), that is an unrelated Google egress-IP restriction, not this
# bug. This bug is identifiable by the "thought_signature" wording.Actual response or error
# HTTP 400 from the proxy:
{"error":{"message":"Provider error 400: {\n \"error\": {\n \"code\": 400,\n \"message\": \"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, ...\",\n \"status\": \"INVALID_ARGUMENT\"\n }\n}\n","type":"upstream_error","code":null}}
# As surfaced in Codex, after the tool has already executed successfully:
exec ... succeeded in 1658ms: 2
ERROR: {"error":{"message":"Provider error 400","type":"upstream_error","code":null}}
# Same request via /v1/chat/completions on the same provider and model: HTTP 200.Upstream documentation
Upstream documentation
Google AI for Developers — Thought Signatures:
https://ai.google.dev/gemini-api/docs/thought-signatures
Function calling with the Gemini API:
https://ai.google.dev/gemini-api/docs/function-calling
Key requirements stated there:
- Gemini 3 models enforce stricter validation on thought signatures than earlier versions.
- Signatures from previous responses must be returned in subsequent requests, even when using MINIMAL thinking levels.
- The part containing the
functionCalland itsthought_signaturemust be included exactly as returned by the model. - A missing required signature produces a 400 error.
- For parallel function calls, the signature is attached only to the first
functionCallpart in a response.
Suggested mapping or implementation notes
Include the AI Studio path in the same guards — treat an absent googleMode (or an explicit "ai-studio") as replay-eligible at all four sites, so signatures are both observed from responses and applied to continuations.
The cache in google-antigravity-replay.ts looks provider-agnostic (keyed by model + session + functionCall identity), so this may be a wiring change rather than new machinery. Worth confirming the session key is meaningful on the AI Studio path, since it has no Antigravity/Vertex session concept.
If AI Studio genuinely cannot round-trip signatures, an explicit upfront error naming the limitation would be far better than an opaque upstream 400 after the tool has already run and had side effects.
Additional context and attachments
This is not a duplicate of the existing thought-signature issues. Those all concern providers where the replay machinery is already wired in, and address cache misses within it:
- [Bug] Gemini/Antigravity tool call loses thoughtSignature during Codex continuation #1735 — Gemini/Antigravity loses thoughtSignature during Codex continuation
- [Bug]: google-antigravity tool continuation 400s once the in-process thought-signature replay cache misses #1429 — google-antigravity 400s once the in-process replay cache misses
- google-vertex: Codex tool continuation returns 400 when functionCall thought_signature is not replayed #1254 / google-vertex: Codex tool continuation returns 400 when functionCall thought_signature is not replayed #1248 — google-vertex: continuation 400 when signature is not replayed
- google-antigravity: a reasoning signature carried on a standalone thought part is dropped by the replay cache #897 — signature on a standalone thought part dropped by the replay cache
On the plain google provider the replay path is never entered at all, for any request — a coverage gap rather than a cache-correctness bug. That is why the vertex/CCA fixes do not resolve it.
Environment: opencodex 2.20.0 (npm, bundled Bun) · Windows 10 Pro 19045 · Node v24.11.1 · Codex CLI 0.144.1 · provider google, adapter google, authKind: key.
Unrelated minor finding: two models listed in the google registry entry return HTTP 404 from the AI Studio API (they appear in the Codex model picker but cannot be called):
gemini-3.6-flash→ 404gemini-3.7-flash→ 404
(gemini-3.1-pro-preview returned 429 in my testing, likely quota rather than availability.) Happy to split this into its own issue if preferred.
Checks
- I searched existing provider and compatibility issues.
- The request and response were redacted.
- The expected behaviour is based on an upstream specification or a concrete client requirement.
Activity
github-actions commentedon Aug 17, 2026
Issue closed: insufficient detail
Thanks for taking the time to submit this issue. It was closed automatically because the structured report is missing information needed to evaluate or reproduce it.
Please edit the issue to add:
See the Contributing guide for details.
Once the report passes the automated checks, it will be reopened automatically unless a maintainer has changed its state.
coderabbitai commentedon Aug 17, 2026
🔗 Related PRs
#430 - fix(google): never emit empty or malformed content parts (
#420) [open]#941 - fix(antigravity): keep the signature from a standalone thought part [merged]
#1266 - fix(google): replay Vertex thought signatures [merged]
#1335 - fix(vertex): scope replay by client thread [open]
#1772 - fix(google): replay Gemini thought signatures through the web-search loop [open]
#1781 - fix(google): carry Gemini thought signatures through the Responses round trip [merged]
#1823 - fix(google): re-attach Gemini thought signatures on bare history replay [merged]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!