Skip to content

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

@fellanH

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.

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