Firmas de pensamiento

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., text o functionCall partes).

Como regla general, si recibes una firma de pensamiento en una respuesta del modelo, debes volver a pasarla exactamente como la recibiste cuando envíes el historial de conversaciones en el siguiente turno. Cuando uses modelos de Gemini 3, debes volver a pasar 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.

Diagrama de turnos y pasos de la llamada a función

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 muestra 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 muestra 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 volver a pasar todas las firmas.
  • Las respuestas del modelo sin una llamada a función mostrarán una firma de pensamiento dentro de la última parte que muestra 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

(no FCs)

Ninguno

Firmas en 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 función única: La parte functionCall contendrá una thought_signature.
    • Llamadas a funciones paralelas: Si el modelo genera llamadas a funciones paralelas en una respuesta, la thought_signature se adjunta solo a la primera functionCall parte. Las partes functionCall posteriores en la misma respuesta no contendrán una firma.
  • Requisito: Debes mostrar esta firma en la parte exacta en la que se recibió cuando envíes el historial de conversaciones.
  • 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 regresa al historial (del más reciente al más antiguo) para encontrar el mensaje User más reciente que contenga contenido estándar (p.ej., text) ( que sería el inicio del turno actual). Esto no be una functionResponse.
    • Se considera que todos los turnos functionCall del modelo que ocurren después de ese mensaje de uso específico forman parte del turno.
    • La primera functionCall parte en cada paso del turno actual debe incluir su thought_signature.
    • Si omites un thought_signature para la primera parte functionCall en cualquier paso del turno actual, la solicitud fallará con un error 400.
  • Si no se muestran 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:
      • La llamada a función <Function Call> en el <index of contents array> bloque de contenido no tiene una thought_signature. Por ejemplo, la llamada a función FC1 en el bloque de contenido 1. no tiene una thought_signature.

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

(no FCs)

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 un 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 el modelo realiza la validación.

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 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 mostrar 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 muestra el modelo puede contener una thought_signature.
  • Recomendación: Se recomienda mostrar 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 contextual (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

FC2 ("London")

FR1

1

2

request 2 = request1 + FC1 ("Paris") + signature + FC2 ("London") text_output

(no FCs)

None

El siguiente código explica 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 el modelo realiza la validación.

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)

None

Este es el código para explicar 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

  1. ¿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, por ejemplo, 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.

  2. Devuelvo llamadas a funciones y respuestas paralelas intercaladas, y la API muestra un error 400. ¿Por qué?

    Cuando la API muestra 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 mostrará un error 400.

  3. Cuando se transmite y el modelo no muestra 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 mostrar la firma de pensamiento en una parte con una parte de contenido de texto vacío parte. Se recomienda analizar toda la solicitud hasta que el finish_reason muestre el modelo.

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 mostrar esa parte.
    • Gemini 2.5 tendrá la firma en la primera parte (independientemente del tipo). Es opcional mostrar 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.