DeepAI Paper Hermes Agent 教程,Hermes 多模态与工具调用,Hermes 模型与 Provider API Gemini 报 missing thought_signature?Hermes Agent 工具调用历史丢签名的排错指南

Gemini 报 missing thought_signature?Hermes Agent 工具调用历史丢签名的排错指南

Hermes Agent 使用 Gemini 3 / Gemini preview 模型时,如果一进入工具调用就报:

Function call is missing a thought_signature in functionCall parts.
This is required for tools to work correctly.

很多人第一反应会去换 API Key、换地区、重试 Google endpoint,甚至怀疑 Gemini 服务当天不稳定。但从 Hermes Agent issue #14488 的修复过程看,这类错误更准确的关键词不是“网络问题”,而是:Gemini 工具调用历史里必须保留 thought_signature,客户端在持久化 tool call 时把它丢了。

这篇文章面向正在搜索这些长尾问题的人:

  • Gemini Function call is missing a thought_signature
  • Hermes Agent Gemini thought_signature HTTP 400
  • gemini-3-flash-preview default_api terminal thought_signature
  • gemini-3.1-pro-preview missing thought_signature
  • Gemini tools work correctly missing thought_signature

如果你只是在 Hermes Agent 里配置 Gemini 模型,最重要的结论是:先升级到包含修复的版本;如果仍复现,再检查 tool call 的 extra_content / provider_data 是否在历史消息构建时被保留下来。


典型报错长什么样?

issue 中多个用户都给出了类似错误,常见形式如下:

HTTP 400: Gemini HTTP 400 (INVALID_ARGUMENT):
Function call is missing a thought_signature in functionCall parts.
This is required for tools to work correctly, and missing thought_signature may lead to degraded model performance.
Additional data, function call `default_api:terminal`, position 2.

也可能出现在其他工具名上:

function call `default_api:skill_view`, position 5
function call `default_api:search_files`, position 4

这说明问题触发点通常不是某一个具体工具坏了,而是 Gemini 的工具调用消息在后续请求中缺少了模型要求的签名字段。


一句话结论:这不是普通 API Key 错误

missing thought_signature 和下面这些问题不是同一类:

现象更可能的原因
401 / 403API Key、权限、项目、账单或区域限制
404 model not found模型名、endpoint 版本或账号权限不匹配
context length exceeded上下文长度超限
missing thought_signature工具调用历史消息缺少 Gemini 要求的签名字段

所以,反复重试、换代理、清空温度参数,通常不会从根上解决这个错误。


为什么 Gemini 工具调用需要 thought_signature?

Gemini 的部分模型在工具调用流程里,会把内部思考/工具调用相关的签名信息附加到响应中。后续轮次如果把历史 functionCall / tool call 重新发回 Gemini,客户端需要保留这些签名。

可以把它理解成:

  • 模型第一次决定调用工具时,Gemini 返回了一个带签名的 function call;
  • Hermes Agent 把这个 function call 写进 conversation history;
  • 下一轮请求时,Hermes Agent 需要把这个带签名的历史片段回传;
  • 如果客户端只保存了工具名和参数,却丢掉了 thought_signature,Gemini 就会认为这段 function call 不完整,于是返回 HTTP 400。

这和 DeepSeek thinking mode 要求回传 reasoning_content / content[].thinking 有相似之处:都不是“用户要看到隐藏思考”,而是客户端协议层必须保留供应商要求的隐藏元数据

区别是:

  • DeepSeek 常见关键词是 reasoning_contentcontent[].thinking
  • Gemini 这里的关键词是 thought_signatureextra_contentprovider_data

Hermes Agent #14488 的根因是什么?

#14488 的讨论里,一位用户给出了非常清楚的根因分析:

> commit 43de1ca8 移除了 _nr_to_assistant_message shim,改用 ToolCall / NormalizedResponse dataclass 上的 duck-typed properties。但 ToolCall 定义里漏掉了 extra_content property,而 extra_content 正是承载 Gemini thought_signature 的地方。

结果就是:

1. Gemini transport 正确把 thought_signature 放进了 provider_data["extra_content"]; 2. 但 agent loop 构建 assistant message 时读取 getattr(tc, "extra_content", None); 3. 因为 ToolCall 没有 extra_content property,读取结果变成 None; 4. 历史消息落盘/拼接时静默丢掉签名; 5. 下一轮工具调用或 fallback 请求中,Gemini 看到 functionCall 缺 thought_signature,返回 HTTP 400。

这类 bug 最麻烦的地方是:第一轮响应可能是正常的,真正爆炸发生在后续工具调用或历史 replay。


官方修复思路:给 ToolCall 补回 extra_content property

issue 里最终给出的修复方向很直接:在 ToolCall dataclass 上补一个 extra_content property,让 agent loop 能从 provider_data 里读到 Gemini 的额外签名内容。

简化后的补丁逻辑如下:

@property
def extra_content(self) -> Optional[Dict[str, Any]]:
    """Gemini extra_content (thought_signature) from provider_data."""
    return (self.provider_data or {}).get("extra_content")

维护者随后确认修复已进入 commit f5af6520,并提示用户运行:

hermes update

因此,如果你遇到这个错误,第一优先级不是改 prompt,而是确认当前安装版本是否包含 f5af6520 或后续等效修复。


排查清单:遇到 missing thought_signature 该怎么查?

1. 先确认模型和触发路径

这个问题在 issue 中主要出现在 Gemini preview / 新模型路径上,例如:

  • gemini-3-flash-preview
  • gemini-3.1-pro-preview
  • 部分 Gemini 3 preview 工具调用场景

如果你只问普通文本问题不报错,一调用 terminal、search_files、skill_view 等工具才报错,就更符合这个问题的特征。

2. 升级 Hermes Agent

先执行:

hermes update

然后重新打开会话测试。不要只重启旧进程,因为旧代码仍可能使用已经丢签名的历史结构。

3. 用新会话复现,不要只在旧会话里重试

如果旧会话历史里已经缺了 thought_signature,升级后也可能继续被坏历史污染。

建议:

  • 新开一个 clean session;
  • 选择同一个 Gemini 模型;
  • 让它执行一个简单工具调用;
  • 看是否仍然报 missing thought_signature

如果新会话正常,旧会话异常,说明你很可能遇到的是历史消息已经损坏,而不是当前版本仍未修好。

4. 检查 provider_data / extra_content 是否被保留

如果你维护的是 fork、插件、adapter 或自定义 transport,要重点检查:

  • Gemini response 是否把 thought_signature 存入 provider_data["extra_content"]
  • ToolCall 对象是否暴露 extra_content
  • _build_assistant_message 或类似 history builder 是否把 extra_content 写回 assistant message;
  • fallback、retry、compression、cron、tool replay 路径是否都没有丢字段。

很多协议 bug 都不是主路径出错,而是 fallback / retry / 历史压缩路径漏了一个字段。

5. 不要把它误判为“Gemini 今天不稳定”

issue 中确实有人一开始怀疑 Google/Gemini 服务当天异常,因为前一天还能用、当天突然报错。但后续根因说明更像是客户端升级后消息结构变更导致字段丢失。

如果错误稳定包含:

Function call is missing a thought_signature in functionCall parts

那它就是一个很明确的协议字段问题。


临时规避方案

如果你暂时无法升级到修复版本,可以考虑这些临时方案:

1. 切回不触发该问题的 Gemini 2.5 模型 issue 中有人提到切到 2.5 模型暂时可用。但这只是规避,不是修复。

2. 避免使用工具调用密集任务 如果普通对话可用、工具调用报错,可以临时减少 terminal / search_files / skill_view 等调用。

3. 新建会话 对已经污染的历史,新会话比继续在旧会话里 retry 更可靠。

4. 手动打补丁 如果你维护自定义部署,可以把 extra_content property 补到 ToolCall,但生产环境仍建议跟进官方更新。


给开发者的定位关键词

如果你要在日志或源码里快速定位,可以搜索:

  • thought_signature
  • extra_content
  • provider_data
  • ToolCall
  • _build_assistant_message
  • _nr_to_assistant_message
  • functionCall parts
  • GeminiAPIError [HTTP 400]

重点不是只看 Gemini transport 是否拿到了签名,而是看签名是否完整穿过:

Gemini response → NormalizedResponse / ToolCall → provider_data → extra_content → assistant history → next request

只要其中任何一步把字段扔了,下一轮就可能炸。


和 DeepAI API 中转站有什么关系?

如果你在多工具环境里管理模型,DeepAI API 中转站更适合解决的是这些基础设施问题:

  • 统一 OpenAI-compatible Base URL;
  • 统一 API Key 管理;
  • 在 Cherry Studio、Cline、Dify、Open WebUI 等支持自定义 OpenAI Compatible API 的工具里集中接入模型;
  • 降低多供应商模型切换时的配置成本。

但要说清楚边界:DeepAI API 中转站不能替客户端恢复已经丢失的 Gemini thought_signature

如果 Hermes Agent 或任何客户端在 history replay 时把供应商字段丢了,中转层最多能看到一个已经不完整的请求。真正要修的是客户端消息构建、工具调用历史保存和 provider adapter。

所以正确组合是:

  • 用 DeepAI 这类 OpenAI-compatible API 基础设施统一模型接入;
  • 同时确保客户端对 Gemini / DeepSeek / OpenAI Responses API 等供应商特有字段有正确适配;
  • 不把“中转站”包装成能修复客户端协议字段丢失的万能方案。

FAQ

missing thought_signature 是不是 API Key 错了?

通常不是。API Key 错误更常见是 401 / 403。missing thought_signature 指向的是 Gemini 工具调用历史消息缺少供应商要求的签名字段。

为什么第一轮能跑,第二轮或工具调用才报错?

因为签名是在模型返回 function call 后需要被保存并在后续请求中回传。第一轮拿到签名没问题,但客户端持久化时丢掉了它,下一轮 replay 才暴露。

只要运行 hermes update 就一定好吗?

如果你升级到了包含 f5af6520 或等效修复的版本,新会话通常应解决。但旧会话历史如果已经缺字段,仍建议新开会话验证。

这个问题和 DeepSeek reasoning_content 是同一个 bug 吗?

不是同一个 bug,但属于同一类协议问题:供应商要求客户端在后续请求里保留某些隐藏元数据。DeepSeek 是 reasoning_content / content[].thinking,Gemini 是 thought_signature

为什么 retry / fallback 没用?

因为请求体本身缺字段。重试只会重复发送不完整历史,fallback 如果复用同一段坏历史,也会继续失败。


总结

Hermes Agent 的 Gemini Function call is missing a thought_signature 错误,本质上是工具调用历史消息丢失 Gemini thought_signature。在 #14488 中,根因被定位到 ToolCall dataclass 缺少 extra_content property,导致 provider_data["extra_content"] 中的签名没有进入 assistant history。

最实用的处理顺序是:

1. 升级 Hermes Agent,确认包含 f5af6520 或后续修复; 2. 用新会话复现,避免旧历史污染; 3. 检查 Gemini tool call 的 extra_content 是否完整穿过 history builder; 4. 不要把它误判为 API Key、网络或简单模型不可用; 5. 使用 DeepAI API 中转站时,也要清楚它解决的是模型接入与配置统一,不是客户端丢字段的问题。

Related Post

Hermes Agent 报 No module named agent.transports?pip / Nix 源码安装缺包排错指南Hermes Agent 报 No module named agent.transports?pip / Nix 源码安装缺包排错指南

Hermes Agent 源码安装后报 ModuleNotFoundError: No module named agent.transports?这通常不是 Anthropic API Key 或模型名问题,而是 setuptools include 缺少 agent.*,导致 pip / Nix 安装产物漏掉 agent/transports 子包。

Hermes Agent 辅助任务报 401?provider:auto、base_url 与空 api_key 排错指南Hermes Agent 辅助任务报 401?provider:auto、base_url 与空 api_key 排错指南

Hermes Agent 主模型能用,但 auxiliary title_generation 报 401 Missing Authentication header?可能是 provider:auto/openrouter 搭配 base_url 和空 api_key 被误判成 custom provider,跳过 OPENROUTER_API_KEY 环境变量读取。本文给出配置排查、workaround 和修复方向。

Discord 明明发了代码,Hermes 却像没看见:message.txt 附件被静默吞掉的原因Discord 明明发了代码,Hermes 却像没看见:message.txt 附件被静默吞掉的原因

Discord 会把长代码自动转成 message.txt 附件,Hermes 旧版在读取这类文本附件时可能因 Brotli br 解码失败而静默忽略内容。本文复盘 #12511:为什么 PDF 和图片能过,txt/py/html 却进不了 Agent 上下文。