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 pasos.
Cuando se usan modelos de pensamiento (como las series Gemini 3 y 2.5), la API puede
mostrar un campo thoughtSignature dentro de las partes de contenido
de la respuesta (p.ej., partes text o functionCall).
Como regla general, si recibes una firma de pensamiento en una respuesta del modelo, debes devolverla exactamente como la recibiste cuando envíes el historial de conversación en el siguiente turno.
Cuando uses modelos de Gemini 3, debes devolver las firmas de pensamiento durante la llamada a función; de lo contrario, recibirás un error de validación (código de estado 4xx).
Esto incluye cuando se usa la configuración de minimal
nivel de pensamiento para Gemini 3
Flash.
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.

Este documento se centra en el manejo de la llamada a función para los modelos de Gemini 3. Consulta la sección sobre el comportamiento del modelo para ver las discrepancias con la versión 2.5.
Gemini 3 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 (varios pasos), cada llamada a función tendrá una firma y debes 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 devuelve el modelo.
En la siguiente tabla, se proporciona una visualización de las llamadas a funciones de varios pasos, que combina las definiciones de turnos y pasos con el concepto de firmas que se presentó anteriormente:
Turn |
Step |
User Request |
Model Response |
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 partes de llamadas a funciones
Cuando Gemini genera una functionCall, se basa en la thought_signature para procesar correctamente el resultado de la herramienta en el siguiente turno.
- Comportamiento:
- Llamada a función única: La parte
functionCallcontendrá unathought_signature. - Llamadas a funciones paralelas: Si el modelo genera llamadas a funciones paralelas
en una respuesta, la
thought_signaturese adjunta solo a la primerafunctionCallparte. Las partesfunctionCallposteriores en la misma respuesta no contendrán una firma.
- Llamada a función única: 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 de
l turno actual . (Solo se requiere el turno actual; no validamos en turnos anteriores).
- La API vuelve al historial (del más reciente al más antiguo) para encontrar el mensaje Usuario más reciente que contenga contenido estándar (p.ej.,
text) ( que sería el inicio del turno actual). Esto be será unafunctionResponse. - Se considera que todos los turnos
functionCalldel modelo que ocurren después de ese mensaje de uso específico forman parte del turno. - La primera parte
functionCallen cada paso del turno actual debe incluir suthought_signature. - Si omites una
thought_signaturepara la primera partefunctionCallen cualquier paso del turno actual, la solicitud fallará con un error 400.
- La API vuelve al historial (del más reciente al más antiguo) para encontrar el mensaje Usuario más reciente que contenga contenido estándar (p.ej.,
- Si no se devuelven las firmas adecuadas, se producirá un error de la siguiente manera
- Modelos de Gemini 3: Si no se incluyen firmas, se producirá un error 400. La redacción tendrá el siguiente formato:
- Falta un
thought_signatureen la llamada a función<Function Call>en el bloque de contenido<index of contents array>. Por ejemplo, Falta unathought_signatureen la llamada a funciónFC1en el bloque de contenido1..
- Falta un
- Modelos de Gemini 3: Si no se incluyen firmas, se producirá un error 400. La redacción tendrá el siguiente formato:
Ejemplo de llamada a función secuencial
En esta sección, se muestra un ejemplo de varias llamadas a funciones en las 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 |
User Request |
Model Response |
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"
]
}
}
]
}
]
}
Turno 1, paso 1 (respuesta del modelo)
{
"content": {
"role": "model",
"parts": [
{
"functionCall": {
"name": "check_flight",
"args": {
"flight": "AA100"
}
},
"thoughtSignature": "<Signature A>"
}
]
}
}
Turno 1, paso 2 (respuesta del usuario: envío de resultados de herramientas) Como este turno del usuario solo contiene una functionResponse (sin texto nuevo), aún estamos en el turno 1. Debemos
conservar <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"
}
}
}
]
}
Turno 1, paso 2 (modelo) El modelo ahora 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>"
}
]
}
}
Turno 1, paso 3 (usuario: envío de resultados de herramientas) 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
Veamos un ejemplo de llamada a función paralela en el que el usuario pregunta
"Check weather in Paris and London" para ver dónde realiza la validación el modelo.
Turn |
Step |
User Request |
Model Response |
FunctionResponse |
|---|---|---|---|---|
1 |
1 |
request1="Check the weather in Paris and London" |
FC1 ("Paris") + signature FC2 ("London") |
FR1 |
1 |
2 |
request 2 = request1 + FC1 ("Paris") + signature + FC2 ("London") |
text_output (no FCs) |
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"
]
}
}
]
}
]
}
Turno 1, paso 1 (respuesta del modelo)
{
"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
}
}
]
}
}
Turno 1, paso 2 (respuesta del usuario: envío de resultados de herramientas) Debemos conservar
<Signature_A> en la primera parte exactamente como la recibimos.
[
{
"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 partes que no son de llamadas a funciones.
- Comportamiento: La parte final del contenido (
text, inlineData…) que devuelve el modelo puede contener unathought_signature. - Recomendación: Se recomienda devolver estas firmas para garantizar que el modelo mantenga un razonamiento de alta calidad, en especial 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.
Razonamiento de texto o en contexto (sin validación)
Turno 1, paso 1 (respuesta del modelo)
{
"role": "model",
"parts": [
{
"text": "I need to calculate the risk. Let me think step-by-step...",
"thought_signature": "<Signature_C>" // OPTIONAL (Recommended)
}
]
}
Turno 2, paso 1 (usuario)
[
{ "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 varias llamadas a funciones en las 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 |
User Request |
Model Response |
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.1-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), aún estamos 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\"}"
}
]
Turno 1, paso 2 (modelo)
El modelo ahora decide reservar un taxi según el resultado de la herramienta anterior.
{
"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"
}
]
}
Turno 1, paso 3 (usuario: envío de resultados de herramientas)
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
Veamos 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 realiza el modelo
la validación.
Turn |
Step |
User Request |
Model Response |
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 la recibiste.
"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 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 determinista, o transferir un seguimiento de un modelo diferente que no incluya firmas de pensamiento, puedes configurar 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.Devuelvo llamadas a funciones y respuestas paralelas intercaladas, y la API devuelve un error 400. ¿Por qué?
Cuando la API devuelve llamadas a funciones paralelas "FC1 + signature, FC2", la respuesta del usuario esperada es "FC1+ signature, FC2, FR1, FR2". Si las tienes intercaladas como "FC1 + signature, 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 el
finish_reason.
Firmas de pensamiento para diferentes modelos
Los modelos de Gemini 3 y los modelos de 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 siempre tendrá la firma en la primera parte de la llamada a 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 tendrá la firma en la última parte si el modelo genera un pensamiento.
- Gemini 2.5 no tendrá una firma en ninguna parte.
Consulta la página Pensamiento para obtener más detalles de comparación. Para los modelos de imágenes de Gemini 3, consulta la sección sobre el proceso de pensamiento de la guía de generación de imágenes.