Skip to content

Gemini 3: function calls require thought_signature (400 error) #283

Description

@fellanH

Gemini 3: function calls require thought_signature (400 error)

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch @inngest/agent-kit@0.13.2 for the project I'm working on.

Problem: When using the Gemini adapter with Gemini 3 models (e.g. gemini-3-flash-preview), the API returns a 400 error:

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.

Google’s docs: Thought Signatures | Gemini API. For Gemini 3, every functionCall part in conversation history must include a thoughtSignature. The adapter was neither capturing it from responses nor sending it on subsequent requests, so validation failed.

Fix (summary):

  1. Response parser – When the API returns a functionCall part, read thoughtSignature / thought_signature from that part and store it on the tool-call message (e.g. as thought_signature on the first tool).
  2. Request builder – When building Gemini contents, include thoughtSignature on every functionCall part: use the stored value when present, otherwise the documented dummy "skip_thought_signature_validator" so the request is accepted (e.g. first turn or history without signatures).

Here is the diff that solved my problem:

diff --git a/node_modules/@inngest/agent-kit/dist/chunk-BSWKEFTT.js b/node_modules/@inngest/agent-kit/dist/chunk-BSWKEFTT.js
index 50538d4..20cbda1 100644
--- a/node_modules/@inngest/agent-kit/dist/chunk-BSWKEFTT.js
+++ b/node_modules/@inngest/agent-kit/dist/chunk-BSWKEFTT.js
@@ -658,6 +658,7 @@ var responseParser4 = (input) => {
           content: content.text
         });
       } else if (candidate.content.role === "model" && "functionCall" in content) {
+        const thoughtSignature = content.thoughtSignature ?? content.thought_signature;
         messages.push({
           role: "assistant",
           type: "tool_call",
@@ -667,7 +668,8 @@ var responseParser4 = (input) => {
               name: content.functionCall.name,
               input: content.functionCall.args,
               type: "tool",
-              id: content.functionCall.name
+              id: content.functionCall.name,
+              ...(thoughtSignature != null && { thought_signature: thoughtSignature })
             }
           ]
         });
@@ -711,7 +713,10 @@ var messageToContent = (m) => {
                 functionCall: {
                   name: m.tools[0].name,
                   args: m.tools[0].input
-                }
+                },
+                ...(m.tools[0].thought_signature != null
+                  ? { thoughtSignature: m.tools[0].thought_signature }
+                  : { thoughtSignature: "skip_thought_signature_validator" })
               }
             ]
           };
@@ -735,7 +740,10 @@ var messageToContent = (m) => {
                 functionCall: {
                   name: m.tools[0].name,
                   args: m.tools[0].input
-                }
+                },
+                ...(m.tools[0].thought_signature != null
+                  ? { thoughtSignature: m.tools[0].thought_signature }
+                  : { thoughtSignature: "skip_thought_signature_validator" })
               }
             ]
           };
diff --git a/node_modules/@inngest/agent-kit/dist/index.cjs b/node_modules/@inngest/agent-kit/dist/index.cjs
index 2ecaa90..805ddf3 100644
--- a/node_modules/@inngest/agent-kit/dist/index.cjs
+++ b/node_modules/@inngest/agent-kit/dist/index.cjs
@@ -1476,6 +1476,7 @@ var responseParser4 = (input) => {
           content: content.text
         });
       } else if (candidate.content.role === "model" && "functionCall" in content) {
+        const thoughtSignature = content.thoughtSignature ?? content.thought_signature;
         messages.push({
           role: "assistant",
           type: "tool_call",
@@ -1485,7 +1486,8 @@ var responseParser4 = (input) => {
               name: content.functionCall.name,
               input: content.functionCall.args,
               type: "tool",
-              id: content.functionCall.name
+              id: content.functionCall.name,
+              ...(thoughtSignature != null && { thought_signature: thoughtSignature })
             }
           ]
         });
@@ -1529,7 +1531,10 @@ var messageToContent = (m) => {
                 functionCall: {
                   name: m.tools[0].name,
                   args: m.tools[0].input
-                }
+                },
+                ...(m.tools[0].thought_signature != null
+                  ? { thoughtSignature: m.tools[0].thought_signature }
+                  : { thoughtSignature: "skip_thought_signature_validator" })
               }
             ]
           };
@@ -1553,7 +1558,10 @@ var messageToContent = (m) => {
                 functionCall: {
                   name: m.tools[0].name,
                   args: m.tools[0].input
-                }
+                },
+                ...(m.tools[0].thought_signature != null
+                  ? { thoughtSignature: m.tools[0].thought_signature }
+                  : { thoughtSignature: "skip_thought_signature_validator" })
               }
             ]
           };

This issue body was partially generated by patch-package.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions