Files
sanguo_moziplus_v2/docs/design/v2.7.1-mail-envelope-separation.md
T
cfdaily 0d7425b88c
Deploy / ci (push) Waiting to run
Deploy / deploy (push) Blocked by required conditions
Deploy / notify-deploy-failure (push) Blocked by required conditions
auto-sync: 2026-06-07 01:35:53
2026-06-07 01:35:53 +08:00

7.0 KiB
Raw Blame History

v2.7.1 Mail 信封/载荷分离优化

版本: v1.0
日期: 2026-05-24
作者: 庞统
状态: 实施中(评审通过,用户确认)


1. 背景

v2.7.0 Mail 飞鸽传书功能已稳定上线。实测"庞统发 request 给赵云"一封来回邮件:

  • 庞统侧 6 次 LLM 调用(input 1,702 + output 430
  • 赵云侧 4 次 LLM 调用(input 12,528 + output 277
  • 合计 10 次 LLM 调用,~14,937 tokens(不含 cache

核心问题:Agent 同时管信封(状态流转)和载荷(业务内容)。状态转换命令(claimed→working→done)占用 LLM tokens,且不可靠。

2. 业界调研

系统 信封(系统管) 载荷(Agent/LLM 管)
Hermes Kanban Dispatcher 负责 claim → spawn → reclaim → 状态流转;Agent 通过 kanban_complete() 声明完成,状态写入由系统工具执行 Agent 调 kanban_show() 读任务、调 kanban_heartbeat() 保活、调 kanban_complete(summary) 声明完成
MCP Agent Mail 系统管投递、线程聚合、消息路由 Agent 调 fetch_inbox() + acknowledge_message() 读内容和 ack
ClawTeam Inbox JSON 文件即消息,系统管 claim → ack 原子操作 Agent 读文件内容、执行业务、写产出文件
EIP 信封模式 Headerfrom/to/type/routing)由消息基础设施处理 Body(业务内容)由接收方处理

共识:状态流转是信封,属于系统。业务内容是载荷,属于 Agent。

3. 设计原则

  1. 系统管信封claimed → working → done/failed 全部由系统完成
  2. Agent 管载荷:只看业务内容,只做业务决策(回复/不回复/触发行动)
  3. 统一超时机制:Mail 任务走标准 task 超时路径(default_task_timeout_minutes),不开特殊路径
  4. 产出验证request 类型邮件验证 Agent 是否真的回复了(幻觉门控)

4. 新生命周期

4.1 正常流

系统(Dispatcher                          AgentMain Session
─────────────                          ─────────────
1. 邮件创建(Mail API
2. Dispatcher 路由到目标 Agent
3. [新增] 系统标 working               →  5. 收到精简 prompt
4. spawn Agent                         →  6. LLM 理解内容
                                       →  7. [inform] 只读,无需操作
                                       →     [request] 回复发件者(curl
                                       →  8. Agent turn 结束
9. on_complete 触发(进程退出)
10. [新增] 系统标 done/failed
    - inform → 直接标 done
    - request → 幻觉门控验证后标 done/failed

4.2 异常流

异常 处理方 方式 现有机制?
spawn 失败 系统 标 failedreason: spawn_failed),不标 working 需新增
Agent 执行超时/崩溃 系统 Ticker _check_timeoutsworking 超 default_task_timeout_minutes 标 failed 已有
Agent 忘记回复(request 系统 幻觉门控:on_complete 时查 DB 有无 in_reply_to 的回复邮件 需新增
Agent 回复 type 写错 prompt 模板提醒 已有
on_complete 标 done API 失败 系统 重试 3 次 + 写日志 需新增

4.3 on_complete 的触发时机

on_complete 在 openclaw 子进程退出时触发(spawner _handle_exit)。子进程的生命周期是:

moziplus spawn openclaw 子进程
  → 子进程调 Gateway API 投递消息到 Agent session
  → Agent main session 收到 prompt
  → LLM 生成回复
  → turn 结束
  → openclaw 子进程退出
  → spawner 检测退出 → on_complete 触发

on_complete 触发 = Agent 已处理完这封邮件(turn 结束)

如果 Agent spawn 了子任务继续干,on_complete 仍会触发(主 turn 结束 ≠ 子任务完成)。这是合理的——邮件投递 = 信息传递到位,不等后续衍生工作。

4.4 超时机制

Mail 任务走标准 task 超时路径,不做特殊处理:

Ticker 每 30s 扫一次 working 状态任务
  → 有 task.deadline?→ timeout = deadline - started_at
  → 无 deadline?→ timeout = default_task_timeout_minutes30 分钟)
  → elapsed > timeout → 标 failed

5. Prompt 模板

5.1 inform 模板(~80 tokens,当前 ~200 tokens

你收到一封飞鸽传书(纯通知)。

发件者: {from_agent}
主题: {title}
内容: {text}

已阅即可,无需操作。

5.2 request 模板(~150 tokens,当前 ~400 tokens

你收到一封飞鸽传书,需要处理并回复。

发件者: {from_agent}
主题: {title}
内容: {text}

请处理后回复发件者:
curl -s -X POST http://localhost:8083/api/mail \
  -H 'Content-Type: application/json' \
  -d '{"from": "{agent_id}", "to": "{from_agent}", "title": "回复: {title}", "text": "你的回复内容", "type": "inform", "in_reply_to": "{task_id}"}'

⚠️ 将"你的回复内容"替换为实际回复。type 必须用 inform 防止循环。

变化:去掉所有状态转换命令(working/done 的 curl),Agent 只看业务内容。

6. 幻觉门控

来源Hermes v0.13 实践——Agent 声称完成时验证产出是否真实存在。

Mail 场景request 类型邮件 on_complete 时,系统查 _mail DB 有无 in_reply_to = task_id 的回复邮件记录:

on_complete 触发
  → _classify_outcome 判断 outcome
  → outcome 正常(release_counter
    → inform → 直接标 done
    → request → 查 DB 有无回复邮件
      → 有 → 标 done
      → 无 → 标 failedreason: no_reply_found

inform 类型不需要门控——不需要回复,on_complete 触发即完成。

7. 改动范围

文件 改动 行数 说明
src/daemon/spawner.py 精简两个模板常量 改 ~40 行 去掉 working/done curl 命令
src/daemon/dispatcher.py spawn 前标 working + on_complete 增强 + 幻觉门控 新增 ~50 行 _mail 专用的 on_complete 回调
src/daemon/ticker.py 不改 0 走标准超时机制

总计 ~90 行改动,涉及 2 个文件。

8. 预期效果

场景 当前 v2.7.0 优化后 v2.7.1 说明
inform 邮件(Agent 侧) 4 次 LLM, ~13k tokens 1 次 LLM Agent 读内容后无操作,系统标 done
request 邮件(Agent 侧) 4 次 LLM, ~13k tokens 2 次 LLM Agent 读+回复,系统标 done
inform prompt ~200 tokens ~80 tokens 省掉状态转换命令
request prompt ~400 tokens ~150 tokens 省掉状态转换命令
状态可靠性 依赖 LLM 遵守 系统保证 最大收益

9. 不做的事

  • isolated session 投递(必须是主 Agent 来决定是否 spawn
  • Mail 专用超时配置(走标准 task 超时路径)
  • inform 类型跳过 LLM(Agent 需要读内容,信息不能丢)