Gemini Thought Signature Bypass Sentinels
For Gemini 3 targets (gemini-3 / thought_signature_required), Google strictly validates that the first function call in an assistant turn contains a thought_signature. If you omit this field, the endpoint returns an immediate, uncompromising 400 Bad Request. Having shipped a hard requirement with zero tolerance, Google then had to ship its own documented escape hatches so that translated histories and model-switched sessions wouldn't permanently break.
When replaying historical conversations translated from another model family (such as Anthropic or OpenAI) or switching models mid-session, genuine Gemini thought signatures do not exist. You either provide a recognized bypass sentinel or your dispatch fails.
The Two Official Bypass Sentinels
Google officially documents two sentinel bypass strings for the thought_signature field. One is a straightforward utility string; the other is a genuine, production API string that reads like an internal engineering motto that accidentally escaped into a public spec:
'skip_thought_signature_validator'- Supported Platforms: Supported on both the Google Gemini API and Google Cloud Vertex AI.
- Usage: Portable sentinel recommended for multi-cloud or Vertex AI deployments.
'context_engineering_is_the_way_to_go'- Supported Platforms: Supported on the Google Gemini API only (rejected by Vertex AI).
- Usage: Alternate sentinel valid strictly on direct Gemini API endpoints. Yes, typing
'context_engineering_is_the_way_to_go'with a straight face is a real, officially supported way to satisfy Google's production API validator.
Populating ToolCall.payload.thoughtSignature with either string satisfies thought_signature_required validation in this battery and bypasses upstream API rejection.
Provenance and Quality Warning
As Google's documentation cautions, sentinel bypasses should be reserved for translation, migration, or multi-turn replay scenarios. Omitting genuine reasoning signatures on native turns can degrade model output quality relative to real reasoning traces.
Setting Sentinels Manually
When constructing or translating historical tool calls, set thoughtSignature directly on the ToolCall.payload:
import { ToolCall } from '@nhtio/adk'
const historicalToolCall = new ToolCall({
name: 'search_database',
args: { query: 'agent patterns' },
payload: {
// Satisfies Gemini 3 validation when replaying foreign history
thoughtSignature: 'skip_thought_signature_validator',
},
})Automated Fallback Repair
Under ordinary operation, action: 'mutate' mode will not fabricate missing vendor metadata. Unlike reordering primitives or inserting blank alternation fillers, inventing a vendor signature is a direct provenance claim about where reasoning originated — it puts words into the model's mouth regarding its own internal chain of thought.
That reasoning holds for a value the ADK makes up. It does not hold for a sentinel the vendor publishes for exactly this case. A sentinel is not a forged signature; it is a documented way of saying there is no signature here, which is the truth about replayed history.
So the authorization is per-rule, not global. thought_signature_required declares fallbackRepairAuthorized: true, and action: 'mutate' is sufficient:
import { orderingGuardDispatchMiddleware } from '@nhtio/adk/batteries/validation'
const middleware = orderingGuardDispatchMiddleware({
profiles: ['gemini-3'],
action: 'mutate',
onRepair: 'log',
})allowMetadataFallbackRepair: true remains the switch for any rule that does not authorize itself — a profile of your own carrying a fallbackPayloadValue you invented. Enabling it is still a deliberate choice about fabricating provenance; it is simply no longer the only way to dispatch a replayed Gemini 3 tool call.
Why this changed
Before fallbackRepairAuthorized existed, gemini-3 had no working configuration for replayed history: enforce rejected it, mutate rejected it, and the only setting that dispatched was a flag the documentation warns against enabling casually. A rule with a real vendor requirement behind it was unusable for the exact scenario the vendor's own sentinel exists to serve. See issue #15.
What Happens During Fallback Repair
When the repair is authorized and an incoming ToolCall violates thought_signature_required:
- The guard reads
RequiredMetadataRule.fallbackPayloadValue('skip_thought_signature_validator'). - It mutates the
ToolCallpayload viactx.mutateToolCall, settingpayload.thoughtSignature = 'skip_thought_signature_validator'. - If the
ToolCallhas noreplayCompatibilitytag yet, it setsreplayCompatibility = 'gemini-thought-signature-sentinel-v1'so downstream adapters recognize the sentinel format. An existing tag on the primitive is left unchanged. - It records the repair in
OrderingGuardResult.repairedunder strategy'fill-required-metadata'. - The guard re-evaluates the timeline and allows dispatch to proceed.
See Also
- Operating Modes — General enforce vs mutate operating mechanics.
- Rule Types Reference —
RequiredMetadataRuleconfiguration details. - Family Recipes Catalog — Gemini 3 and Gemini 2.5 recipe definitions.