第 12 章:自动化与多 Agent 编排
1. 两个系统解决不同问题
| 系统 | Automation | Orchestration |
|---|---|---|
| 触发 | 时间、cron、RRULE、手动 | coordinator/CLI/API |
| 主要对象 | automation + run | run + task + dispatch + message |
| Agent 数量 | 通常一个/每次运行 | 多 worker |
| Workspace | 新建或复用 | parent/child/federated |
| 持久化 | 主 Store | SQLite |
| 关注点 | 调度、precheck、历史 | DAG、通信、幂等、所有权 |
2. Automation 数据模型
Automation 通常包含:
- 名称、enabled;
- trigger(预设、cron、RRULE);
- timezone 与下次运行;
- prompt 和 provider;
- repo/new-worktree 或 existing workspace target;
- setup policy;
- fresh/reuse session;
- created/updated metadata。
Run 记录 dispatch 时间、状态、workspace、terminal pane/PTY、output snapshot、错误和 precheck。
类型在 automations-types.ts。
3. 调度不是简单 setInterval
自动化需要处理:
- app 长时间睡眠后补偿;
- timezone/DST;
- disabled / edited schedule;
- 同一 automation 重叠运行;
- repo/host/Agent 不可用;
- headless serve 没有 renderer;
- existing workspace session 已过期。
AutomationService 计算下一次 due,执行 precheck,再通过 runtime/worktree/terminal 现有能力启动,而不是自己复制一套 Git 和 PTY 逻辑。
4. 新 worktree 与复用 workspace
New per run
每次创建独立 worktree,隔离强、历史清楚,代价是磁盘和清理。
Existing workspace
直接在指定 worktree/folder 中启动。reuse-session 会尝试沿用上次 Agent session;若原 terminal 不在,回退 fresh session。
自动化创建的 workspace 会有 provenance,sidebar 可选择隐藏,避免定时任务淹没人工任务。
5. Headless dispatch
没有 renderer 时,runtime 自己维护 session tab snapshot,并为 automation 创建 workspace/terminal。输出通过 headless terminal model 截取有界 snapshot,run history 不依赖挂载 xterm。
这是 main-owned terminal state 的直接收益:自动化不需要假装有一个隐藏 UI。
6. Orchestration 的核心对象
Run
全局 objective、coordinator handle 与 contract generation。
Task
spec、parent、dependencies、状态和结果,构成 DAG。
Dispatch
把 task 分配给具体 worker,记录 capability、pane、process incarnation、heartbeat 与失败次数。
Message
带 from/to、subject、body、type、priority、thread、sequence 与 delivery 状态。
7. Task DAG 的状态机
一个 task 不能仅靠 worker 自报结果改变任意行。report 要匹配 run、task、dispatch、active generation 和 capability。
8. 为什么需要 mutation receipt
网络重试下,“创建 task”“dispatch worker”“发送消息”可能重复。Orchestration DB 保存:
- caller fingerprint;
- request id;
- method;
- payload hash;
- effect/response receipt。
同 caller + request id + 同 payload 返回旧结果;同 id 不同 payload 拒绝。这把 at-least-once transport 提升为应用层幂等副作用。
9. Worker 启动
Worker dispatch 会:
- 解析 placement:同 workspace、child worktree、folder 或 federated host;
- 创建/选择 workspace;
- 执行 setup gate;
- 创建 terminal 与 Agent session;
- 注入任务 spec、身份与 communication contract;
- 等待 ready/heartbeat;
- 将 pane/terminal/incarnation 绑定到 dispatch。
状态细分为 starting、ready、start_unknown、failed、succeeded、stopping、stop_unknown、stopped、abandoned。
start_unknown 很关键:超时不代表 worker 未启动,不能直接安全创建第二个。
10. 消息与 inbox
消息 type 包括 status、dispatch、worker_done、merge_ready、escalation、handoff、decision_gate、question、heartbeat。
worker 通过自己的 capability 读取 inbox/ack;coordinator 可以等待消息或 group address:
@all;@idle;- Agent name group;
@worktree:<id>。
发送消息和直接往另一个 PTY 注入文字不同:消息可追踪、可 ack、可按 run 隔离,并能跨 federation relay。
11. Decision Gate 与 Question
Decision gate 是 coordinator 需要用户/策略选择时的持久对象;question 是 worker 向 coordinator 的交互。
它们都有 pending/resolved/timeout/closed 等显式状态,避免一条自然语言消息被多个并发 worker 各自解释成最终决定。
12. Circuit breaker 与 failure count
同一 task 不应无限失败重启。dispatch context 记录 failure_count 与 last_failure,达到策略边界后进入 circuit_broken。恢复需要明确 reset/新 dispatch,而不是后台自旋。
13. Federation:让 worker 跑在另一环境
Federated dispatch 把 task 放到另一个 paired runtime:
数据库保存 peer fingerprint、protocol、remote epoch、remote worktree/terminal 与双向 imported sequence。断线后按 sequence 续传,不能把旧 peer 的消息导入新 runtime incarnation。
14. Legacy contract 与滚动升级
编排系统仍保留 legacy run/principal/operation receipt 等兼容表。新旧 runtime 共存时通过 contract version 与 capability 决定路径。
升级策略遵循单调性:升级某一层不应让旧工作流突然不可用;但不能为了兼容在 side effect 不确定后降级并重复启动。
15. Agent 状态与编排上下文的连接
worker pane 的 AgentStatusEntry.orchestration 包含 taskId、dispatchId、displayName、parent pane、coordinator handle 和 run id。renderer 因此可以把独立 PTY 显示成 coordinator 的子层级,而无需根据标题猜父子关系。
16. 源码导航
- Automation service:
src/main/automations/service.ts - Automation RPC:
src/main/runtime/rpc/methods/automations.ts - Orchestration DB:
src/main/runtime/orchestration/db.ts - 数据类型:
src/main/runtime/orchestration/types.ts - RPC 方法:
src/main/runtime/rpc/methods/orchestration.ts - federation:
src/main/runtime/rpc/methods/orchestration-federation.ts - CLI handler:
src/cli/handlers/orchestration.ts