修的是内核的交付判定与我们对不上的问题。
## 根因
内核判断「这一轮到底有没有交付」**只认工具名前缀** `output_send__*`
(internal/agent/core/process.go 的 isOutputDeliveryTool)。而 `send_mail`
是个普通工具,长得和 read_inbox 没有区别 —— 模型用它发完信,内核不知道
回复已经交付,照常补一句「请根据以上工具结果继续。」。模型把这句话读成
「还要再做一步」,而它手里唯一能做的「一步」往往又是再发一封信。
这个自我强化循环在 QQ 上有过真实事故(单轮 34 次 output_send__qq、514 秒)。
三处改动,缺一不可:
1. **通道名 `homeagent` → `email`**(按投递介质命名,与内核自带的
qq/webui/cli/acp/a2a 一致),内核据此拼出 `output_send__email`。
能力位声明必须与实现一致:原先声明了 CapFile 而 handler 不读 `type`,
于是任何 type=file 都会静默变成一封「把路径当正文」的邮件 ——
声明一个做不到的能力比不声明更糟(调用方无从发现)。现在 caps=7
且真的实现 text/file/image。
2. **注入来信时用通道名,不再用插件名**。内核的约定是「用回复该走的通道名
注入」:webui 传 "webui",clawhubadapter 传它自己的通道名。我们原先两个
参数都传 `homeagent-mail-bridge` —— 那个名字**不是一个已注册的通道**,
于是注入来源、模型被告知要用的通道名、实际注册的通道名三者对不上。
3. **提示词补上平台特有的投递指引**(channel.go 的 deliveryHint)。
共用的 replyInstruction 对人来信说的是「回信不用你自己发,插件会替你转发」
—— 那句在 dsh/opencode/pi 上完全正确,在 HomeAgent 上却与内核的 persona
(「必须显式调用 output_send__{通道名}」)相反。实测:模型听我们的、
返回纯文本、插件兜底转发,邮件确实到了,但内核不知道已交付。
现在两条口径对齐:优先走通道,兜底 relay 仍然生效且**不会重复发**
(通道 handler 先 noteExplicitChannelSend,自动 relay 据此让位)。
同时按新纪律在 plg.json 声明 `sdk: "1.2.0"`;工具链据此同步了 go.mod 的
require/replace(它自己写的,含 store 里的绝对路径 —— 换机器跑一次
hmapdev build 会重新同步)。
## 验证(真模型、真网关、真邮件)
进程构建:`hmapdev build` 报「SDK 1.2.0(项目声明 sdk=1.2.0)」、
子进程模式(协议 2);go vet 干净、go test 通过。
部署:经内核自己的 pluginmgr(POST 127.0.0.1:9876/plugins,overwrite=true)
0.1.0 → 0.2.1 → 0.2.2,每次 config_kept=true;重启后 loaded/alive/心跳齐全,
插件日志「注册完成(15 个工具 + 1 个输出通道)」。
行为端到端(两封真邮件):
- 让模型列出通道 → 回信里列出 `email | text / file / image`,与注册的
caps=7 及描述逐字一致
- 让模型「原样重复标记」→ 内核日志 `executing tool: output_send__email`,
回流**恰好 1 封**,插件日志「模型已自行回复,跳过自动 relay」
- 让模型建文件并以 type=file 发送 → `cmd_run` → `output_send__email_help`
→ `output_send__email`,附件 chan-file-*.txt(15 字节)原样到达,relay 让位
这两条正是改造的两个动因:内核认得交付(循环被切断),以及附件走
「一个本地路径字符串」而不是 `attachment_ids=[...]` 数组
(opencode 上模型把数组写成 JSON 字符串、连试 6 次放弃整个任务的那个失败模式,
在结构上就不存在了)。
14 lines
314 B
JSON
14 lines
314 B
JSON
{
|
||
"author": "AgentMail",
|
||
"description": "HomeAgent 接入 AgentMail:邮件驱动的多智能体协作",
|
||
"entry": "plugin.bin",
|
||
"name": "homeagent-mail-bridge",
|
||
"name_en": "homeagent",
|
||
"name_zh": "AgentMail 桥接",
|
||
"sdk": "1.2.0",
|
||
"tags": [
|
||
"mail",
|
||
"agentmail"
|
||
],
|
||
"version": "0.2.2"
|
||
} |