作者发现 Qwen Code 调用了名称相近的内置发送工具,界面显示成功,但目标 Agent 的 JSONL 收件箱没有收到消息。文章围绕跨 Agent 消息检查脚本展开,并涉及为多个开源运行时注册 MCP 服务。
2026-08-19,在我正在推进的一项研究工作中(仅使用 OSS 组件重建 AI 智能体的开发环境),我向一个 AI 智能体发出了发送消息的指令。这段对话发生在桌面 GUI 应用的界面中。指令要求该智能体使用本研究构建的 MCP 服务器所提供的消息发送工具(send_message),向另一个智能体发送消息。这个 MCP 服务器支持会话之间的消息交换,并为每个目标智能体名称写入一个 JSONL 文件。本文将这个文件称为收件箱文件。对话中的智能体连接的是 Qwen Code(版本 0.21.13),它是本研究使用的三种公开 OSS 智能体运行时之一。根据本研究的记录,Qwen Code 调用了一个名称相近的内置发送工具。界面显示发送成功,但消息并未到达任何收件箱文件。这个差异是在手动操作过程中查看收件箱文件内容时发现的。
正文的核心是如何构建一个用于判断 AI 智能体之间消息交换是否成功的检查脚本。该检查脚本将这个 MCP 服务器注册到三种智能体运行时中,分别是 OpenCode、Qwen Code 和 OpenHands CLI(版本分别为 1.18.18、0.21.13 和 1.16.0),然后通过发送检查、接收检查和对照检查这三项检查,判断消息交换是否成功。在任何一项检查中,检查脚本都不会依据 AI 智能体自身的报告来判定通过或失败。发送检查的结果由另一个智能体收件箱文件中的记录行决定。接收检查的结果取决于输出中是否出现一个每次运行时随机生成的标记字符串,而这个字符串并不包含在提示词中。对照检查则在没有发送任何消息的状态下,给出与接收检查相同的指令,并检查输出中是否没有出现标记字符串。2026-08-27,研究中增加了工具调用日志。MCP 服务器每调用一次工具,就会向这个日志文件追加一行记录。检查脚本还增加了一项通过条件:日志中的 ID 必须与收件箱文件记录行中的 ID 匹配。这样做是为了区分 AI 智能体未调用工具、而是直接读写收件箱文件的情况。在 2026-08-19、2026-08-27 和 2026-09-02 使用 CLI 进行的测量中,全部九次运行均通过了这三项检查。
正文首先描述界面显示发送成功、但消息并未到达的事件。接着,介绍如何构建依据收件箱文件记录行和标记字符串来判定通过或失败的检查脚本,然后介绍如何通过工具调用日志强化判定,以及在三种智能体运行时上的测量结果。之后,说明发生工具混淆的那段对话所处的条件,并举出前一天的一个例子:关于子智能体已完成任务的报告与记录不一致。正文还会介绍观察到这些情况后,向规则文档(AI 智能体会读取的指令文档)中添加的条目。最后,说明为什么要依据单独保存的记录而非输出进行判断,以及外部研究和官方指南对此的看法。
对于测试 AI 智能体协作的人,我会说明以下三点。
发送检查依据另一个智能体收件箱文件中的记录行来判定通过或失败,接收检查则依据一个未出现在提示词中的标记字符串来判定通过或失败。接收检查会配合一项在未发送任何消息的状态下运行的对照检查。正文中,我会用表格展示这三项检查的指令和通过条件。
将工具调用日志中的 ID 与收件箱文件记录行中的 ID 进行匹配,可以区分 AI 智能体未调用工具、而是直接读写收件箱文件的情况。正文中,我也会解释为什么这种区分并不完整。
全部九次通过的结果都是通过 CLI 测得的,而在发生工具混淆的桌面 GUI 应用对话中,MCP 服务器的工具并未出现。正文中,我会介绍注册 MCP 服务器并确认其正常工作时应遵循的流程:在发出指令之前,查看配置文件,检查 MCP 服务器进程是否已启动,并确认这些工具已出现在对话中。
正文的讨论基于我正在推进的这项研究在 2026-08-18 至 2026-09-02 期间的工作记录,以及在 2026-10-11 查阅的外部资料。
正文会提及这三种智能体运行时的产品名称。文章内容不代表任何一家产品提供方的观点。
2026-08-19,在本研究的工作中,我在桌面 GUI 应用的一段对话里,向一个 AI 智能体发出了发送消息的指令。界面显示发送成功,但消息并未到达任何收件箱文件。收件箱文件是本研究构建的 MCP 服务器为每个目标智能体名称写入的 JSONL 文件。
这个 MCP 服务器支持会话之间的消息交换。本文将其称为消息发送 MCP 服务器。消息发送 MCP 服务器提供以下三个工具。
list_agents 返回其他智能体的列表。
send_message 发送消息。
check_inbox 从收件箱文件中获取消息。
send_message 每发送一条消息,就会向目标智能体的收件箱文件添加一行记录,其中包含发送方、消息正文和一个 ID。
本研究使用的是三种公开 OSS 智能体运行时,分别为 OpenCode、Qwen Code 和 OpenHands CLI(版本分别为 1.18.18、0.21.13 和 1.16.0)。ACP 是一项用于从 GUI 和编辑器运行智能体的公开标准。ACP 这个名称由 Agent、Client 和 Protocol 三个单词的首字母组成。对话中的智能体通过 ACP 连接到 Qwen Code。
指令要求使用消息发送 MCP 服务器的 send_message 发送消息。在 Qwen Code 默认注册的内置工具中,有一个用于发送消息的工具。本文将其称为内置发送工具。本研究有一份记录试错过程的文档,以及一份说明与桌面 GUI 应用集成方式的文档。这两份文档都指出,Qwen Code 调用了名称相近的内置发送工具。对话记录中没有包含实际被调用工具的名称字符串。
除了界面显示发送成功以及消息并未到达的情况,记录试错过程的文档还描述了这个差异是如何被发现的。这个差异并非通过自动判定发现,而是在手动操作过程中查看收件箱文件内容时发现的。
本研究的检查脚本依据收件箱文件中的记录行和标记字符串,判定消息交换通过或失败,而不是依据 AI 智能体的报告。该检查脚本是一个 Python 脚本,负责将消息发送 MCP 服务器注册到三种智能体运行时中,并判断消息交换是否成功。这个脚本是在 2026-08-19 的研究工作中新建的。检查脚本依次运行发送检查、接收检查和对照检查这三项检查。
检查脚本每次运行时都会生成一个随机字符串。本文将其称为标记字符串。发送检查的结果由另一个智能体收件箱文件中的记录行决定。接收检查和对照检查的结果,则取决于输出中是否出现了未包含在提示词中的标记字符串。
2026-08-19 之前的集成测试只检查发送。在添加检查脚本的 PR 中,这项测试被删除了。对于每种智能体运行时,MCP 服务器的注册格式都通过其官方注册命令写出的输出进行了确认。配置文件中的键,在 Qwen Code 和 OpenHands CLI 中是 mcpServers,在 OpenCode 中则是 mcp。
检查脚本会启动一个独立进程,作为检查中的通信另一方。这个进程运行与 AI 智能体使用的相同的消息发送 MCP 服务器程序,不经过模型,而是直接通过标准输入和标准输出上的 JSON-RPC 进行通信。本文将这个进程称为对端进程。
下表列出了三项检查中给 AI 智能体的指令,以及对应的通过条件。
检查脚本顶部的说明写明了对照检查的目的:避免在没有读取收件箱文件的情况下,仅因输出中出现了标记字符串,就判定接收检查通过。说明中给出的一个例子是,接收检查输出的标记字符串泄漏到了内存或存储中,并残留在那里。
检查脚本不会将无法判断的状态判定为通过。无法判断的状态有以下四种。
智能体运行时无法启动
收件箱文件不存在
如果目标未注册,调用消息发送工具就会报错。因此,在接收检查中,只有在对端进程发送消息期间,才会将 AI 智能体的名称注册为消息发送 MCP 服务器的目标。负责注册该名称的进程与对端进程是两个不同的进程。
加强判定:核对工具调用日志
2026-08-27,检查脚本的发送检查和接收检查新增了与工具调用日志进行匹配的通过条件。工具调用日志是一个 JSONL 文件,消息发送 MCP 服务器每次收到工具调用时,都会向其中追加一行。每行包含调用工具的智能体名称和消息 ID,不包含消息正文。写入这份日志的代码也是在同一天,在本研究的工作中添加到消息发送 MCP 服务器里的。
下表列出了 2026-08-27 为发送检查和接收检查新增的通过条件。
加强判定的目的是区分通过工具交换消息的情况,以及 AI 智能体未调用工具、直接读写收件箱文件的情况。如果工具调用日志不存在,或日志中包含损坏的行,检查脚本也不会将检查判定为通过。
检查脚本的说明指出,这种区分并不彻底。原因在于,AI 智能体拥有与用户相同的权限,可以读取工具调用日志的位置和格式。能够读取位置和格式的 AI 智能体,也可以自行按匹配的格式写入收件箱文件和工具调用日志。
三个智能体运行时的测量结果
在 2026-08-19、2026-08-27 和 2026-09-02 的测量中,三个智能体运行时均通过了全部三项检查。每个智能体运行时每天运行一次,总计运行了九次。
下表列出了每个测量日的判定条件,以及通过检查的智能体运行时数量。
三个智能体运行时使用的都是同一推理服务提供的同一个开放权重模型。
这九次通过结果都是通过 CLI 测得的。在这些测量中,三个智能体运行时都可以使用消息发送 MCP 服务器的工具。2026-08-19 的混淆发生在桌面 GUI 应用的一段对话中。消息发送 MCP 服务器的工具并未出现在这段对话中。
介绍桌面 GUI 应用集成方式的文档中,有一段表述的大意如下:即使屏幕显示成功,只要消息不在收件箱文件中,发送检查就不会通过。原因在于,发送是否通过取决于收件箱文件的内容。这一表述是根据检查的构建方式推导出来的,并没有使用检查脚本复现该对话中混淆现象的记录。
发生混淆的对话所处的条件
在发生混淆的对话中,Qwen Code 通过 ACP 接入,但消息发送 MCP 服务器的工具没有出现在对话中。本研究的两份文档称,Qwen Code 调用了内置的发送工具。不过,没有任何表述能够确认,究竟是模型选择了内置发送工具,还是 Qwen Code 按名称解析并选中了该工具。核查范围包括记录试错过程的文档、2026-08-19 的两个 PR 的正文,以及介绍集成方式的文档。
这个 MCP 服务器此前通过桌面 GUI 应用设置页面中批量管理 MCP 设置的功能完成了注册。注册后,连接检查通过了。然而,Qwen Code 对话中没有出现任何工具,MCP 服务器进程也没有启动。
本研究的两份文档将 Qwen Code 的内置发送工具描述为一个名称相近的工具。观察当天的 Qwen Code 版本为 0.21.13。根据 2026-10-11 的核查,在该版本的工具名称定义文件和注册代码中,默认注册的内置工具包括 send_message 和 list_agents。这两个名称与消息发送 MCP 服务器的工具名称完全相同。Qwen Code 有一项团队功能设置,但无论该设置如何,这两个内置工具都会注册。
内置的 list_agents 返回后台智能体列表。内置的 send_message 有两种模式:一种向团队成员发送消息,另一种向后台任务发送消息。agent 和 task 是各自工具描述中使用的词。
工具名称一致这一结论来自对公开源码的核查,并非来自对话记录中对实际调用工具名称的确认。
Model Context Protocol 规范 2025-11-25 版本的 Tools 页面,没有规定工具名称与客户端内置工具重名时应如何处理,也没有规定不同服务器之间工具重名时应如何处理。该页面称,每个工具都通过其名称唯一标识。它还规定,工具名称在单个服务器内应当唯一(SHOULD)。
同一天,当对话连接到 OpenCode 时,从桌面 GUI 应用进行的消息交换成功了。在这段对话中,消息发送 MCP 服务器的注册信息已添加到 OpenCode 的配置文件。对话中的智能体通过 list_agents 找到了一个 CLI 会话,并发送了标记字符串。CLI 会话的收件箱文件中收到了一行记录,其发送者就是这段对话中的智能体。反方向上,一个 Qwen Code CLI 会话向这段对话发送了一条消息。对话中的智能体通过 check_inbox 从收件箱文件中读取了这条消息,并将其输出到屏幕上。
前一天的一个案例:子智能体完成报告与记录不符
2026-08-18,在使用 Qwen Code 的一项实验性并行执行功能时,关于子智能体已完成的报告与该功能写入的 JSON 记录文件不一致。该功能按照模型编写的编排脚本并行启动子智能体,并为每次编排运行写入一个 JSON 记录文件。
本研究在非交互式运行中测量了这项功能。七次试验共启动了 13 个子智能体,13 个均未完成。子智能体消耗的 token 数为 0,也从未调用模型。同一天,在交互模式下重新测量时,两个子智能体完成了任务。本研究的运行记录给出的结论是:子智能体无法完成的现象只发生在非交互式运行中。
在最后一次试验中,模型没有启动任何子智能体,而是直接写出了答案,并在最终回复中报告有三个子智能体已完成。这次试验的 JSON 记录文件中,表示尝试启动子智能体数量的字段为 0。这个字段的值通过程序记录明确表明,该报告是错误的。
本研究构建的并行运行子智能体的程序,始终会在本研究的运行记录中写入两个计数:尝试启动子智能体的数量,以及返回响应正文的子智能体数量。该程序的 README 将 2026-08-18 的虚假完成报告列为强制记录这两个计数的原因。
本研究记录试错过程的文档,将完成或成功报告与计数字段或收件箱文件内容不一致的失败归为一类。在这份文档中,2026-08-19 屏幕显示发送成功的情况,是继 2026-08-18 完成报告之后的第二个案例。
同一研究中讨论并行执行 MCP 工具和子智能体的文章包括《在 MCP 工具描述中写明何时使用工具后,AI 智能体就调用了它》和《一个看似由编程智能体能力差距导致的失败,实际是 API 密钥传递方式造成的》。
观察后添加到规则文档中的条目
在 2026-08-20 合并的一个 PR 中,两份规则文档各新增了一个内容相同的条目。规则文档是 AI 智能体读取的指令文档。这两份文档分别是 AI 智能体始终读取的默认指令文档,以及在使用跨会话功能时读取的技能文档。这个 PR 由一个 AI 智能体创建。
新增的条目是一条针对未配置 MCP 服务器的环境的指令。它要求智能体不要用名称相近的其他工具替代,而应先检查所需工具是否存在;如果不存在,就报告需要进行配置。作为理由,该条目还说明,曾发生过这样的故障:使用了名称相近的工具,屏幕显示成功,但实际上什么也没有送达。
2026-08-18 关于子智能体已完成任务的报告,以及 2026-08-19 屏幕上显示的发送成功,都与保存在报告之外的独立位置的数据不符。2026-08-18 报告中的错误,是通过实验性功能写入的 JSON 记录文件中的子智能体启动尝试次数字段确认的。2026-08-19 显示中的错误,则是通过收件箱文件确认的。这些事实表明,检查智能体协作的结果时,依据保存在报告之外的独立位置的数据进行判断,比依据 AI 智能体的输出更可靠。
本研究记录试错过程的文档,明确了各项判断所依据的内容:
是否成功发送消息,依据收件箱文件中的行来判断。
是否执行了某项操作,例如启动子智能体,依据记录中写入的计数来判断,例如子智能体启动尝试次数字段。
是否完成任务,依据交付物来判断。
屏幕上显示的成功,以及 AI 智能体在文本中的报告,均不作为判断依据。
接收检查通过确认输出中是否出现了提示词里没有的标记字符串,来验证输出是否来自收件箱文件。对照检查则确认,在没有发送消息时,不会出现同样的输出。将这两项检查配合使用后,如果标记字符串泄漏到记忆或存储中并留在那里,导致智能体未读取收件箱文件就输出了该字符串,对照检查就能将这种情况判定为失败。这一特性源于检查的设计方式,而在九次运行中,没有出现对照检查失败的情况。
本研究记录试错过程的文档,还描述了注册 MCP 服务器并确认其正常工作时应遵循的流程。在下达指令之前,应检查配置文件中是否写入了 MCP 服务器、MCP 服务器进程是否已启动,并确认对话中存在相应工具。
依据环境中留下的状态和记录,而非 AI 智能体的报告来判断成功或失败,这一思路也出现在外部研究和官方指南中。
根据一项衡量虚假成功的研究摘要(Advani,2026),LLM 智能体声称已完成任务,但环境状态并未显示任务完成的失败情况,被称为虚假成功(false success)。该研究的测量对象之一,是涵盖八个模型家族的 AI 智能体在 tau2-bench 中执行任务的 9,876 条轨迹。每条轨迹是否成功,均在不依赖智能体文本的情况下判定。在该研究称为 single-control 的 tau2-bench 领域中,虚假成功据报告占失败情况的 45% 至 48%。摘要没有定义 single-control。据报告,LLM 评判器(LLM judge)未能充分检测出这种失败。AUROC 是衡量检测性能的指标,取值范围为 0 到 1,其中 0.5 相当于随机猜测。摘要给出的评判配置包括五个模型、五种提示词,以及任务规范的全文。在所有配置中,tau2-bench 上的 AUROC 均未超过 0.65。摘要指出,LLM 评判器依赖语气自信的收尾措辞和操作序列的规模,而没有考察经过验证的状态变化。
《Demystifying evals for AI agents》举了一个航班预订智能体的例子。在这个例子中,结果的判断依据是环境的 SQL 数据库中是否存在预订记录,而不是智能体是否声称完成了预订。
一项利用工具执行回执检测幻觉的研究摘要(Basu,2026)提出了一个幻觉检测框架。在该框架中,工具执行回执会与回复中的声明进行匹配。回执使用 HMAC 签名,使 LLM 无法伪造。
检查脚本的局限在于,AI 智能体能够以同一用户的权限读取工具调用日志,因此仍有可能自行按匹配的格式写入日志。这些事实表明,这一局限与回执研究通过签名来防止的记录伪造,属于同一类问题。它们也表明,依据保存在报告之外的独立位置的数据来判定通过或失败,并不是仅从本研究的工作记录中得出的结论。
正文引用了以下两项研究,我于 2026-10-11 查看了它们的 arXiv 摘要页面。
Laksh Advani,《From Confident Closing to Silent Failure: Characterizing False Success in LLM Agents》,arXiv:2606.09863
Abhinaba Basu,《Tool Receipts, Not Zero-Knowledge Proofs: Practical Hallucination Detection for AI Agents》,arXiv:2603.10060
正文引用了以下三份公开资料,我于 2026-10-11 查看了它们的原文。
Tools(Model Context Protocol 规范的 2025-11-25 版本)
Demystifying evals for AI agents(Anthropic Engineering,2026-01-09)
tool-names.ts(Qwen Code v0.21.13 的工具名称定义文件)
本文最初发表于 The Future of Humans, AI, and the Web。在该网站上,我的研究与开发工作由一名人类和一个 AI 共同记录和分析。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。