Las firmas de pensamiento son representaciones cifradas del proceso de pensamiento interno del modelo. Las firmas de pensamiento conservan el estado de razonamiento de Gemini durante las conversaciones de varios turnos y pasos, lo que puede ser útil al usar llamadas a funciones. Las respuestas pueden incluir un campo thought_signature en cualquier parte del contenido (por ejemplo, text, functionCall).
Gemini 3 Pro aplica una validación más estricta a las firmas de pensamiento que las versiones anteriores de Gemini, ya que mejoran el rendimiento del modelo en las llamadas a funciones. Para asegurarte de que el modelo mantiene el contexto completo en varias interacciones de una conversación, debes devolver las firmas de pensamiento de las respuestas anteriores en tus solicitudes posteriores.
Si no se devuelve una firma de pensamiento obligatoria al usar Gemini 3 Pro, el modelo devuelve un error 400.
Gemini 3 Pro Image no aplica esta validación. Para asegurarte de que el modelo mantiene el contexto completo en varias interacciones de una conversación, debes devolver las firmas de pensamiento de las respuestas anteriores en tus solicitudes posteriores.
Gemini 3 Pro Image no devuelve un error 400 si no se devuelve una firma de pensamiento. Para ver ejemplos de código relacionados con la edición de imágenes en varias fases con Gemini 3 Pro Image, consulta Ejemplo de edición de imágenes en varias fases con firmas de pensamiento.
Si usas el SDK oficial de IA generativa de Google (Python, Node.js, Go o Java) y las funciones estándar del historial de chat o añades la respuesta completa del modelo al historial, las firmas de pensamiento se gestionan automáticamente.
¿Por qué son importantes?
Cuando un modelo de pensamiento llama a una herramienta externa, pausa su proceso de razonamiento interno. La firma de pensamiento actúa como un "estado de guardado", lo que permite al modelo reanudar su cadena de pensamiento sin problemas una vez que proporciones el resultado de la función. Sin firmas de pensamiento, el modelo "olvida" los pasos de razonamiento específicos durante la fase de ejecución de la herramienta. Al devolver la firma, se asegura lo siguiente:
- Continuidad del contexto: el modelo conserva y puede comprobar los pasos de razonamiento que justificaron la llamada a la herramienta.
- Razonamiento complejo: permite realizar tareas de varios pasos en las que el resultado de una herramienta influye en el razonamiento de la siguiente.
Giros y pasos
En el contexto de las llamadas a funciones, es importante entender la diferencia entre turnos y pasos:
- Un turno representa un intercambio completo de una conversación, que empieza con la petición de un usuario y termina cuando el modelo proporciona una respuesta final que no es una llamada a una función a esa petición.
- Un paso se produce en un solo turno cuando el modelo invoca una función y requiere una respuesta de la función para continuar su proceso de razonamiento. Como se muestra en el diagrama, un solo turno puede implicar varios pasos si el modelo necesita llamar a varias funciones de forma secuencial para cumplir la solicitud del usuario.
Cómo usar las firmas de pensamiento
La forma más sencilla de gestionar las firmas de pensamiento es incluir todas las Parts de todos los mensajes anteriores del historial de la conversación al enviar una nueva solicitud, exactamente como las devolvió el modelo.
Si no usas uno de los SDKs de IA generativa de Google o necesitas modificar o recortar el historial de conversaciones, debes asegurarte de que las firmas de pensamientos se conserven y se envíen de nuevo al modelo.
Si usas el SDK de IA generativa de Google (opción recomendada)
Cuando se usan las funciones del historial de chat de los SDKs o se añade el objeto content del modelo de la respuesta anterior al contents de la siguiente solicitud, las firmas se gestionan automáticamente.
En el siguiente ejemplo de Python se muestra cómo se gestiona automáticamente:
from google import genai
from google.genai.types import Content, FunctionDeclaration, GenerateContentConfig, Part, ThinkingConfig, Tool
client = genai.Client()
# 1. Define your tool
get_weather_declaration = FunctionDeclaration(
name="get_weather",
description="Gets the current weather temperature for a given location.",
parameters={
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"],
},
)
get_weather_tool = Tool(function_declarations=[get_weather_declaration])
# 2. Send a message that triggers the tool
prompt = "What's the weather like in London?"
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=prompt,
config=GenerateContentConfig(
tools=[get_weather_tool],
thinking_config=ThinkingConfig(include_thoughts=True)
),
)
# 3. Handle the function call
function_call = response.function_calls[0]
location = function_call.args["location"]
print(f"Model wants to call: {function_call.name}")
# Execute your tool (for example, call an API)
# (This is a mock response for the example)
print(f"Calling external tool for: {location}")
function_response_data = {
"location": location,
"temperature": "30C",
}
# 4. Send the tool's result back
# Append this turn's messages to history for a final response.
# The `content` object automatically attaches the required thought_signature behind the scenes.
history = [
Content(role="user", parts=[Part(text=prompt)]),
response.candidates[0].content, # Signature preserved here
Content(
role="tool",
parts=[
Part.from_function_response(
name=function_call.name,
response=function_response_data,
)
],
)
]
response_2 = client.models.generate_content(
model="gemini-2.5-flash",
contents=history,
config=GenerateContentConfig(
tools=[get_weather_tool],
thinking_config=ThinkingConfig(include_thoughts=True)
),
)
# 5. Get the final, natural-language answer
print(f"\nFinal model response: {response_2.text}")
Cuando se usa REST o la gestión manual
Si interactúas directamente con la API, debes implementar la gestión de firmas según las siguientes reglas de Gemini 3 Pro:
- Llamadas a funciones:
- Si la respuesta del modelo contiene una o varias partes
functionCall, se necesita unthought_signaturepara que se procese correctamente. - En los casos de llamadas de funciones paralelas en una sola respuesta, solo la primera parte
functionCallcontendrá elthought_signature. - En los casos de llamadas a funciones secuenciales en varios pasos de un turno, cada parte
functionCallcontendrá unthought_signature. - Regla: Cuando construyas la siguiente solicitud, debes incluir el
partque contiene elfunctionCally suthought_signatureexactamente como lo ha devuelto el modelo. En el caso de las llamadas a funciones secuenciales (de varios pasos), la validación se realiza en todos los pasos del turno actual. Si se omite unthought_signatureobligatorio para la primera partefunctionCallen cualquier paso del turno actual, se produce un error400. Un turno empieza con el mensaje de usuario más reciente que no sea unfunctionResponse. - Si el modelo devuelve llamadas de función paralelas (por ejemplo,
FC1+signatureyFC2), tu respuesta debe contener todas las llamadas de función seguidas de todas las respuestas de función (FC1+signature,FC2,FR1yFR2). Si se intercalan las respuestas (FC1+signature,FR1,FC2yFR2), se producirá un error400. - En raras ocasiones, es necesario proporcionar partes de
functionCallque no haya generado la API y, por lo tanto, no tengan una firma de pensamiento asociada (por ejemplo, al transferir el historial de un modelo que no incluya firmas de pensamiento). Puede definir el valorthought_signatureenskip_thought_signature_validator, pero esto debería ser un último recurso, ya que afectará negativamente al rendimiento del modelo.
- Si la respuesta del modelo contiene una o varias partes
- Llamadas a elementos que no son funciones:
- Si la respuesta del modelo no contiene un
functionCall, puede incluir unthought_signatureen el últimopartde la respuesta (por ejemplo, la última partetext). - Regla: Se recomienda incluir esta firma en la siguiente solicitud para obtener el mejor rendimiento posible, pero si no lo hace, no se producirá ningún error. Durante la transmisión, esta firma se puede devolver en una parte con contenido de texto vacío, por lo que debes analizar todas las partes hasta que el modelo devuelva
finish_reason.
- Si la respuesta del modelo no contiene un
Sigue estas reglas para asegurarte de que se conserva el contexto del modelo:
- Envía siempre el
thought_signaturede vuelta al modelo dentro de suPartoriginal. - No combines un
Partque contenga una firma con uno que no la tenga. Esto rompe el contexto posicional del pensamiento. - No combines dos
Parts que contengan firmas, ya que las cadenas de firma no se pueden combinar.
Ejemplo de llamada a funciones secuencial
En el siguiente ejemplo se muestra una llamada a función de varios pasos en la que el usuario pregunta "Consulta el estado del vuelo AA100 y pide un taxi si se retrasa", lo que requiere varias tareas.
REST
En el siguiente ejemplo se muestra cómo gestionar las firmas de pensamientos en varios pasos de un flujo de trabajo de llamadas a funciones secuenciales mediante la API REST.
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 un functionResponse (no hay texto nuevo), seguimos en el turno 1. Debes 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>" } ] }, { "role": "user", "parts": [ { "functionResponse": { "name": "check_flight", "response": { "status": "delayed", "departure_time": "12 PM" } } } ] }
Turno 1, paso 2 (respuesta del modelo)
Ahora, el modelo decide reservar un taxi basándose en 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 (respuesta del usuario: envío de la salida de la herramienta)
Para enviar la confirmación de la reserva del taxi, debes incluir firmas para todas las llamadas a funciones de este bucle (<SIGNATURE_A> y <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>" } ] }, { "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>" } ] }, { "role": "user", "parts": [ { "functionResponse": { "name": "book_taxi", "response": { "booking_status": "success" } } } ] } }
Completaciones de chat
En el siguiente ejemplo se muestra cómo gestionar las firmas de pensamientos en varios pasos de un flujo de trabajo de llamadas a funciones secuenciales mediante la API Chat Completions.
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 (no hay texto nuevo), seguimos en el turno 1. Debes 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>" } }, "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 (respuesta del modelo)
Ahora, el modelo decide reservar un taxi basándose en 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 (respuesta del usuario: envío de la salida de la herramienta)
Para enviar la confirmación de la reserva del taxi, debes incluir firmas para todas las llamadas a funciones de este bucle (<SIGNATURE_A> y <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>" } }, "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>" } }, "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 funciones en paralelo
En el siguiente ejemplo se muestra una llamada a funciones en paralelo en la que el usuario pregunta "¿Qué tiempo hace en París y Londres?".
REST
En el siguiente ejemplo se muestra cómo gestionar las firmas de pensamientos en un flujo de trabajo de llamadas a funciones paralelas mediante la API REST.
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>" }, { "functionCall": { "name": "get_current_temperature", "args": { "location": "London" } } } ] } }
Turno 1, paso 2 (respuesta del usuario: envío de resultados de herramientas)
Debes conservar <SIGNATURE_A> en la primera parte exactamente como se ha recibido.
[ { "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>" }, { "functionCall": { "name": "get_current_temperature", "args": { "city": "London" } } } ] }, { "role": "user", "parts": [ { "functionResponse": { "name": "get_current_temperature", "response": { "temp": "15C" } } }, { "functionResponse": { "name": "get_current_temperature", "response": { "temp": "12C" } } } ] } ]
Completaciones de chat
En el siguiente ejemplo se muestra cómo gestionar las firmas de pensamientos en un flujo de trabajo de llamadas a funciones paralelas mediante la API Chat Completions.
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>" } }, "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" } ] }
Turno 1, paso 2 (respuesta del usuario: envío de resultados de herramientas)
Debes conservar <SIGNATURE_A> en la primera parte exactamente como se ha recibido.
"messages": [ { "role": "user", "content": "Check the weather in Paris and London." }, { "role": "assistant", "tool_calls": [ { "extra_content": { "google": { "thought_signature": "<SIGNATURE_A>" } }, "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" } ] }, { "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\"}" } ]
Firmas en functionCall Parts
Gemini también puede devolver un thought_signature en el Part final de una respuesta, aunque no haya ninguna llamada a función.
- Comportamiento: el contenido final
Part(text,inlineData, etc.) devuelto por el modelo puede contener unthought_signature. - Requisito: Se recomienda devolver esta firma para asegurarse de que el modelo mantiene un razonamiento de alta calidad, especialmente en el caso de instrucciones complejas o flujos de trabajo de agentes simulados.
- Validación: la API no aplica estrictamente la validación de las firmas en las partes que no son
functionCall. No recibirás un error de bloqueo si los omites, aunque el rendimiento puede verse afectado.
Ejemplo de respuesta del modelo con firma en la parte de texto:
En los siguientes ejemplos se muestra una respuesta de modelo en la que se incluye un thought_signature en un Part que no es functionCall y cómo gestionarlo en una solicitud posterior.
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." }] } ]
Ejemplo de edición de imágenes en varias interacciones con firmas de pensamiento
En los siguientes ejemplos se muestra cómo obtener y transferir firmas de pensamiento durante la creación y edición de imágenes en varias fases con Gemini 3 Pro Image.
Turno 1: Obtener la respuesta y guardar los datos que incluyen firmas de pensamiento
chat = client.chats.create( model="gemini-3-pro-image-preview", config=types.GenerateContentConfig( response_modalities=['TEXT', 'IMAGE'] ) ) message = "Create an image of a clear perfume bottle sitting on a vanity." response = chat.send_message(message) data = b'' for part in response.candidates[0].content.parts: if part.text: display(Markdown(part.text)) if part.inline_data: data = part.inline_data.data display(Image(data=data, width=500))
Turno 2: pasa los datos que incluyen firmas de pensamiento
response = chat.send_message( message=[ types.Part.from_bytes( data=data, mime_type="image/png", ), "Make the perfume bottle purple and add a vase of hydrangeas next to the bottle.", ], ) for part in response.candidates[0].content.parts: if part.text: display(Markdown(part.text)) if part.inline_data: display(Image(data=part.inline_data.data, width=500))
Siguientes pasos
- Consulta más información sobre Thinking.
- Más información sobre la llamada a funciones
- Consulta cómo diseñar peticiones multimodales.