Skip to content

[Bug] Gemini/Antigravity tool call loses thoughtSignature during Codex continuation #1735

Closed

Description

@fhh2626

Client or integration

Codex App

Area

CLI

Summary

When routing Gemini Flash through Antigravity using the OpenAI-compatible
OpenCodex path, tool calls fail after the first tool execution:

Provider error 400:
Function call is missing a thought_signature in functionCall parts.
Function call: default_api:exec

Expected behavior

The thought signature returned with the Gemini function call should be
preserved and sent back in the next assistant tool call.

For OpenAI-compatible format, the field is:

tool_calls[].extra_content.google.thought_signature

Actual behavior

The first model response contains the signature, but the next request
contains the assistant tool call without it.

Impact

Multi-turn tool calling with Gemini Flash through Antigravity fails.
Pi agent works with the same model/tool flow.

Suggested fix

Preserve extra_content.google.thought_signature while:

  1. Parsing streamed tool-call responses.
  2. Accumulating tool-call deltas.
  3. Serializing assistant history for the next request.
  4. Preserving the exact tool-call order and call ID.

The signature must be replayed unchanged in the same tool-call part.

Reference:
https://ai.google.dev/gemini-api/docs/generate-content/thought-signatures

Reproduction

Simply use Codex + gemini v4.7 flash (via gemini outh)

Version

2.19.0

Operating system

Windows 11

Provider and model

No response

Logs or error output

Screenshots and supporting files

No response

Redacted configuration

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

  1. coderabbitai commented on Aug 15, 2026

    @coderabbitai
    Contributor
    🔗 Related PRs

    #430 - fix(google): never emit empty or malformed content parts (#420) [open]
    #1266 - fix(google): replay Vertex thought signatures [merged]
    #1411 - fix(command-code): pair tool results and synthesize missing-result errors [merged]
    #1434 - fix(google-antigravity): persist thought-signature replay across restarts [open]
    #1499 - fix(deepseek): keep parallel reasoning replay on continuation [open]


    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  2. added
    cliCLI, config inject, packaging flags
    toolstool_calls, MCP, web-search / sidecar tools
    on Aug 15, 2026
  3. github-actions commented on Aug 15, 2026

    @github-actions
    Contributor

    Maintainer decision respected

    A maintainer has reopened this issue. The automated closure has been deactivated.

  4. fhh2626 commented on Aug 15, 2026

    @fhh2626
    Author
  5. reopened this on Aug 15, 2026
  6. added
    providerProvider adapters, OpenAI-compat presets, upstream API quirks
    on Aug 15, 2026
  7. AaronConlon commented on Aug 15, 2026

    @AaronConlon

    Reproduced through a third-party OpenAI Responses client (Survey Workbench) against http://localhost:10100/v1/responses using google/gemini-3.6-flash and OpenCode @bitkyc08/opencodex 2.15.0 on macOS.

    The client is stateless and correctly sends the full current tool turn as:

    1. user message
    2. assistant function_call
    3. function_call_output

    Observed behavior:

    • The first streamed Responses result contains a function_call, but its exposed keys are only arguments, call_id, id, name, status, and type. It has no extra_content, thought_signature, or thoughtSignature.
    • The next request fails upstream with Gemini 400: Function call is missing a thought_signature in functionCall parts (for default_api:articles_read).
    • Manually adding extra_content.google.thought_signature with Google's documented compatibility sentinel skip_thought_signature_validator still yields the same missing-signature 400, indicating the Responses gateway parser/adapter drops or does not replay this metadata before it reaches Gemini.
    • I also tested two consecutive requests with a stable x-codex-parent-thread-id; the first tool request succeeds (200) and the continuation still fails (400), so the gateway replay cache does not currently rescue this Responses flow.

    Expected: /v1/responses should either expose and accept/replay function_call.extra_content.google.thought_signature losslessly, or have its internal Gemini replay cache inject the real signature for the continuation. Current external clients cannot preserve a signature they never receive.

    No API keys, prompts, tool arguments, or tool output are included in this report.

  8. Ingwannu commented on Aug 15, 2026

    @Ingwannu
    Owner

    Confirmed as a real Responses compatibility gap on current dev.

    The Google adapter observes the upstream Gemini thoughtSignature and stores it in the internal Antigravity replay cache, but the outward bridge cannot expose it to a stateless Responses client: the shared tool_call_start event carries only id and name, the emitted function_call item has no extra_content, and the inbound Responses schema/parser likewise do not accept or restore extra_content.google.thought_signature into OcxToolCall.thoughtSignature.

    That explains both reported observations: the first response gives the client no signature to retain, and a later stateless continuation cannot repair a field it never received. A stable thread/session may use the internal replay cache in some managed flows, but it is not a substitute for a lossless Responses wire contract.

    The fix needs to be end-to-end rather than a parser-only patch:

    • carry a validated opaque signature from the Google adapter through the tool-call event;
    • emit it on the matching Responses function_call.extra_content.google.thought_signature;
    • accept the same field on inbound history and map it back to OcxToolCall.thoughtSignature;
    • preserve call order/id and keep the existing validation that refuses foreign item ids as signatures;
    • add stateless two-request and managed replay regressions.

    I am keeping this issue open while that cross-layer contract is implemented and tested.

  9. added 2 commits that reference this issue on Aug 15, 2026
    d8b01b5
    4b95010
  10. lidge-jun commented on Aug 15, 2026

    @lidge-jun
    Owner

    Fixed on dev as 4b95010 (PR #1781).

    The signature now travels with the individual tool call at every hop — adapter event, Responses function_call item (extra_content.google.thought_signature), parser, and the rebuilt Google part — so a history-driven or previous_response_id turn keeps continuity without the same-process replay cache. That cache is why this looked intermittent: it covered streaming turns and nothing else.

    Both synthetic loops (web search, images) now copy the metadata per call, so a batched or parallel response cannot share or swap a signature between calls. Values stay opaque — never parsed, merged, re-encoded, or synthesized — and are refused above the same 64 KiB ceiling the replay cache already enforces.

    Verified on the remote validation host: 176 pass / 0 fail, 534 expect() calls across google-provider-metadata-roundtrip, google-signature-history-roundtrip, google-vertex-thought-signature, google-antigravity-wire, bridge, and web-search. The new cold-replay test warms no cache.

    Two adjacent defects found during review are recorded in devlog/_plan/260815_roadmap_closeout/050_gemini_thought_signature.md rather than bundled in: Google-issued functionCall.id is still replaced by a synthetic call_* (the ids match each other, so pairing works), and the web-search loop interleaves parallel calls as FC1, FR1, FC2, FR2 where Google wants FC1, FC2, FR1, FR2.

    Thanks @chilung-cgu — your #1772 identified the defect and is credited as co-author.

  11. added 2 commits that reference this issue on Sep 17, 2026
    5c9bc21
    78c34d7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcliCLI, config inject, packaging flagsproviderProvider adapters, OpenAI-compat presets, upstream API quirksprovider-compatibilityProvider compatibility reportstoolstool_calls, MCP, web-search / sidecar tools

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions