Сигнатуры мыслей представляют собой зашифрованные представления внутреннего мыслительного процесса модели и используются для сохранения контекста рассуждений при многооборотном взаимодействии. При использовании моделей мышления (таких как серии Gemini 3 и 2.5) API может возвращать поле thoughtSignature в составе содержимого ответа (например, text или functionCall частей).
Как правило, если вы получаете сигнатуру мысли в ответе модели, вы должны передать её обратно в том же виде, в котором она была получена, при отправке истории разговора в следующем шаге. При использовании Gemini 3 Pro необходимо передавать сигнатуры мысли во время вызова функции, иначе вы получите ошибку валидации (код статуса 4xx).
Как это работает
На рисунке ниже наглядно показано значение терминов «поворот» и «шаг» применительно к вызову функций в API Gemini. «Поворот» — это единичный, полный обмен данными в диалоге между пользователем и моделью. «Шаг» — это более детальное действие или операция, выполняемая моделью, часто в рамках более крупного процесса для завершения хода.

В этом документе основное внимание уделено обработке вызовов функций в Gemini 3 Pro. Информация о расхождениях с версией 2.5 приведена в разделе, посвященном поведению модели .
Gemini 3 Pro возвращает сигнатуры мыслей для всех ответов модели (ответов API) при вызове функции. Сигнатуры мыслей отображаются в следующих случаях:
- При наличии параллельных вызовов функций первая часть вызова функции, возвращаемая ответом модели, будет иметь сигнатуру мысли.
- При последовательных вызовах функций (многошаговых) каждый вызов функции будет иметь сигнатуру, и вам необходимо будет передать все сигнатуры обратно.
- Ответы модели без вызова функции вернут сигнатуру мысли внутри последней части, возвращаемой моделью.
В следующей таблице представлена визуализация многошаговых вызовов функций, объединяющая определения поворотов и шагов с концепцией сигнатур, представленной выше:
Повернуть | Шаг | Запрос пользователя | Модель ответа | ФункцияОтвет |
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(без FC) | Никто |
Сигнатуры в частях вызова функций
Когда Gemini генерирует functionCall , он полагается на thought_signature для правильной обработки выходных данных инструмента в следующем ходу.
- Поведение :
- Одиночный вызов функции : часть
functionCallбудет содержатьthought_signature. - Параллельные вызовы функций : если модель генерирует параллельные вызовы функций в ответе,
thought_signatureдобавляется только к первой частиfunctionCall. Последующие частиfunctionCallв том же ответе не будут содержать сигнатуру.
- Одиночный вызов функции : часть
- Требование : Вы должны вернуть эту подпись именно в той части, в которой она была получена при обратной отправке истории разговора.
- Проверка : строгая проверка применяется ко всем вызовам функций в текущем ходу. (Требуется только текущий ход; проверка на предыдущих ходах не выполняется.)
- API просматривает историю (от самых новых к самым старым), чтобы найти самое последнее сообщение пользователя со стандартным содержимым (например,
text) (которое будет началом текущего хода). Это не будетfunctionResponse. - Все ходы
functionCallмодели, происходящие после этого конкретного сообщения об использовании, считаются частью хода. - Первая часть
functionCallна каждом шаге текущего хода должна включать своюthought_signature. - Если вы пропустите
thought_signatureдля первой частиfunctionCallна любом этапе текущего хода, запрос завершится ошибкой 400.
- API просматривает историю (от самых новых к самым старым), чтобы найти самое последнее сообщение пользователя со стандартным содержимым (например,
- Если не будут возвращены надлежащие подписи, вот как вы получите ошибку
-
gemini-3-pro-preview: Отсутствие подписей приведёт к ошибке 400. Текст будет выглядеть следующим образом:- В вызове функции
<Function Call>в блоке контента<index of contents array>отсутствуетthought_signature. Например, в вызове функцииFC1в блоке контента1.отсутствуетthought_signature.
- В вызове функции
-
Пример последовательного вызова функции
В этом разделе показан пример множественных вызовов функций, где пользователь задает сложный вопрос, требующий выполнения нескольких задач.
Давайте рассмотрим пример вызова многооборотной функции, в котором пользователь задает сложный вопрос, требующий выполнения нескольких задач: "Check flight status for AA100 and book a taxi if delayed" .
Повернуть | Шаг | Запрос пользователя | Модель ответа | ФункцияОтвет |
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(без FC) | None |
Следующий код иллюстрирует последовательность, представленную в таблице выше.
Поворот 1, Шаг 1 (запрос пользователя)
{
"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"
]
}
}
]
}
]
}
Ход 1, Шаг 1 (Модель ответа)
{
"content": {
"role": "model",
"parts": [
{
"functionCall": {
"name": "check_flight",
"args": {
"flight": "AA100"
}
},
"thoughtSignature": "<Signature A>"
}
]
}
}
Поворот 1, шаг 2 (ответ пользователя — отправка выходных данных инструмента) Поскольку этот ход пользователя содержит только functionResponse (без нового текста), мы все еще находимся на повороте 1. Мы должны сохранить <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"
}
}
}
]
}
Поворот 1, Шаг 2 (Модель) Теперь модель решает заказать такси на основе предыдущих выходных данных инструмента.
{
"content": {
"role": "model",
"parts": [
{
"functionCall": {
"name": "book_taxi",
"args": {
"time": "10 AM"
}
},
"thoughtSignature": "<Signature B>"
}
]
}
}
Поворот 1, Шаг 3 (Пользователь — Отправка выходных данных инструмента) Чтобы отправить подтверждение бронирования такси, мы должны включить подписи для ВСЕХ вызовов функций в этом цикле ( <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"
}
}
}
]
}
}
Пример параллельного вызова функции
Давайте рассмотрим пример вызова параллельной функции, где пользователь спрашивает: "Check weather in Paris and London" чтобы увидеть, где модель выполняет проверку.
Повернуть | Шаг | Запрос пользователя | Модель ответа | ФункцияОтвет |
|---|---|---|---|---|
1 | 1 | request1="Проверьте погоду в Париже и Лондоне" | FC1 («Париж») + подпись FC2 («Лондон») | ФР1 |
1 | 2 | запрос 2 = запрос1 + FC1 («Париж») + подпись + FC2 («Лондон») | текстовый_вывод (без FC) | Никто |
Следующий код иллюстрирует последовательность, представленную в таблице выше.
Поворот 1, Шаг 1 (запрос пользователя)
{
"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"
]
}
}
]
}
]
}
Ход 1, Шаг 1 (Модель ответа)
{
"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
}
}
]
}
}
Поворот 1, Шаг 2 (Ответ пользователя — Отправка выходных данных инструмента) Мы должны сохранить <Signature_A> в первой части точно так же, как получено.
[
{
"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"
}
}
}
]
}
]
Подписи в functionCall частях вызова
Gemini также может возвращать thought_signatures в заключительной части ответа в частях, не являющихся вызовами функций.
- Поведение : Конечная часть содержимого (
text, inlineData…), возвращаемая моделью, может содержатьthought_signature. - Рекомендация : рекомендуется возвращать эти подписи, чтобы гарантировать, что модель поддерживает высокое качество рассуждений, особенно для сложных инструкций или моделируемых рабочих процессов агентов.
- Валидация : API не требует строгой проверки. Если вы её пропустите, ошибка блокировки не возникнет, хотя производительность может снизиться.
Текстовое/контекстное рассуждение (без проверки)
Ход 1, Шаг 1 (Модель ответа)
{
"role": "model",
"parts": [
{
"text": "I need to calculate the risk. Let me think step-by-step...",
"thought_signature": "<Signature_C>" // OPTIONAL (Recommended)
}
]
}
Поворот 2, Шаг 1 (Пользователь)
[
{ "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." }] }
]
Подписи для совместимости с OpenAI
В следующих примерах показано, как обрабатывать подписи мыслей для API завершения чата с использованием совместимости с OpenAI .
Пример последовательного вызова функции
Это пример вызова нескольких функций, когда пользователь задает сложный вопрос, требующий выполнения нескольких задач.
Давайте рассмотрим пример вызова многооборотной функции, в котором пользователь спрашивает Check flight status for AA100 and book a taxi if delayed и вы увидите, что происходит, когда пользователь задает сложный вопрос, требующий выполнения нескольких задач.
Повернуть | Шаг | Запрос пользователя | Модель ответа | ФункцияОтвет |
1 | 1 | request1="Check the weather in Paris and London" | FC1 ("Paris") + signatureFC2 («Лондон») | FR1 |
1 | 2 | request 2 = request1 + FC1 ("Paris") + signature + FC2 ("London") | text_output(без FC) | None |
Следующий код проходит по заданной последовательности.
Поворот 1, Шаг 1 (Запрос пользователя)
{
"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"
]
}
}
}
]
}
Поворот 1, Шаг 1 (Модель ответа)
{
"role": "model",
"tool_calls": [
{
"extra_content": {
"google": {
"thought_signature": "<Signature A>"
}
},
"function": {
"arguments": "{\"flight\":\"AA100\"}",
"name": "check_flight"
},
"id": "function-call-1",
"type": "function"
}
]
}
Поворот 1, шаг 2 (Ответ пользователя — Отправка выходных данных инструмента)
Поскольку этот ход пользователя содержит только functionResponse (без нового текста), мы все еще находимся на шаге 1 и должны сохранить <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\"}"
}
]
Поворот 1, Шаг 2 (Модель)
Теперь модель принимает решение заказать такси на основе предыдущих результатов инструмента.
{
"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"
}
]
}
Поворот 1, Шаг 3 (Пользователь — отправка выходных данных инструмента)
Чтобы отправить подтверждение бронирования такси, мы должны включить подписи для ВСЕХ вызовов функций в этом цикле ( <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\"}"
}
]
Пример параллельного вызова функции
Давайте рассмотрим пример вызова параллельной функции, где пользователи спрашивают: "Check weather in Paris and London" , и вы увидите, где модель выполняет проверку.
Повернуть | Шаг | Запрос пользователя | Модель ответа | ФункцияОтвет |
1 | 1 | request1="Check the weather in Paris and London" | FC1 ("Paris") + signatureFC2 («Лондон») | FR1 |
1 | 2 | request 2 = request1 + FC1 ("Paris") + signature + FC2 ("London") | text_output(без FC) | None |
Вот код для прохождения заданной последовательности.
Поворот 1, Шаг 1 (Запрос пользователя)
{
"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"
]
}
}
]
}
]
}
Поворот 1, Шаг 1 (Модель ответа)
{
"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
}
]
}
Поворот 1, шаг 2 (Ответ пользователя — Отправка выходных данных инструмента)
Необходимо сохранить <Signature_A> в первой части точно в том виде, в котором вы ее получили.
"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\"}"
}
]
Часто задаваемые вопросы
Как перенести историю из другой модели в Gemini 3 Pro с частью вызова функции в текущем ходе и шаге? Мне нужно предоставить части вызова функции, которые не были сгенерированы API и, следовательно, не имеют связанной сигнатуры мысли?
Хотя внедрение пользовательских блоков вызовов функций в запрос настоятельно не рекомендуется, в случаях, когда этого нельзя избежать, например, при предоставлении модели информации о вызовах функций и ответах, которые были выполнены клиентом детерминированно, или при передаче трассировки из другой модели, которая не включает сигнатуры мыслей, вы можете задать следующие фиктивные сигнатуры
"context_engineering_is_the_way_to_go"или"skip_thought_signature_validator"в поле сигнатуры мыслей, чтобы пропустить проверку.Я отправляю обратно чередующиеся параллельные вызовы функций и ответы, а API возвращает 400. Почему?
Когда API возвращает параллельные вызовы функций «FC1 + сигнатура, FC2», ожидаемый ответ пользователя — «FC1 + сигнатура, FC2, FR1, FR2». Если же они чередуются в виде «FC1 + сигнатура, FR1, FC2, FR2», API вернёт ошибку 400.
При потоковой передаче и отсутствии возврата вызова функции я не могу найти сигнатуру мысли.
При ответе модели, не содержащей FC, на потоковый запрос модель может вернуть сигнатуру мысли в части с пустым текстовым содержимым. Рекомендуется анализировать весь запрос до тех пор, пока модель не вернет
finish_reason.
Поведение мыслительной сигнатуры по модельным рядам
Модели Gemini 3 Pro и Gemini 2.5 ведут себя по-разному с сигнатурами мыслей в вызовах функций:
- Если в ответе есть вызовы функций,
- Gemini 3 Pro всегда будет содержать сигнатуру в первой части вызова функции. Возвращать эту часть обязательно .
- В Gemini 2.5 подпись будет в первой части (независимо от типа). Возвращать эту часть необязательно .
- Если в ответе нет вызовов функций,
- Если модель сгенерирует мысль, то на последней части будет размещена подпись Gemini 3 Pro.
- У Gemini 2.5 не будет подписи ни в одной из частей.
Информацию о поведении, характерном для моделей Gemini 2.5, см. на странице «Мышление» .