Assinaturas de pensamento

As assinaturas de pensamento são representações criptografadas do processo de pensamento interno do modelo e são usadas para preservar o contexto de raciocínio em interações de vários turnos. Ao usar modelos de pensamento (como as séries Gemini 3 e 2.5), a API pode retornar um campo thoughtSignature nas partes de conteúdo da resposta (por exemplo, text ou functionCall).

Como regra geral, se você receber uma assinatura de pensamento em uma resposta do modelo, transmita-a exatamente como foi recebida ao enviar o histórico da conversa na próxima vez. Ao usar o Gemini 3 Pro, é necessário transmitir assinaturas de pensamento durante a chamada de função. Caso contrário, você vai receber um erro de validação (código de status 4xx).

Como funciona

O gráfico abaixo mostra o significado de "rodada" e "etapa" em relação à chamada de função na API Gemini. Um "turno" é uma troca única e completa em uma conversa entre um usuário e um modelo. Uma "etapa" é uma ação ou operação mais refinada realizada pelo modelo, geralmente como parte de um processo maior para concluir uma interação.

Diagrama de turnos e etapas de chamada de função

Este documento se concentra no processamento de chamadas de função para o Gemini 3 Pro. Consulte a seção comportamento do modelo para ver discrepâncias com a versão 2.5.

O Gemini 3 Pro retorna assinaturas de pensamento para todas as respostas do modelo (respostas da API) com uma chamada de função. As assinaturas de pensamento aparecem nos seguintes casos:

  • Quando há chamadas de função paralelas, a primeira parte da chamada de função retornada pela resposta do modelo tem uma assinatura de pensamento.
  • Quando há chamadas de função sequenciais (várias etapas), cada uma tem uma assinatura, e você precisa transmitir todas as assinaturas de volta.
  • As respostas do modelo sem uma chamada de função vão retornar uma assinatura de pensamento na última parte retornada pelo modelo.

A tabela a seguir mostra uma visualização das chamadas de função de várias etapas, combinando as definições de turnos e etapas com o conceito de assinaturas apresentado acima:

Girar

Etapa

Solicitação do usuário

Resposta do 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

(no FCs)

Nenhum

Assinaturas em partes de chamada de função

Quando o Gemini gera um functionCall, ele depende do thought_signature para processar a saída da ferramenta corretamente na próxima vez.

  • Comportamento:
    • Chamada de função única: a parte functionCall vai conter um thought_signature.
    • Chamadas de função paralelas: se o modelo gerar chamadas de função paralelas em uma resposta, o thought_signature será anexado apenas à primeira parte functionCall. As partes functionCall subsequentes na mesma resposta não vão conter uma assinatura.
  • Requisito: você precisa retornar essa assinatura na mesma parte em que ela foi recebida ao enviar o histórico de conversas de volta.
  • Validação: a validação estrita é aplicada a todas as chamadas de função no turno atual . (Apenas a vez atual é obrigatória. Não validamos as vezes anteriores.)
    • A API volta no histórico (do mais recente ao mais antigo) para encontrar a mensagem User mais recente que contém conteúdo padrão (por exemplo, text), que seria o início da vez atual. Isso be será um functionResponse.
    • Todas as rodadas do modelo functionCall que ocorrem depois dessa mensagem de uso específica são consideradas parte da rodada.
    • A primeira parte functionCall em cada etapa da vez atual precisa incluir o thought_signature.
    • Se você omitir um thought_signature para a primeira parte functionCall em qualquer etapa da vez atual, a solicitação vai falhar com um erro 400.
  • Se as assinaturas adequadas não forem retornadas, veja como vai ocorrer um erro
    • gemini-3-pro-preview: se você não incluir assinaturas, vai receber um erro 400. A frase será deste formato:
      • A chamada de função <Function Call> no bloco de conteúdo <index of contents array> está sem um thought_signature. Por exemplo, A chamada de função FC1 no bloco de conteúdo 1. está sem um thought_signature.

Exemplo de chamada de função sequencial

Esta seção mostra um exemplo de várias chamadas de função em que o usuário faz uma pergunta complexa que exige várias tarefas.

Vamos analisar um exemplo de chamada de função de várias interações em que o usuário faz uma pergunta complexa que exige várias tarefas: "Check flight status for AA100 and book a taxi if delayed".

Girar

Etapa

Solicitação do usuário

Resposta do 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

(no FCs)

None

O código a seguir ilustra a sequência na tabela acima.

Turno 1, etapa 1 (solicitação do usuário)

{
  "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, etapa 1 (resposta do modelo)

{
"content": {
        "role": "model",
        "parts": [
          {
            "functionCall": {
              "name": "check_flight",
              "args": {
                "flight": "AA100"
              }
            },
            "thoughtSignature": "<Signature A>"
          }
        ]
  }
}

Turno 1, Etapa 2 (resposta do usuário: envio de saídas da ferramenta): como este turno do usuário contém apenas um functionResponse (sem texto novo), ainda estamos no Turno 1. Precisamos 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"
                }
              }
            }
        ]
}

Turno 1, etapa 2 (modelo): o modelo decide reservar um táxi com base na saída da ferramenta anterior.

{
      "content": {
        "role": "model",
        "parts": [
          {
            "functionCall": {
              "name": "book_taxi",
              "args": {
                "time": "10 AM"
              }
            },
            "thoughtSignature": "<Signature B>"
          }
        ]
      }
}

Turno 1, etapa 3 (usuário: envio da saída da ferramenta): para enviar a confirmação da reserva de táxi, precisamos incluir assinaturas para TODAS as chamadas de função neste loop (<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"
              }
              }
            }
        ]
    }
}

Exemplo de chamada de função paralela

Vamos analisar um exemplo de chamada de função paralela em que os usuários pedem "Check weather in Paris and London" para ver onde o modelo faz a validação.

Girar

Etapa

Solicitação do usuário

Resposta do modelo

FunctionResponse

1

1

request1="Confira a previsão do tempo em Paris e Londres"

FC1 ("Paris") + assinatura

FC2 ("Londres")

FR1

1

2

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

text_output

(sem FCs)

Nenhum

O código a seguir ilustra a sequência na tabela acima.

Turno 1, etapa 1 (solicitação do usuário)

{
  "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, etapa 1 (resposta do 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, etapa 2 (resposta do usuário: envio de saídas da ferramenta): precisamos preservar <Signature_A> na primeira parte exatamente como recebido.

[
  {
    "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"
          }
        }
      }
    ]
  }
]

Assinaturas em partes que não são functionCall

O Gemini também pode retornar thought_signatures na parte final da resposta em partes que não são de chamada de função.

  • Comportamento: a parte final do conteúdo (text, inlineData…) retornada pelo modelo pode conter um thought_signature.
  • Recomendação: retornar essas assinaturas é recomendado para garantir que o modelo mantenha um raciocínio de alta qualidade, especialmente para instruções complexas ou fluxos de trabalho de agentes simulados.
  • Validação: a API não aplica a validação de forma estrita. Você não vai receber um erro de bloqueio se omitir esses parâmetros, mas o desempenho pode ser prejudicado.

Texto/Raciocínio no contexto (sem validação)

Turno 1, etapa 1 (resposta do 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, etapa 1 (usuário)

[
  { "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." }] }
]

Assinaturas para compatibilidade com a OpenAI

Os exemplos a seguir mostram como processar assinaturas de pensamento para uma API Chat Completions usando a compatibilidade com a OpenAI.

Exemplo de chamada de função sequencial

Este é um exemplo de chamada de várias funções em que o usuário faz uma pergunta complexa que exige várias tarefas.

Vamos analisar um exemplo de chamada de função de várias interações em que o usuário pergunta Check flight status for AA100 and book a taxi if delayed e você pode ver o que acontece quando o usuário faz uma pergunta complexa que exige várias tarefas.

Girar

Etapa

Solicitação do usuário

Resposta do modelo

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

O código a seguir explica a sequência.

Turno 1, etapa 1 (solicitação do usuário)

{
  "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, etapa 1 (resposta do 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, etapa 2 (resposta do usuário: envio de saídas de ferramentas)

Como essa vez do usuário contém apenas um functionResponse (sem texto novo), ainda estamos na vez 1 e precisamos preservar <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)

Agora, o modelo decide reservar um táxi com base na saída da ferramenta 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"
          }
       ]
}

Turn 1, Step 3 (User - Sending Tool Output)

Para enviar a confirmação da reserva de táxi, precisamos incluir assinaturas para TODAS as chamadas de função neste loop (<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\"}"
    }
  ]

Exemplo de chamada de função paralela

Vamos analisar um exemplo de chamada de função paralela em que o usuário pergunta "Check weather in Paris and London" e você pode ver onde o modelo faz a validação.

Girar

Etapa

Solicitação do usuário

Resposta do modelo

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

Confira o código para percorrer a sequência especificada.

Turno 1, etapa 1 (solicitação do usuário)

{
  "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, etapa 1 (resposta do 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, etapa 2 (resposta do usuário: envio de saídas de ferramentas)

Preserve <Signature_A> na primeira parte exatamente como recebido.

"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\"}"
    }
  ]

Perguntas frequentes

  1. Como faço para transferir o histórico de um modelo diferente para o Gemini 3 Pro com uma parte de chamada de função na vez e etapa atuais? Preciso fornecer partes de chamada de função que não foram geradas pela API e, portanto, não têm uma assinatura de pensamento associada?

    Embora seja altamente desencorajado injetar blocos de chamada de função personalizados na solicitação, em casos em que isso não pode ser evitado, por exemplo, ao fornecer informações ao modelo sobre chamadas de função e respostas executadas deterministicamente pelo cliente ou ao transferir um rastreamento de um modelo diferente que não inclui assinaturas de pensamento, é possível definir as seguintes assinaturas fictícias de "context_engineering_is_the_way_to_go" ou "skip_thought_signature_validator" no campo de assinatura de pensamento para ignorar a validação.

  2. Estou enviando chamadas e respostas de função paralelas intercaladas, e a API está retornando um erro 400. Por quê?

    Quando a API retorna chamadas de função paralelas "FC1 + assinatura, FC2", a resposta esperada do usuário é "FC1+ assinatura, FC2, FR1, FR2". Se você os tiver intercalados como "FC1 + assinatura, FR1, FC2, FR2", a API vai retornar um erro 400.

  3. Quando estou fazendo streaming e o modelo não retorna uma chamada de função, não consigo encontrar a assinatura de pensamento

    Durante uma resposta do modelo que não contém um FC com uma solicitação de streaming, o modelo pode retornar a assinatura de pensamento em uma parte com um conteúdo de texto vazio. É recomendável analisar toda a solicitação até que o modelo retorne o finish_reason.

Comportamento de assinatura de pensamento por série de modelos

Os modelos Gemini 3 Pro e Gemini 2.5 se comportam de maneira diferente com assinaturas de pensamento em chamadas de função:

  • Se houver chamadas de função em uma resposta,
    • O Gemini 3 Pro sempre terá a assinatura na primeira parte da chamada de função. É obrigatório retornar essa parte.
    • O Gemini 2.5 terá a assinatura na primeira parte (independente do tipo). É opcional retornar essa parte.
  • Se não houver chamadas de função em uma resposta,
    • O Gemini 3 Pro vai ter a assinatura na última parte se o modelo gerar um pensamento.
    • O Gemini 2.5 não terá uma assinatura em nenhuma parte.

Para saber mais sobre o comportamento de assinatura de pensamento dos modelos do Gemini 2.5, consulte a página Pensamento.