Skip to main content

簡潔な回答

Gemini 3 以降のモデル(gemini-4-argon、gemini-3.8-flash、gemini-3.1-pro-preview など)でマルチターンの Function Calling を実行する際、思考シグネチャ(thoughtSignature)に関連する400エラーには2種類あり、それぞれ異なる対処が必要です。 OpenAI 互換の /v1/chat/completions エンドポイント経由で呼び出す場合、これらは一切関係ありません。ゲートウェイがシグネチャを管理するため、標準的な tool_calls / tool メッセージを用意するだけで十分です。

2つのエラーの見分け方

署名の欠落

このメッセージには、関数名と parts 配列内でのインデックスが示されています。これは Gemini 3 ファミリーに対してモデルプロバイダーが適用している厳格なルールです。現在のターンにあるすべての functionCall パートには、その署名が付与されている必要があります。 1つでも欠落しているとすべてのルートで 400 エラーとなり、再試行しても解決しません。

無効または破損した署名

フィールドは存在しますが、検証に失敗しています。署名は暗号化された blob であり、それを生成したルートのみが検証できます。会話の途中でルート、モデル、キー、またはグループが切り替わった場合、以前の署名は受け入れられなくなる可能性があります。

この問題が発生する理由

tools が有効化されている場合、Gemini 3 モデルは暗号化された thoughtSignature を各 functionCall と同じパートに付加し、そのステップにおける推論状態を記録します。モデルは次のリクエストで推論チェーンを継続するためにこれを必要とするため、プロバイダーは変更を加えずにそのまま送り返すことを求めています。

欠落:クライアントがパートを再構築した

最も一般的な原因です。カスタムフレームワークやミドルウェアが履歴を組み立てる際に、name および args だけを functionCall から保持して兄弟の thoughtSignature を破棄してしまっているか、シグネチャをマージせずにストリーミングチャンクを再構成していることが考えられます。

欠落:履歴が圧縮または書き直された

クライアントがコンテキストをトリミングまたは要約したか、複数のパートを1つに統合したことで、シグネチャも一緒に失われました。

無効:会話の途中でルートが変更された

最初のターンはルートAで処理され、その後のターンがルートBに割り振られた場合、ルートBはルートAのシグネチャを認識できません。この切り替えは、グループやキーの変更、または自動フェイルオーバーによって発生することがあります。

無効:会話の途中でモデルが変更された

同一の会話内で gemini-3.8-flash から開始し、gemini-4-argon に切り替えた場合などが該当します。シグネチャはモデル間で互換性がありません。
並列関数呼び出しの場合、モデルは最初の functionCall パートにのみシグネチャを付加します。それ以外には正当な理由でシグネチャが存在しないため、偽造しないでください。順次呼び出し(1ターン内に複数のステップがある場合)では、すべてのステップにシグネチャが含まれ、そのすべてを送り返す必要があります。

修正方法 1:署名の欠落、クライアントによる履歴の再送方法を変更する

1

モデルの応答全体をそのまま返す

公式の google-genai SDKを使用する場合は、単に contents.append(response.candidates[0].content) してください。function_call フィールドのみを抽出しないでください。手動でRESTを実装している場合、2回目のリクエストの contents 内のモデルターンは次のようになっている必要があります:
thoughtSignature と functionCall は、2つのパーツではなく、同じパーツ内の2つのフィールドです。
2

フレームワークやミドルウェアがフィールドを除去していないか確認する

LangChain、カスタムエージェントフレームワーク、またはOpenAIからGeminiへの変換レイヤーを使用している場合は、2回目のターンの実際のリクエストボディを出力し、thoughtSignature が残っていることを確認してください。エラー内の position N は parts[N] です。そこを直接確認してください。
3

一部のモデルで通過する挙動に依存しない

モデルやルーティングによって、署名の欠落をどれだけ厳密にチェックするかは異なります。通過させるものもあれば、400を返すものもあります。同じコードがgemini-3.8-flashで常に動作していてgemini-4-argonで失敗する場合、署名は最初から送信されておらず、以前は単に許容されていただけである可能性が高いです。プロバイダーの要求どおりに署名を返却すれば、すべてのモデルで安定して動作します。

解決策2: 無効な署名、再送信するか最初からやり直す

1

そのまま一度再送信する

APIYI ゲートウェイが署名に関する 400 エラーを受信すると、別のルートで自動的にリトライするため、そのまま再送信するだけで成功することがよくあります。変更は不要です。
2

それでも 400 エラーが出る場合:履歴ターンから署名を削除して再送信

履歴内のすべての role: "model" ターンの parts から thoughtSignature フィールドを削除して再送信します。該当ターンの推論コンテキストは失われ、回答品質がわずかに低下する可能性がありますが、会話を継続できます。削除するのは履歴のターンのみとし、現在のターンは絶対に削除しないでください。
3

または新しい会話を開始する

最もシンプルで信頼性の高い選択肢です。新しい会話では、最初のターンからすべての署名が同一ルートから取得されます。
4

会話ごとに 1 つのモデル、1 つのキー

モデル、キー、またはグループを切り替える必要がある場合は、まず新しい会話を開始してください。すでにツール呼び出し履歴がある会話の途中で切り替えないでください。

OpenAI互換エンドポイントでの署名処理は不要

/v1/chat/completions 経由で Gemini を呼び出す場合、tool_calls メッセージには signature フィールドがありません。ゲートウェイが変換中にそれを保存および復元します。gemini-4-argon でのテストでは、単一の呼び出し、2つの並列呼び出し、テキストと呼び出しの組み合わせという3つのパターンすべてで、2ターンの会話が成功しました。標準的な OpenAI の方法で tool_calls および tool メッセージを返却するだけです。
Gemini モデルはそのエンドポイントをまだサポートしていないため、デフォルトで /v1/responses を使用する Codex などのクライアントは、チャットプロトコルに切り替える必要があります。Gemini 4 Argon テキスト生成 を参照してください。

よくある質問

いいえ。シグネチャの返却はGemini 3ファミリー全体に対するプロバイダーの要件であり、一部のモデルのルートでは単にシグネチャの欠落に対して寛容であるに過ぎません。厳格な検証を行うモデルに移行したことで問題が表面化しただけであり、根本的な原因は依然としてクライアントがシグネチャを送信していないことにあります。
いいえ。シグネチャは、それを生成したルートおよび会話コンテキスト内でのみ有効です。別の会話にコピーするとInvalidになります。
functionCallと同じパート内、つまりそれを保持するチャンクの内部にあります。streamを再構成する際は、履歴に戻す前に、このフィールドをfunctionCallと一緒に最終的なモデルの返答へとマージしてください。
厳密には必須ではありません。プロバイダーがシグネチャを厳格に検証するのはfunctionCallパートのみです。テキストターンでシグネチャが欠落していても400エラーにはなりませんが、シグネチャを維持することで推論の継続性が向上するため、いずれにせよ返答全体をそのまま送り返してください。

関連ドキュメント

Gemini Function Calling ガイド

シグネチャの返し方を含む、完全な2ターンの例

Gemini 4 Argon テキスト生成

マルチターンのツール呼び出しに関する注意点とクライアントのセットアップ

ClaudeのInvalid Thinking Signatureエラーを解決する方法

Claude側における同種の問題

マルチターン会話ガイド

各プロバイダーが期待する履歴の返却方法