跳到主要内容

第 4 章 · 编排自动化、安全边界、巧妙之处、代码地图

前三章讲清了「一个 agent 怎么被生出来、靠什么协作、为什么任意 CLI 能接入」。本章讲剩下的自动化机制、安全边界,并提炼可借鉴的精华与横向对比,最后给一张代码地图。

4.1 自动化编排:从「被动看板」到「主动唤醒」

ClawTeam 的基础形态是被动的——agent 要自己路过看板。但它提供了几个主动的协调器,都实现成「前台轮询循环 + 信号优雅退出」的同一套路。

TaskWaiter:leader 阻塞等全员完成

clawteam task wait 背后是 TaskWaiter.wait()(clawteam/team/waiter.py:66-165)。每轮循环做四件事:① 把自己信箱里的消息排干(触发回调);② 探测死掉的 agent,把它没干完的 in_progress 任务退回 pending(_check_dead_agents,第 168-191 行,这是自动故障恢复);③ 统计任务进度;④ 全完成 / 超时 / 被中断则返回。

LeaderWatcher:把状态变化「推」回 leader

更聪明的是 LeaderWatcher(clawteam/team/leader_watcher.py)。它周期性给团队状态拍快照(完成了哪些、leader 有几封未读、谁死了、有无阻塞),算一个签名;只在签名变化或心跳到期时,才生成一段「调度检查」摘要并注入到 leader 的 tmux pane——注入失败就退回写进 leader 信箱(_inject,第 238-277 行)。

团队状态拍快照 ──► 算签名 ──► 和上次签名比

没变 且 没到心跳 ────┴──► 啥都不做(避免刷屏)

变了 / 心跳到期 ────► 渲染摘要 ──► 注入 leader pane
(失败 → 写 leader 信箱兜底)

这解决了一个真实痛点:leader agent 可能停在那里「等指令」,而 worker 已经悄悄完成了任务。LeaderWatcher 主动捅它一下:「有 3 个任务完成了、你有 2 封未读,要不要看看?」它还能订阅 Redis 频道做事件驱动唤醒(_run_redis_loop,第 129-163 行),否则退回轮询。

Harness:可选的「先计划后执行」阶段机

clawteam harness 是一套更重的编排:把一次运行拆成 plan → execute → verify阶段,每阶段之间有门(gate)——比如 PLAN 阶段必须产出 spec.md(ArtifactRequiredGate)、VERIFY 阶段必须所有任务完成(AllTasksCompleteGate)、还能插人工审批门(HumanApprovalGate)(clawteam/harness/orchestrator.py:56-61)。HarnessConductor 是个前台循环,自动按阶段派生对应角色的 agent、把契约转成任务、推进阶段(clawteam/harness/conductor.py)。

诚实说明: harness 是项目里相对独立、较「进阶」的一支(对应 templates/harness-default.toml)。它依赖事件总线和角色/契约抽象(harness/roles.pyharness/contracts.py),复杂度明显高于核心的 spawn/task/inbox 三件套。一般用法(README 三个 use case)走的是核心三件套,不经过 harness。

EventBus:给插件留的挂钩

各管理器在关键动作后会 emit_async 事件(任务创建、任务完成、worker 派生、工作区合并/清理……),走一个同步优先级派发、可后台异步触发的 EventBus(clawteam/events/bus.py)。它本身不改变核心行为(所有 emit 都包在 try/except: pass 里),纯粹是给插件(如 plugins/ralph_loop_plugin.py)和 shell 钩子提供扩展点。

4.2 模板与一键拉队

clawteam launch <template> 从 TOML 模板一次拉起整支队伍。模板用 [template.leader] / [[template.agents]] / [[template.tasks]] 描述角色、任务和提示词,支持 {goal} / {team_name} / {agent_name} 变量替换。内置的 hedge-fund.toml(clawteam/templates/hedge-fund.toml)定义了一个 7 agent 投资分析队:portfolio-manager(leader)+ 5 个不同策略的分析师 + 1 个 risk-manager,任务的提示词里直接写明了协作流程(分析师把信号发给 risk-manager,risk-manager 汇总后发给 PM)。这就是 README use case 3 的全部实现——没有硬编码编排逻辑,协调全靠提示词 + 任务依赖

4.3 接口入口:CLI 与 MCP

ClawTeam 对外有两个等价入口:

  • CLI(clawteam/cli/commands.py):Typer 构建,一个根 app 挂十几个子 Typer(team/task/inbox/board/workspace/plan/lifecycle/harness…)。--json 全局 flag 让所有命令输出机器可读 JSON(给 agent 解析)。
  • MCP server(clawteam/mcp/server.py):用 FastMCP 把同一批管理器包成 MCP 工具(mcp/tools/ 下按 board/cost/mailbox/plan/task/team/workspace 分组)。server 本身极薄——遍历 TOOL_FUNCTIONS 注册,每个工具用 translate_error 统一错误转换(第 16-29 行)。

两条入口共用同一套协调层逻辑,只是表现形式不同。

4.4 安全边界:文件系统是攻击面

既然所有状态都是「按队名/agent 名拼出来的文件路径」,路径注入就是头号风险(teamName="../../etc")。ClawTeam 用两个小函数守住(clawteam/paths.py):

  • validate_identifier:只允许 [A-Za-z0-9._-],显式拒绝 ...(第 11-23 行)。
  • ensure_within_root:把拼出的路径 resolve() 后,验证它仍在 root 之内,否则抛错(第 26-35 行)。

几乎每个碰文件路径的函数(_tasks_root_inbox_dir_team_dir_registry_path…)都先过这两关。这是把「不可信的逻辑名」安全映射到文件系统的标准防御。

4.5 巧妙之处(可借鉴的技术)

  • 「CLI 即协议」。 不发明 agent 间协议,把协作降维成「跑 shell 命令 + 看共享文件」。代价是没有强类型 RPC,收益是任何能跑 shell 的 agent 零成本接入——这是整个项目最大的设计赌注。
  • claim-by-rename 实现精确一次消费。 用「原子 rename 到 .consumed」做认领、文件锁做独占、解析失败 quarantine 到死信目录(clawteam/transport/file.py:claim_messages + mailbox.py:_parse_claimed_messages)。纯文件也能做出健壮队列。
  • 锁与存活探测联动,死 agent 不锁死任务。 任务锁、死任务回收都查 is_agent_alive,且「不确定」时保守处理(clawteam/store/file.py:_acquire_lock)。
  • tmux 探活看 pane_current_command 区分「agent 在跑」和「agent 退了只剩 shell」,比看窗口存在与否准(clawteam/spawn/registry.py:_tmux_pane_alive)。
  • 启动弹窗自动点掉。 截屏 pane 文本识别「信任目录 / 危险权限」弹窗并模拟按键,是让任意交互式 CLI 无人值守启动的脏活(tmux_backend.py:_confirm_workspace_trust_if_prompted)。
  • env 文件自删 + 解嵌套。 绕开 tmux 命令长度上限与 Claude 自我嵌套检测(tmux_backend.py:140-166)。

4.6 边界与局限(诚实)

  • 单机/共享文件系统优先。 默认 file 传输要求所有 agent 看到同一个 ~/.clawteam/;跨机得靠 NFS/SSHFS 或可选的 P2P(ZeroMQ)传输。Redis 跨机传输在 roadmap 上标 v0.4 Planned(README.md:781),尚未发布。
  • 强依赖外部 CLI 与 tmux。 README 反复强调「若 agent CLI 自己跑不起来,clawteam spawn 救不了你」(README.md:413)。tmux 后端是交互监控的前提。
  • 协调靠提示词「软约束」。 worker 是否真的循环待命、是否真在完成前 commit,取决于 agent 听不听提示词——没有硬性强制。这是「CLI 即协议」的另一面代价。
  • 成熟度。 pyproject.tomlDevelopment Status :: 3 - Alpha,版本 0.3.0;v1.0 的「auth/权限/审计日志」还在探索阶段(README.md:786)。
  • P2P 内部细节 本文未逐行核读(只读了类与初始化);其 ZeroMQ 发送/对等发现以文件回退兜底,行为以 clawteam/transport/p2p.py 类文档为准。

4.7 横向对比(同 shelf 兄弟)

ClawTeam 属于 ai-frontier-reference 货架「agent loop / 多 agent 编排」分支(见 docs/guide/agent-loop.md)。它和兄弟项目的取舍差异:

项目多 agent 怎么编排基础设施代码隔离
ClawTeamagent 自己跑 CLI 命令,看共享文件文件 + tmuxgit worktree
AutoGen / CrewAI人类用 Python 写 agent 拓扑与对话流进程内对象无(同进程)
LangGraph人类把多 agent 编成状态图进程内 / 可加检查点存储
OpenAI Agents SDK人类用 handoff/工具定义编排进程内

核心差异一句话:别人是「人写编排代码、agent 在一个进程里对话」;ClawTeam 是「agent 自己当编排者、每个 agent 是独立 OS 进程 + 独立 git 分支」。 前者强类型、好调试;后者真隔离、CLI 无关、更接近「在真实终端上指挥一群真实 agent」。

4.8 代码地图(导航索引)

主题文件关键符号
spawn 总流程clawteam/cli/commands.pyspawn_agent
tmux 后端clawteam/spawn/tmux_backend.pyTmuxBackend.spawn / _inject_prompt_via_buffer / _confirm_workspace_trust_if_prompted
后端抽象clawteam/spawn/base.pySpawnBackend
CLI 适配器clawteam/spawn/adapters.pyNativeCliAdapter.prepare_command / is_claude_command
保活续跑clawteam/spawn/keepalive.pybuild_keepalive_shell_command / build_resume_command
存活探测clawteam/spawn/registry.pyis_agent_alive / register_agent / _tmux_pane_alive
提示词构建clawteam/spawn/prompt.pybuild_agent_prompt
数据模型clawteam/team/models.pyTeamConfig / TaskItem / TeamMessage / TaskStatus / MessageType
任务板存储clawteam/store/file.pyFileTaskStore / _resolve_dependents_unlocked / _acquire_lock / _validate_blocked_by_unlocked
信箱层clawteam/team/mailbox.pyMailboxManager / _parse_claimed_messages / broadcast
传输:文件clawteam/transport/file.pyFileTransport / claim_messages / _quarantine_bytes
传输:接口/P2Pclawteam/transport/base.py / p2p.pyTransport / P2PTransport
队伍管理clawteam/team/manager.pyTeamManager.create_team / add_member / resolve_inbox
工作区clawteam/workspace/manager.py / git.pyWorkspaceManager.create_workspace / merge_workspace / git.create_worktree
等待全员完成clawteam/team/waiter.pyTaskWaiter.wait / _check_dead_agents
主动唤醒 leaderclawteam/team/leader_watcher.pyLeaderWatcher.check_once / _inject
生命周期协议clawteam/team/lifecycle.pyLifecycleManager
harness 阶段机clawteam/harness/orchestrator.py / conductor.pyHarnessOrchestrator / HarnessConductor
事件总线clawteam/events/bus.pyEventBus.emit / emit_async
路径安全clawteam/paths.pyvalidate_identifier / ensure_within_root
MCP 入口clawteam/mcp/server.pymcp / main
团队模板clawteam/templates/hedge-fund.toml[template.leader] / [[template.agents]]
协作知识(给 agent)skills/clawteam/SKILL.md——