第 14 章 · Secondmate:持久第二副手与隔离章程
本章目标:理解 secondmate(第二副手)的定位与隔离模型,学会用
config/secondmate-harness配置其启动方式,并掌握"secondmate 不孵化 secondmate"这条关键边界。
14.1 为什么需要第二副手
随着舰队规模扩大,一个常见问题浮现:所有 crewmate 都从主 home 派出,任务类型一多,主 firstmate 的监督面就越来越宽——前端修复、后端审计、文档巡检混在同一个 backlog 和同一套 state 里。
FirstMate 的解法不是引入新架构,而是复制现有架构:
A secondmate is a crewmate with an isolated firstmate home and a charter, not a second architecture.
也就是说,secondmate 本质上仍然是一个 ordinary direct report(普通直接下属)——它和普通 crewmate 一样接受主 firstmate 的路由与监督;区别在于它运行在一个隔离的、持久的 firstmate home 里,并携带一份 charter(章程)界定自己的职责域。
这种设计的收益:
- 职责域划分:每个 secondmate 只接自己章程范围内的工作,路由按工作性质而非克隆清单进行;
- 状态隔离:各自的 backlog、state、projects 互不干扰;
- 可长期存在:secondmate 是持久实体,空闲队列是健康态,不需要时也不必销毁。
14.2 隔离的 FM_HOME:每个 secondmate 一个家
AGENTS.md 对此有一条明确约定:
Each secondmate has a persistent isolated
FM_HOME, including its own state, backlog, projects, and session lock.
回顾第 5 章的布局知识:FM_HOME 选定一个实例私有的 data/、state/、config/、projects/。对 secondmate 而言,这意味着:
主 home(PRIMARY)
├── FM_HOME=~/firstmate-home-main
│ ├── data/backlog.md # 主 backlog:只记工作项
│ ├── data/secondmates.md # secondmate 路由表
│ ├── state/ # 主 home 运行记录
│ └── projects/ # 主 home 的项目克隆
└── 注册的 secondmate
└── FM_HOME=~/firstmate-home-infra # 完全独立的第二个家
├── data/backlog.md # 自己的积压队列
├── state/ # 自己的运行记录 + session lock
├── config/ # 自己的本地运营配置
└── projects/ # 在自己家里克隆的项目几个关键点值得展开:
- session lock 独立:每个 home 有自己的会话锁,两个 home 的引导流程互不竞争;
- backlog 分账:路由给 secondmate 的工作记在该 secondmate home 自己的 backlog 里,而不是主 backlog;
- projects 各自克隆:secondmate home 需要哪些项目就在自己家克隆,主 home 的
projects/对它是不可见的。
data/secondmates.md 是主 home 维护的 local and remote secondmate routing table(本地与远程 secondmate 路由表),由 secondmate seed 辅助脚本维护,记录每个已注册 secondmate 的位置信息。
14.3 charter 章程:职责域的书面边界
每个 secondmate 携带一份 charter brief。在 data/ 布局中可以看到它的存放形式:
data/
├── <id>/brief.md # per-task crewmate brief,
│ # 或 kind=secondmate 时的 per-secondmate charter briefcharter 回答的问题是:"这个 secondmate 负责哪一类工作?" 主 firstmate 路由时遵循的规则是:
Route by the nature of the work against each registered secondmate scope.
即按工作的性质对照各 secondmate 的注册范围来路由,而不是看某个仓库恰好登记在谁名下。若没有合适的 secondmate 范围能承接某项工作,就用主 home 处理,或者讨论创建一个新的 secondmate。
另外两条路由纪律值得记住:
- 范围匹配的工作默认发给对应的 secondmate,除非它被阻塞或 captain 明确改道;
- 不要去翻 secondmate 的聊天窗口——标记路由的回复会通过 status 或文档指针返回。
14.4 启动配置:config/secondmate-harness
主 home 用 config/secondmate-harness 指定用哪个 harness 启动 secondmate agent:
# config/secondmate-harness(LOCAL, gitignored)
# 格式:<harness> [<model>] [<effort>],三段写在同一行
# 例:用 Claude Code 启动 secondmate
claude
# 例:指定模型与 effort
pi sonnet medium回落顺序是本章的重点记忆点:
config/secondmate-harness 存在且有效?
├─ 是 → 用它启动 SECONDMATE
└─ 否(缺失或值为 default)
└─ 回落到 config/crew-harness
└─ 再回落到 firstmate 自己正在用的 harness注意它与 config/crew-harness 的分工:
| 文件 | 控制对象 | 继承行为 |
|---|---|---|
config/crew-harness | 本 home 派出的 crewmate | 作为字面文件被继承:具体的 primary adapter 值也会控制 secondmate home 自己的 crewmate |
config/crew-dispatch.json | 每任务的 harness/model/effort 选择规则 | Inherited by secondmate homes |
config/secondmate-harness | PRIMARY 启动 SECONDMATE 的方式 | NOT inherited into secondmate homes |
crew-harness 的继承语义比较特殊——它是"inherited as the literal file":如果主 home 写了 claude,那么 secondmate home 自己派 crewmate 时也用 claude。而 secondmate-harness 只属于 primary 一侧。
14.5 关键边界:secondmate 不孵化 secondmate
这是整个 secondmate 体系最重要的一条安全设计:
The primary's own setting; NOT inherited into secondmate homes (secondmates do not spawn secondmates).
为什么这样设计?因为一旦允许 secondmate 再创建自己的 secondmate,舰队就会形成任意深度的树状结构,带来三类问题:
- 监督链失控:主 firstmate 的恢复协议明确写着"Do not reconstruct or supervise a secondmate's child tree from the main home"——主 home 不跨层重建或监督子树。层级超过两层后,故障恢复的确定性无法保证;
- 责任稀释:硬规则要求所有沟通经由 firstmate 汇报给 captain,中间层越多,信息保真度越差;
- 资源不可控:嵌套孵化会让 agent 数量指数增长。
所以 FirstMate 把层级严格限制为两代:captain → firstmate → {crewmate, secondmate},而 secondmate 手下只能有普通 crewmate:
you (the captain)
└── firstmate(主 home,PRIMARY)
├── crewmate × N ← 由 config/crew-harness / crew-dispatch.json 决定
└── secondmate × M ← 由 config/secondmate-harness 决定
└── 它自己的 crewmate × K(受继承的 crew-harness 控制)
(到此为止,不能再有第三代 secondmate)14.6 secondmate-provisioning:供给流程概览
创建、供给、校验、启动、交接 backlog、恢复、推送继承材料、退役 secondmate home,以及编辑 data/secondmates.md——这些操作全部由内部技能 secondmate-provisioning 负责(第 13 章讲过 .agents/skills/ 下的 agent-only 技能体系)。作为 captain,你只需要知道流程骨架:
1. 提出需求 "我想为一个长期维护的基础设施项目设一个专职 secondmate"
2. 加载技能 firstmate 加载 secondmate-provisioning
3. 创建 home 建立独立 FM_HOME,写入 charter brief
4. 注册路由 更新 data/secondmates.md 路由表
5. 继承材料 按 allowlist 同步继承配置(如 crew-harness、crew-dispatch.json)
6. 校验启动 校验通过后按 secondmate-harness 启动
7. 日常路由 范围内工作自动发往该 home;回复经 status/文档返回
8. 退役 仅在 captain 或主 firstmate 明确决定时执行,
且该 home 必须无进行中的工作两条补充纪律:
- A secondmate is idle by default and acts only on work routed by the main firstmate. secondmate 默认闲置,只做主 firstmate 路由来的工作,不会自找活干;
- 持久实体不进 backlog。 AGENTS.md 明确写道:"It tracks work items only, never agents; persistent secondmates never appear as backlog items." secondmate 记录在注册表与运行时状态里,绝不作为积压工作项管理。
14.7 何时值得引入 secondmate
引入 secondmate 有成本(多一个 home 要维护、多一份章程要写),以下场景才划算:
- 职责域长期稳定:比如一个需要持续巡检的基础设施 monorepo,或一条固定的内容生产流水线;
- 状态需要硬隔离:主 home 的 backlog 已混杂多个领域,希望各领域的任务队列、学习记录(learnings)、captain 偏好分开管理;
- 并行规模超出单 home 舒适区:多个长期项目同时推进,各自需要独立的 session lock 与 projects 克隆。
反之,偶发的并行需求用普通 crewmate 就够了——worktree 隔离(第 9 章)已经能保证互不冲突。
本章小结
- secondmate = 带隔离 firstmate home 和 charter 的普通直接下属,不是第二种架构;
- 每个 secondmate 拥有持久的独立
FM_HOME:自己的 state、backlog、projects 与 session lock; config/secondmate-harness决定 PRIMARY 用哪个 harness 启动 SECONDMATE,缺省依次回落到crew-harness与 firstmate 自身;crew-harness与crew-dispatch.json被 secondmate home 继承,secondmate-harness不被继承——secondmates do not spawn secondmates,舰队严格限制为两代;- 供给全流程由
secondmate-provisioning技能负责;secondmate 默认 idle,是持久实体而非 backlog 工作项。
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. 按照官方定义,secondmate 最准确的描述是?
2. 当 config/secondmate-harness 缺失或值为 default 时,PRIMARY 会如何选择启动 harness?
3. 关于 secondmate 的嵌套,正确的说法是?
4. 下列哪项符合 secondmate 的日常纪律?
🛠️ 动手实践
- 在纸上(或文本编辑器里)画出你的目标舰队拓扑图:标注主 home、计划中的 secondmate 数量、每个 secondmate 的章程职责域,以及每个 home 将使用的 harness。检查是否存在任何需要"第三代 secondmate"的场景,若有,重新划分职责域使其落在两代结构内。
- 在你的主 home 中创建
config/secondmate-harness,写入与你当前 harness 不同的另一款验证过的 harness(例如主会话用pi,则写claude),然后向 firstmate 提问"你现在会用什么 harness 启动 secondmate?crewmate 又用什么?",核对回答是否体现了两者的回落与继承关系。 - 向 firstmate 发起一次真实供给对话:"请为 <某个你长期维护的项目> 创建一个 secondmate,章程是……"。观察它是否加载了
secondmate-provisioning技能、是否建立了独立 FM_HOME 并更新了data/secondmates.md;随后给它发一项范围外的工作,验证它是否会拒绝或转回主 home 处理。