Gemini: ошибка missing thought_signature после вызова инструмента

Как сохранить подписи Gemini при вызовах функций, параллельных результатах и преобразовании между REST, SDK и совместимыми API.

Обложка на оливково-сером фоне: светлая бумага с линейным рисунком с чашечными весами, геометрические акценты и заголовок Gemini Thought Signatures.

Если первый запрос Gemini проходит, а после вызова функции возникает missing thought_signature, проверьте содержимое ответа модели, сохранённое между запросами. Верните исходную часть с вызовом и подписью, прежде чем добавлять результат функции. Сохранение только имени и аргументов может удалить состояние, нужное для следующего хода.

Статья касается продолжения инструментальных вызовов и опирается на документацию Google по thought signatures, проверенную 14 сентября 2026 года. Требования различаются между поколениями моделей и API. Не все модели Gemini обязательно возвращают одинаковый HTTP 400 при отсутствии подписи.

Найдите поле в своём интерфейсе

Ошибка может использовать snake_case, хотя нативный REST использует camelCase. В generateContent JSON поле thoughtSignature находится в part рядом с functionCall. Python SDK обычно предоставляет thought_signature. Совместимый endpoint может передавать метаданные в специальном расширении провайдера.

ИнтерфейсЧто сохранять
Нативный REST generateContentПолный model content и parts, включая thoughtSignature
Google Python SDKПолные возвращённые content-объекты, включая thought_signature
OpenAI-совместимый endpointДокументированные метаданные провайдера в сообщении или вызове
Interactions или иной APIПравила состояния и продолжения именно этого API

Не переставляйте поле наугад из-за другого написания в ошибке. Успех первого запроса подтверждает лишь его принятие. При продолжении текстовое хранилище истории или адаптер могут потерять обязательное состояние.

Сначала сохраните ход модели, затем добавьте результат

Полное содержимое ответа модели должно находиться в истории перед следующим пользовательским содержимым с реальным ответом функции. Построение ходов описано в руководстве function calling. Сохраните исходный порядок частей, не восстанавливайте их из виджета чата.

Схематично продолжение выглядит так:

user: исходная задача
model: исходное содержимое ответа, включая functionCall и часть с подписью
user: functionResponse с реальным результатом
model: следующий ответ

Это синтетическая последовательность, не исполняемый запрос и не запись реального API-теста. Для настоящего вызова нужен ответ, полученный для данной задачи. Не заменяйте подпись случайной строкой или примером из чужого диалога.

Параллельным вызовам не всегда нужны отдельные подписи

В текущем документированном инструментальном сценарии Gemini 3 обязательная подпись находится в первой части с вызовом функции каждого шага. При параллельном ответе последующим частям с вызовами собственная подпись не требуется. Валидатор, требующий её у каждой части, способен отвергнуть корректный ответ.

Сохраняйте группу в исходном виде: первый вызов с подписью, затем второй, после них — соответствующие результаты. Если два вызова пришли одним параллельным ходом модели, не переставляйте историю в порядок «вызов один, результат один, вызов два, результат два». Последовательные шаги отличаются: каждый новый ход модели сохраняет своё состояние.

Это важно для middleware, превращающего все инструменты в отдельные сообщения. Удобное общее представление может потерять группировку. Храните достаточно данных для восстановления нативной последовательности принимающего endpoint.

SDK сохраняет только то, что сохраняет приложение

Официальный SDK может обрабатывать подписи при сохранении полного ответа и истории. Если приложение превращает ответ в текст, выделяет лишь аргументы или записывает сокращённую JSON-схему, нельзя переносить эти гарантии на приложение целиком.

Сопоставьте три объекта: ответ провайдера, сохранённую историю и фактически сериализованный следующий запрос. Найдите первую границу, где часть с подписью пропадает или меняется. Проверьте схему БД, фильтры сообщений, callback-обработчики и адаптеры API.

Минимальный пример должен использовать безвредную функцию с фиксированным локальным результатом и без внешних эффектов. Задача — пройти один полный раунд, а не повторить платёж или публикацию во время отладки. Статья не утверждает, что определённая версия стороннего клиента уже исправлена.

Уменьшение thinking не заменяет восстановление состояния

Не считайте минимальный thinking способом убрать требование подписи. Следуйте документации thinking для выбранной модели и интерфейса. Изменение настройки генерации не возвращает уже отброшенные данные.

Google описывает особую обработку некоторых импортированных траекторий, но специальный обходной маркер — не стандартный способ исправить приложение, теряющее собственный ответ модели. Сначала исправьте сохранение истории. Иначе приложение продолжит удалять полезные метаданные, скрыв только один симптом проверки.

Отделяйте отсутствующую подпись от неправильного function response. Неверное имя результата, нарушенная связь вызова или некорректная схема инструмента могут дать иную ошибку. Сохраняйте статус и полное тело ответа, чтобы общий HTTP 400 не направил диагностику по неверному пути.

Проверяйте именно исправленный сценарий

После исправления сериализации выполните небольшой сценарий функции на том же маршруте и версии SDK. Убедитесь, что продолжение принято, а ответ учитывает результат. Если нужны параллельные функции, проверьте их отдельно: успех одиночного вызова не подтверждает параллельный путь.

Укажите, что проверено: локальная схема или настоящий API. Проверка синтаксиса не доказывает принятие провайдером. Не приписывайте шлюзу восстановление потерянного клиентского состояния без теста и понятного механизма.

Стоимость и доступ описаны в руководстве API Gemini 3.8. Похожая ошибка другого провайдера разобрана в руководстве подписей Claude: его нативные поля нельзя просто перенести в Gemini.

Частые вопросы

Каждый параллельный вызов должен иметь подпись?

Нет. В документированном сценарии Gemini 3 обязательная подпись расположена в первой части с вызовом функции данного шага. Сохраняйте полученную группу без изменений.

Почему ошибка использует snake_case, а REST — camelCase?

Названия в ошибке и свойства SDK могут отличаться от нативных REST-полей. Следуйте схеме интерфейса, принимающего запрос.

Смена провайдера решит проблему?

Не обязательно. Если клиент удаляет состояние до отправки, новый адрес назначения его не восстановит. Сначала проверьте путь запроса.

Часто задаваемые вопросы

Каждый параллельный вызов должен иметь подпись?
Нет. В документированном сценарии Gemini 3 обязательная подпись расположена в первой части с вызовом функции данного шага. Сохраняйте полученную группу без изменений.
Почему ошибка использует snake_case, а REST — camelCase?
Названия в ошибке и свойства SDK могут отличаться от нативных REST-полей. Следуйте схеме интерфейса, принимающего запрос.
Смена провайдера решит проблему?
Не обязательно. Если клиент удаляет состояние до отправки, новый адрес назначения его не восстановит. Сначала проверьте путь запроса.