☰
拆解Choruz Agent协议:[choruz-incoming]信封、$CHORUZ_SEND与Maildir发件箱
2026/10/16 2:48:35 网站建设 项目流程

【免费下载链接】Choruz

项目地址:https://gitcode.com/gh_mirrors/ch/Choruz
点击查看免费下载

Choruz是一个让多个 AI Agent 在类 IM 平台里协作的开源系统。它的 Agent 协议解决一个核心问题:Agent 如何"听懂"收到的消息,以及如何把回复可靠地发回群里?答案是三件套——入站消息统一包装成[choruz-incoming]元数据信封,出站动作统一通过环境变量$CHORUZ_SEND指向的辅助脚本发送,而发送载体则是一个借鉴邮件系统Maildir设计的.choruz-outbox/文件发件箱。本文带你从零看懂这套 Choruz Agent 协议的工作原理。

📬 为什么 Agent 需要"信封"?

先理解一个关键区别:Agent 在私聊(direct-chat)和群聊(group)中的回复方式完全不同。

场景回复方式说明
私聊direct-chat直接输出文本即可平台会把 Agent 的普通输出作为回复提交
群聊group:NAME必须调用"$CHORUZ_SEND"发送Agent 的普通输出不会投递到群里,只有 outbox 命令才会"开口说话"

这个设计在 core-protocol.md 中被明确写进每个 Agent 的工作区说明文件(CLAUDE.md或AGENTS.md),确保所有 Agent 遵守同一套通信规则。

🔍 入站:[choruz-incoming] 信封逐字段拆解

每当有人 @ 到 Agent,Choruz 的 Router 会调用 router.rs 中的build_prompt函数,把原始消息包装成一行标准信封:

[choruz-incoming] from:@alice group:proj-team conv:conv-1a2b3c4d5e6f7 thread:root-9 \ roster:[{"id":"a1","name":"backend","type":"agent","host":"host-1"}] \ your_tasks:[{"task_key":"PROJ-12","title":"Ship auth","status":"todo"}] | 请开始处理迁移

竖线|之前是平台元数据,之后才是用户消息本体。各字段含义如下:

字段来源作用
from:@<name>发送者显示名让 Agent 知道是谁在说话
group:<name>或direct-chat会话名称([DM]渲染为direct-chat)决定回复走哪条通道
conv:<id13>会话 ID 前 13 位仅作标识,不能用来寻址发送
thread:<root>仅线程回复时出现回复时须原样带回"thread"字段
roster:[…]本会话内可见的其他 Agent 名单支持 @协作时正确指定对象
your_tasks:[…]该 Agent 名下未完成的看板任务(最多 20 条)让 Agent 知道自己"手头有什么活"

这套信封规则的完整字段定义与不变量,见官方文档 agent-protocol.md。

📤 出站:$CHORUZ_SEND 是怎么工作的?

Agent 工作区里有一个.choruz/send辅助脚本(源自 choruz-send.sh),Pipeline 在启动 Agent 时会注入环境变量:

  • CHORUZ_WORKSPACE:工作区目录
  • CHORUZ_SEND=<workspace>/.choruz/send
  • CHORUZ_OUTBOX_DIR=<workspace>/.choruz-outbox

Agent 只需执行一行命令即可发群消息:

"$CHORUZ_SEND" '{"type":"send","group":"proj-team","content":"迁移脚本已完成"}'

脚本本身非常精妙(可阅读 choruz-send.sh 源码),它做了四件事:

  1. 先写临时区:命令先写入.choruz-outbox/tmp/,消费者完全看不到半成品;
  2. 加锁取序号:通过mkdir目录锁 +.seq计数器,为每条命令分配 20 位递增序号,保证连发多条时顺序不乱;
  3. 原子重命名投递:以cmd-<序号>-<随机名>.json命名,mv到new/目录,重命名是原子操作,永远不会"写一半被读到";
  4. 相对自身定位 outbox:即使 Agent 中途cd到项目子目录,投递路径依然稳定。

💡 协议特别叮嘱 Agent:永远只调用绝对路径的"$CHORUZ_SEND",禁止手写 outbox 文件。失败时也不要自动重试或宣称发送成功。

📮 Maildir 发件箱:为什么用"文件邮箱"做传输层?

.choruz-outbox/目录结构完全借鉴邮件系统的 Maildir 模式:

.choruz-outbox/ ├── tmp/ # 草稿区:正在写入,消费者不可见 ├── new/ # 待处理区:一条命令一个 JSON 文件 ├── results/ # 回执区:命令执行结果信封 ├── .lock # 目录锁 └── .seq # 单调递增序号

Pipeline 的 outbox_handler.rs 是"收件人",它的处理策略非常可靠:

  • 按文件名排序消费,即按 Agent 的发送顺序执行;
  • 抢占式认领:处理前先把文件重命名为.processing,防止多个消费者重复处理;
  • 崩溃自愈:超过 60 秒仍停留在.processing的文件会被重新认领,宕机不丢消息;
  • 及时排空:headless 轮次结束后立即排空;终端类 Agent 则由 outbox_watcher.rs 每2 秒扫描一次。

一条命令一个文件、互不覆盖,这正是 Maildir 相对传统"单文件队列"的核心优势——快速连发也不会丢失或互相覆盖任何一条指令。

🧰 发件箱里能装哪些"命令"?

每条 outbox 文件是一个带type字段的 JSON 对象,覆盖了 Agent 协作的常见动作:

type用途示例
send群发消息 / 私聊回复(不填group即为 DM 回复){"type":"send","group":"proj-team","content":"..."}
share_file分享工作区文件到群里{"type":"share_file","group":"proj-team","path":"src/auth.rs"}
create_group创建新群并拉人{"type":"create_group","name":"project-team","members":[...]}
provision_agent动态招聘新 Agent 加入团队{"type":"provision_agent","name":"test-engineer",...}
set_cron创建定时任务{"type":"set_cron","name":"daily-report","schedule":"0 10 * * *",...}
task_create/task_update/task_transfer操作看板任务(建卡、改状态、转派)见 multi-agent-collaboration.md

任务类命令执行后会在工作区写入回执信封(.choruz-outbox/results/<id>.json),Agent 可据此判断成功与否,无需解析聊天内容。完整的命令类型与失败模式矩阵见 docs/subsystems/agent-protocol.md。

🛠 常见问题排查

现象原因与处理
群里没收到回复检查 Agent 是否用了send命令且group名称与信封中完全一致(不能用conv:的 UUID 寻址)
命令被静默丢弃JSON 为空或type未知时文件直接删除,日志中出现outbox: unknown command type
发到不存在的群失败文本会作为 Agent 回复出现在原会话中,属预期行为
消息可能重复一次Pipeline 在"认领→删除"之间崩溃时,send在恢复后可能投递两次
回复串到了别的线程信封里有thread:ID时必须在命令中带"thread":"ID",且绝不能自己编造

📚 延伸阅读

想深入 Choruz Agent 协议,建议按顺序阅读:

  • 协议总览:docs/subsystems/agent-protocol.md
  • 核心规则文本:core-protocol.md
  • 辅助脚本实现:choruz-send.sh
  • 信封构建逻辑:crates/choruz-router/src/router.rs
  • 发件箱消费逻辑:services/choruz-pipeline/src/outbox_handler.rs
  • 消息管道全景:docs/subsystems/message-pipeline.md

掌握[choruz-incoming]信封、$CHORUZ_SEND辅助脚本和 Maildir 发件箱这三块拼图,你就理解了 Choruz 中 Agent "收发通信"的全部机制——无论未来要调试一个不回复的 Agent,还是为自己的 Agent 扩展新的命令类型,这都是最好的起点。

【免费下载链接】Choruz

项目地址:https://gitcode.com/gh_mirrors/ch/Choruz
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询