Las firmas de pensamiento son representaciones encriptadas del proceso de pensamiento interno del modelo y se usan para preservar el contexto de razonamiento en las interacciones de varios turnos.
Cuando se usan modelos de pensamiento (como las series de Gemini 3 y 2.5), la API puede devolver un campo thoughtSignature dentro de las partes de contenido de la respuesta (p.ej., text o functionCall).
Como regla general, si recibes una firma de pensamiento en la respuesta de un modelo, debes devolverla exactamente como la recibiste cuando envíes el historial de conversación en el siguiente turno. Cuando uses Gemini 3 Pro, debes devolver las firmas de pensamiento durante la llamada a la función; de lo contrario, recibirás un error de validación (código de estado 4xx).
Cómo funciona
En el siguiente gráfico, se visualiza el significado de "turno" y "paso" en relación con la llamada a función en la API de Gemini. Un "turno" es un intercambio único y completo en una conversación entre un usuario y un modelo. Un "paso" es una acción u operación más detallada que realiza el modelo, a menudo como parte de un proceso más grande para completar un turno.

En este documento, se explica cómo controlar las llamadas a funciones de Gemini 3 Pro. Consulta la sección sobre el comportamiento del modelo para conocer las discrepancias con la versión 2.5.
Gemini 3 Pro devuelve firmas de pensamiento para todas las respuestas del modelo (respuestas de la API) con una llamada a función. Las firmas de pensamiento aparecen en los siguientes casos:
- Cuando hay llamadas a funciones paralelas, la primera parte de la llamada a función que devuelve la respuesta del modelo tendrá una firma de pensamiento.
- Cuando hay llamadas a funciones secuenciales (de varios pasos), cada llamada a función tendrá una firma y deberás devolver todas las firmas.
- Las respuestas del modelo sin una llamada a función devolverán una firma de pensamiento dentro de la última parte que devuelva el modelo.
En la siguiente tabla, se proporciona una visualización de las llamadas a funciones de varios pasos, en la que se combinan las definiciones de turnos y pasos con el concepto de firmas que se presentó anteriormente:
Turn |
Step |
Solicitud del usuario |
Respuesta del modelo |
FunctionResponse |
1 |
1 |
request1 = user_prompt |
FC1 + signature |
FR1 |
1 |
2 |
request2 = request1 + (FC1 + signature) + FR1 |
FC2 + signature |
FR2 |
1 |
3 |
request3 = request2 + (FC2 + signature) + FR2 |
text_output
|
Ninguno |
Firmas en las partes de llamadas a funciones
Cuando Gemini genera un functionCall, se basa en el thought_signature para procesar correctamente el resultado de la herramienta en el siguiente turno.
- Comportamiento:
- Llamada a una sola función: La parte
functionCallcontendrá unthought_signature. - Llamadas a funciones paralelas: Si el modelo genera llamadas a funciones paralelas en una respuesta, el
thought_signaturese adjunta solo a la primera parte defunctionCall. Las partesfunctionCallposteriores de la misma respuesta no contendrán una firma.
- Llamada a una sola función: La parte
- Requisito: Debes devolver esta firma en la parte exacta en la que se recibió cuando envíes el historial de conversación.
- Validación: Se aplica una validación estricta para todas las llamadas a funciones dentro del turno actual . (Solo se requiere el turno actual; no validamos los turnos anteriores)
- La API retrocede en el historial (del más reciente al más antiguo) para encontrar el mensaje de User más reciente que contiene contenido estándar (p.ej.,
text) ( que sería el comienzo del turno actual). No be unfunctionResponse. - Todas las respuestas del modelo All que se producen después de ese mensaje de uso específico se consideran parte de la respuesta.
functionCall - La primera parte
functionCallen cada paso del turno actual debe incluir suthought_signature. - Si omites un
thought_signaturepara la primera parte defunctionCallen cualquier paso del turno actual, la solicitud fallará con un error 400.
- La API retrocede en el historial (del más reciente al más antiguo) para encontrar el mensaje de User más reciente que contiene contenido estándar (p.ej.,
- Si no se devuelven las firmas adecuadas, así se producirá el error
gemini-3-pro-preview: Si no se incluyen firmas, se generará un error 400. La redacción tendrá el siguiente formato:- La llamada a la función
<Function Call>en el bloque de contenido<index of contents array>no incluye unthought_signature. Por ejemplo, Falta unthought_signatureen la llamada a la funciónFC1del bloque de contenido1..
- La llamada a la función
Ejemplo de llamada a función secuencial
En esta sección, se muestra un ejemplo de varias llamadas a funciones en el que el usuario hace una pregunta compleja que requiere varias tareas.
Veamos un ejemplo de llamada a función de varios turnos en el que el usuario hace una pregunta compleja que requiere varias tareas: "Check flight status for AA100 and
book a taxi if delayed".
Turn |
Step |
Solicitud del usuario |
Respuesta del modelo |
FunctionResponse |
1 |
1 |
request1="Check flight status for AA100 and book a taxi 2 hours before if delayed." |
FC1 ("check_flight") + signature |
FR1 |
1 |
2 |
request2 = request1 + FC1 ("check_flight") + signature + FR1 |
FC2("book_taxi") + signature |
FR2 |
1 |
3 |
request3 = request2 + FC2 ("book_taxi") + signature + FR2 |
text_output
|
None |
El siguiente código ilustra la secuencia de la tabla anterior.
Turno 1, paso 1 (solicitud del usuario)
{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Check flight status for AA100 and book a taxi 2 hours before if delayed."
}
]
}
],
"tools": [
{
"functionDeclarations": [
{
"name": "check_flight",
"description": "Gets the current status of a flight",
"parameters": {
"type": "object",
"properties": {
"flight": {
"type": "string",
"description": "The flight number to check"
}
},
"required": [
"flight"
]
}
},
{
"name": "book_taxi",
"description": "Book a taxi",
"parameters": {
"type": "object",
"properties": {
"time": {
"type": "string",
"description": "time to book the taxi"
}
},
"required": [
"time"
]
}
}
]
}
]
}
Turn 1, Step 1 (Model response)
{
"content": {
"role": "model",
"parts": [
{
"functionCall": {
"name": "check_flight",
"args": {
"flight": "AA100"
}
},
"thoughtSignature": "<Signature A>"
}
]
}
}
Turn 1, Step 2 (User response - Sending tool outputs) Dado que este turno del usuario solo contiene un functionResponse (sin texto nuevo), seguimos en el turno 1. Debemos preservar <Signature_A>.
{
"role": "user",
"parts": [
{
"text": "Check flight status for AA100 and book a taxi 2 hours before if delayed."
}
]
},
{
"role": "model",
"parts": [
{
"functionCall": {
"name": "check_flight",
"args": {
"flight": "AA100"
}
},
"thoughtSignature": "<Signature A>" //Required and Validated
}
]
},
{
"role": "user",
"parts": [
{
"functionResponse": {
"name": "check_flight",
"response": {
"status": "delayed",
"departure_time": "12 PM"
}
}
}
]
}
Turn 1, Step 2 (Model) Ahora, el modelo decide reservar un taxi según el resultado de la herramienta anterior.
{
"content": {
"role": "model",
"parts": [
{
"functionCall": {
"name": "book_taxi",
"args": {
"time": "10 AM"
}
},
"thoughtSignature": "<Signature B>"
}
]
}
}
Turn 1, Step 3 (User - Sending tool output) Para enviar la confirmación de la reserva de taxi, debemos incluir firmas para TODAS las llamadas a funciones en este bucle (<Signature A> + <Signature B>).
{
"role": "user",
"parts": [
{
"text": "Check flight status for AA100 and book a taxi 2 hours before if delayed."
}
]
},
{
"role": "model",
"parts": [
{
"functionCall": {
"name": "check_flight",
"args": {
"flight": "AA100"
}
},
"thoughtSignature": "<Signature A>" //Required and Validated
}
]
},
{
"role": "user",
"parts": [
{
"functionResponse": {
"name": "check_flight",
"response": {
"status": "delayed",
"departure_time": "12 PM"
}
}
}
]
},
{
"role": "model",
"parts": [
{
"functionCall": {
"name": "book_taxi",
"args": {
"time": "10 AM"
}
},
"thoughtSignature": "<Signature B>" //Required and Validated
}
]
},
{
"role": "user",
"parts": [
{
"functionResponse": {
"name": "book_taxi",
"response": {
"booking_status": "success"
}
}
}
]
}
}
Ejemplo de llamada a función paralela
Analicemos un ejemplo de llamada a función paralela en el que los usuarios le piden a "Check weather in Paris and London" que muestre dónde el modelo realiza la validación.
Turn |
Step |
Solicitud del usuario |
Respuesta del modelo |
FunctionResponse |
|---|---|---|---|---|
1 |
1 |
request1="Consulta el clima en París y Londres" |
FC1 (“París”) + firma FC2 ("Londres") |
FR1 |
1 |
2 |
solicitud 2 = solicitud1 + FC1 (“París”) + firma + FC2 (“Londres”) |
text_output (sin FC) |
Ninguno |
El siguiente código ilustra la secuencia de la tabla anterior.
Turno 1, paso 1 (solicitud del usuario)
{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Check the weather in Paris and London."
}
]
}
],
"tools": [
{
"functionDeclarations": [
{
"name": "get_current_temperature",
"description": "Gets the current temperature for a given location.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name, e.g. San Francisco"
}
},
"required": [
"location"
]
}
}
]
}
]
}
Turn 1, Step 1 (Model response)
{
"content": {
"parts": [
{
"functionCall": {
"name": "get_current_temperature",
"args": {
"location": "Paris"
}
},
"thoughtSignature": "<Signature_A>"// INCLUDED on First FC
},
{
"functionCall": {
"name": "get_current_temperature",
"args": {
"location": "London"
}// NO signature on subsequent parallel FCs
}
}
]
}
}
Turn 1, Step 2 (User response - Sending tool outputs) Debemos conservar <Signature_A> en la primera parte exactamente como se recibió.
[
{
"role": "user",
"parts": [
{
"text": "Check the weather in Paris and London."
}
]
},
{
"role": "model",
"parts": [
{
"functionCall": {
"name": "get_current_temperature",
"args": {
"city": "Paris"
}
},
"thought_signature": "<Signature_A>" // MUST BE INCLUDED
},
{
"functionCall": {
"name": "get_current_temperature",
"args": {
"city": "London"
}
}
} // NO SIGNATURE FIELD
]
},
{
"role": "user",
"parts": [
{
"functionResponse": {
"name": "get_current_temperature",
"response": {
"temp": "15C"
}
}
},
{
"functionResponse": {
"name": "get_current_temperature",
"response": {
"temp": "12C"
}
}
}
]
}
]
Firmas en partes que no son functionCall
Gemini también puede devolver thought_signatures en la parte final de la respuesta en las partes que no son de llamadas a funciones.
- Comportamiento: La parte final del contenido (
text, inlineData…) que devuelve el modelo puede contener unthought_signature. - Recomendación: Se recomienda devolver estas firmas para garantizar que el modelo mantenga un razonamiento de alta calidad, especialmente para el seguimiento de instrucciones complejas o los flujos de trabajo de agentes simulados.
- Validación: La API no aplica la validación de forma estricta. No recibirás un error de bloqueo si los omites, aunque el rendimiento puede disminuir.
Texto/Razonamiento en contexto (sin validación)
Turn 1, Step 1 (Model response)
{
"role": "model",
"parts": [
{
"text": "I need to calculate the risk. Let me think step-by-step...",
"thought_signature": "<Signature_C>" // OPTIONAL (Recommended)
}
]
}
Turn 2, Step 1 (User)
[
{ "role": "user", "parts": [{ "text": "What is the risk?" }] },
{
"role": "model",
"parts": [
{
"text": "I need to calculate the risk. Let me think step-by-step...",
// If you omit <Signature_C> here, no error will occur.
}
]
},
{ "role": "user", "parts": [{ "text": "Summarize it." }] }
]
Firmas para la compatibilidad con OpenAI
En los siguientes ejemplos, se muestra cómo controlar las firmas de pensamiento para una API de finalización de chat con compatibilidad con OpenAI.
Ejemplo de llamada a función secuencial
Este es un ejemplo de llamada a varias funciones en el que el usuario hace una pregunta compleja que requiere varias tareas.
Veamos un ejemplo de llamada a función de varios turnos en el que el usuario pregunta Check flight status for AA100 and book a taxi if delayed y puedes ver qué sucede cuando el usuario hace una pregunta compleja que requiere varias tareas.
Turn |
Step |
Solicitud del usuario |
Respuesta del modelo |
FunctionResponse |
1 |
1 |
request1="Check the weather in Paris and London" |
FC1 ("Paris") + signature
|
FR1 |
1 |
2 |
request 2 = request1 + FC1 ("Paris") + signature + FC2 ("London") |
text_output
|
None |
El siguiente código recorre la secuencia determinada.
Turno 1, paso 1 (solicitud del usuario)
{
"model": "google/gemini-3-pro-preview",
"messages": [
{
"role": "user",
"content": "Check flight status for AA100 and book a taxi 2 hours before if delayed."
}
],
"tools": [
{
"type": "function",
"function": {
"name": "check_flight",
"description": "Gets the current status of a flight",
"parameters": {
"type": "object",
"properties": {
"flight": {
"type": "string",
"description": "The flight number to check."
}
},
"required": [
"flight"
]
}
}
},
{
"type": "function",
"function": {
"name": "book_taxi",
"description": "Book a taxi",
"parameters": {
"type": "object",
"properties": {
"time": {
"type": "string",
"description": "time to book the taxi"
}
},
"required": [
"time"
]
}
}
}
]
}
Turno 1, paso 1 (respuesta del modelo)
{
"role": "model",
"tool_calls": [
{
"extra_content": {
"google": {
"thought_signature": "<Signature A>"
}
},
"function": {
"arguments": "{\"flight\":\"AA100\"}",
"name": "check_flight"
},
"id": "function-call-1",
"type": "function"
}
]
}
Turno 1, paso 2 (respuesta del usuario: envío de resultados de herramientas)
Como este turno del usuario solo contiene un functionResponse (sin texto nuevo), seguimos en el turno 1 y debemos conservar <Signature_A>.
"messages": [
{
"role": "user",
"content": "Check flight status for AA100 and book a taxi 2 hours before if delayed."
},
{
"role": "model",
"tool_calls": [
{
"extra_content": {
"google": {
"thought_signature": "<Signature A>" //Required and Validated
}
},
"function": {
"arguments": "{\"flight\":\"AA100\"}",
"name": "check_flight"
},
"id": "function-call-1",
"type": "function"
}
]
},
{
"role": "tool",
"name": "check_flight",
"tool_call_id": "function-call-1",
"content": "{\"status\":\"delayed\",\"departure_time\":\"12 PM\"}"
}
]
Turn 1, Step 2 (Model)
Ahora, el modelo decide reservar un taxi según el resultado anterior de la herramienta.
{
"role": "model",
"tool_calls": [
{
"extra_content": {
"google": {
"thought_signature": "<Signature B>"
}
},
"function": {
"arguments": "{\"time\":\"10 AM\"}",
"name": "book_taxi"
},
"id": "function-call-2",
"type": "function"
}
]
}
Turn 1, Step 3 (User - Sending Tool Output)
Para enviar la confirmación de la reserva de taxi, debemos incluir firmas para TODAS las llamadas a funciones en este bucle (<Signature A> + <Signature B>).
"messages": [
{
"role": "user",
"content": "Check flight status for AA100 and book a taxi 2 hours before if delayed."
},
{
"role": "model",
"tool_calls": [
{
"extra_content": {
"google": {
"thought_signature": "<Signature A>" //Required and Validated
}
},
"function": {
"arguments": "{\"flight\":\"AA100\"}",
"name": "check_flight"
},
"id": "function-call-1d6a1a61-6f4f-4029-80ce-61586bd86da5",
"type": "function"
}
]
},
{
"role": "tool",
"name": "check_flight",
"tool_call_id": "function-call-1d6a1a61-6f4f-4029-80ce-61586bd86da5",
"content": "{\"status\":\"delayed\",\"departure_time\":\"12 PM\"}"
},
{
"role": "model",
"tool_calls": [
{
"extra_content": {
"google": {
"thought_signature": "<Signature B>" //Required and Validated
}
},
"function": {
"arguments": "{\"time\":\"10 AM\"}",
"name": "book_taxi"
},
"id": "function-call-65b325ba-9b40-4003-9535-8c7137b35634",
"type": "function"
}
]
},
{
"role": "tool",
"name": "book_taxi",
"tool_call_id": "function-call-65b325ba-9b40-4003-9535-8c7137b35634",
"content": "{\"booking_status\":\"success\"}"
}
]
Ejemplo de llamada a función paralela
Analicemos un ejemplo de llamada a función paralela en el que el usuario pregunta "Check weather in Paris and London" y puedes ver dónde el modelo realiza la validación.
Turn |
Step |
Solicitud del usuario |
Respuesta del modelo |
FunctionResponse |
1 |
1 |
request1="Check the weather in Paris and London" |
FC1 ("Paris") + signature
|
FR1 |
1 |
2 |
request 2 = request1 + FC1 ("Paris") + signature + FC2 ("London") |
text_output
|
None |
Este es el código para recorrer la secuencia determinada.
Turno 1, paso 1 (solicitud del usuario)
{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Check the weather in Paris and London."
}
]
}
],
"tools": [
{
"functionDeclarations": [
{
"name": "get_current_temperature",
"description": "Gets the current temperature for a given location.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name, e.g. San Francisco"
}
},
"required": [
"location"
]
}
}
]
}
]
}
Turno 1, paso 1 (respuesta del modelo)
{
"role": "assistant",
"tool_calls": [
{
"extra_content": {
"google": {
"thought_signature": "<Signature A>" //Signature returned
}
},
"function": {
"arguments": "{\"location\":\"Paris\"}",
"name": "get_current_temperature"
},
"id": "function-call-f3b9ecb3-d55f-4076-98c8-b13e9d1c0e01",
"type": "function"
},
{
"function": {
"arguments": "{\"location\":\"London\"}",
"name": "get_current_temperature"
},
"id": "function-call-335673ad-913e-42d1-bbf5-387c8ab80f44",
"type": "function" // No signature on Parallel FC
}
]
}
Turno 1, paso 2 (respuesta del usuario: envío de resultados de herramientas)
Debes conservar <Signature_A> en la primera parte exactamente como se recibió.
"messages": [
{
"role": "user",
"content": "Check the weather in Paris and London."
},
{
"role": "assistant",
"tool_calls": [
{
"extra_content": {
"google": {
"thought_signature": "<Signature A>" //Required
}
},
"function": {
"arguments": "{\"location\":\"Paris\"}",
"name": "get_current_temperature"
},
"id": "function-call-f3b9ecb3-d55f-4076-98c8-b13e9d1c0e01",
"type": "function"
},
{
"function": { //No Signature
"arguments": "{\"location\":\"London\"}",
"name": "get_current_temperature"
},
"id": "function-call-335673ad-913e-42d1-bbf5-387c8ab80f44",
"type": "function"
}
]
},
{
"role":"tool",
"name": "get_current_temperature",
"tool_call_id": "function-call-f3b9ecb3-d55f-4076-98c8-b13e9d1c0e01",
"content": "{\"temp\":\"15C\"}"
},
{
"role":"tool",
"name": "get_current_temperature",
"tool_call_id": "function-call-335673ad-913e-42d1-bbf5-387c8ab80f44",
"content": "{\"temp\":\"12C\"}"
}
]
Preguntas frecuentes
¿Cómo transfiero el historial de un modelo diferente a Gemini 3 Pro con una parte de llamada a función en el turno y el paso actuales? ¿Necesito proporcionar partes de llamadas a funciones que no generó la API y, por lo tanto, no tienen una firma de pensamiento asociada?
Si bien se recomienda no insertar bloques de llamadas a funciones personalizadas en la solicitud, en los casos en que no se pueda evitar, p.ej., proporcionar información al modelo sobre las llamadas a funciones y las respuestas que el cliente ejecutó de forma determinística, o transferir un registro de otro modelo que no incluya firmas de pensamiento, puedes establecer las siguientes firmas ficticias de
"context_engineering_is_the_way_to_go"o"skip_thought_signature_validator"en el campo de firma de pensamiento para omitir la validación.Envío llamadas y respuestas a funciones paralelas intercaladas, y la API devuelve un error 400. ¿Por qué?
Cuando la API devuelve llamadas a funciones paralelas "FC1 + firma, FC2", la respuesta del usuario esperada es "FC1 + firma, FC2, FR1, FR2". Si los tienes intercalados como "FC1 + firma, FR1, FC2, FR2", la API devolverá un error 400.
Cuando se transmite y el modelo no devuelve una llamada a función, no puedo encontrar la firma de pensamiento
Durante una respuesta del modelo que no contiene una FC con una solicitud de transmisión, el modelo puede devolver la firma de pensamiento en una parte con una parte de contenido de texto vacía. Se recomienda analizar toda la solicitud hasta que el modelo devuelva
finish_reason.
Comportamiento de la firma de pensamiento por serie de modelos
Los modelos de Gemini 3 Pro y Gemini 2.5 se comportan de manera diferente con las firmas de pensamiento en las llamadas a funciones:
- Si hay llamadas a funciones en una respuesta,
- Gemini 3 Pro siempre tendrá la firma en la primera parte de la llamada a la función. Es obligatorio devolver esa parte.
- Gemini 2.5 tendrá la firma en la primera parte (independientemente del tipo). Es opcional devolver esa parte.
- Si no hay llamadas a funciones en una respuesta,
- Gemini 3 Pro tendrá la firma en la última parte si el modelo genera un pensamiento.
- Gemini 2.5 no tendrá firma en ninguna parte.
Para conocer el comportamiento de la firma de pensamiento de los modelos de Gemini 2.5, consulta la página Thinking.