惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
T
Tailwind CSS Blog
V
V2EX
阮一峰的网络日志
阮一峰的网络日志
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
腾讯CDC
GbyAI
GbyAI
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Last Week in AI
Last Week in AI
A
About on SuperTechFans
L
LangChain Blog
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
G
Google Developers Blog
The Cloudflare Blog
云风的 BLOG
云风的 BLOG
D
Docker
博客园 - 聂微东
博客园 - 司徒正美
Recent Announcements
Recent Announcements
MyScale Blog
MyScale Blog
U
Unit 42

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解
Agent出现LLM因为历史工具调用消息而误解工具调用方式的问题
囫囵吞桃 · 2026-05-11 · via 博客园_首页

背景

近期在Mac mini上部署了Acbox等开发者开发的Memoh——一款基于docker容器的多智能体Agent。在使用过程中出现了问题,Agent调用工具失败,并且在聊天记录中出现了类似下面格式的文本。

<tool_call ...>{...}</tool_call>

排查

在项目仓库已有人提交了issue #437,其认为问题在于LLM-SDK缺少兜底方案,需要Agent进程在LLM返回的content中扫描tool_call字符串,并转换为正常工具调用。

但是直觉认为,这只是一种治标不治本的方法。问题关键并不在于此。


经过排查,发现<tool_call ...>{...}</tool_call>这种类似XML的格式的由来是:Agent将历史的工具调用记录转换为这种格式的字符串,再放入上下文发送给LLM。这种格式会让LLM误以为在content中写这种格式就是触发工具调用的方法,进而引发错误。

于是,在Codex的建议下,秉持着最小修改的原则,将<tool_call ...>{...}</tool_call>格式改为了更类似自然语言的格式:

[Previous assistant tool use]
Tool: exec
Input: {...}

然而,在接下来的测试中,LLM居然开始误将这种新的格式作为工具调用的方法,继续在输出的content中写入这种内容。

但是,这也印证了问题的根本原因就在于:LLM误学习了历史工具调用格式。

问题处理

考虑到处理该问题会涉及到后端的turn_response管线的大改,因而我没有参与更改。只在项目仓库提了一个issue。在第二天下午,项目的开发者便根据此issue使用Codex予以修改了,具体修改可见PR

其修改的大致思路为:不再将工具调用记录和其他文本一样转为string放入content里,而是以完整的调用结构化数据存放,与content分离。

进一步思考

为什么会发生这样的错误

internal/pipeline/turn_response.go中可以看到,该Agent在把工具调用拼装入上下文的时候,会将其与其他对话上下文一起转换为下面的结构体:

type ContextMessage struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

在这个结构体中,工具调用也和其他聊天文本一样被压扁成string。但是为了表示不同,还会进一步写为这种xml格式。

可能因为项目在最初没有考虑到要将工具调用引入上下文,因而上下文消息只使用string来表示。但是后期引入工具调用上下文时,可能出于方便,没有同步修改消息结构。

关于issue #437

这个issue提出了一种解决方案,让Agent在收到LLM发来的消息的时候,扫描<tool_call ...>,并将其作为触发工具调用的符号。并且指出知名的Agent项目hermes-agent也是这么做的。

但是这种做法的缺陷在于:

<tool_call ...>本身就不应该是LLM触发工具调用的方式,强行兜底处理与项目设计意图相悖。

Agent可能会在不以触发工具调用为目的的时候发出<tool_call ...>,如引用历史工具调用记录。

为什么Hermes会使用这种方式来触发工具调用?

关于这点,我咨询GPT,其给出的答复是,Hermes本身就以在LLM返回的content中使用类似的XML标签来作为工具调用触发的标志。这与Memoh在发送的schema专门的tool_call结构中放入工具调用的内容的做法不一致。