v2.1.178 起,Agent Teams 的生命周期管理从「主 Agent 全托管调度」转向「团队成员自治 + 共享任务板 + 邮箱直连」,Teammate 可以认领任务、私信同级、主动退出,Lead 的角色被收窄为创建者与终结者。本文按废弃项、新模型、落地步骤三段拆解,帮助把存量脚本里那些被悄悄移除的工具与字段一次替换完。
一、为什么会有这次重写
v2.1.32 引入 Agent Teams 之后的一年里,工程团队普遍撞上同一个问题:Lead 既是协调者又是信息中枢,所有跨 Teammate 的通信都得绕回主会话,token 消耗随成员数线性放大。v2.1.178 的核心目标,是把生命周期事件的归属从 Lead 拆出来还给 Teammate 自己——创建归 Lead,运行归 Teammate,销毁归显式调用。
落到配置上有三处可观察变化:
| 维度 | v2.1.32 模型 | v2.1.178 模型 |
|---|---|---|
| 通信路径 | 仅 Lead 中转 | 任意两点直接 SendMessage |
| 任务认领 | Lead 分配 | TaskList 自取 + TaskUpdate 标记 |
| 退出方式 | 关闭主会话 | TeamDelete 显式销毁 |
| 状态文件 | 单一 config.json | config.json + 共享任务目录 + 邮箱目录 |
| 任务所有权 | owner 可空 | 任何有 status 的任务必填 owner |
理解这点差异,是判断哪些旧工具、字段已经失效的前提。owner 由”派发时填”改为”认领时填”,表面是字段的归位,本质是把”任务归属”这件事从派发路径搬到认领路径。Lead 不再可能因为派发顺序错乱而把同一份任务分给两个 Teammate;任何 Teammate 拿到 pending 任务后,必须先写自己的 owner,其它成员看到 owner 非空就会主动跳过。这种”先认领后执行”的小改动,把冲突排查从”事后追责”压到了”事前避让”,是 v2.1.178 在工程体验上最直观的进步。
二、必须替换的废弃项
2.1 工具层:Task 已分裂为两个
旧版的 Task 工具身兼三职:派发子任务、创建团队、注册模型。在 v2.1.178 中,Task 只保留派发能力,团队相关语义被独立为 TeamCreate / TeamDelete / SendMessage / TaskCreate / TaskUpdate / TaskList 六个原子工具。
| 旧用法 | 废弃原因 | 替代写法 |
|---|---|---|
Task(team_name=...) 启动团队 |
语义与派发任务重叠 | TeamCreate 单独调用 |
Task 内嵌 stop / cancel |
缺少所有权校验 | TeamDelete 显式销毁 |
Task 内部跨会话回写 |
中转成本高 | SendMessage 点对点 |
2.2 字段层:owner 与 status 不再是「可选项」
旧配置里 status: pending 可以没有 owner,由 Lead 在派发时填入。v2.1.178 后,任务进入 in_progress 之前必须先通过 TaskUpdate 写入 owner,否则视作未认领、会被其它 Teammate 跳过。这条规则也直接影响调度循环:自取任务前必须 TaskList() 过滤出 owner == "" 且 status == "pending" 的条目。
| 字段 | 旧行为 | 新行为 |
|---|---|---|
owner |
派发时填充 | 认领者必填 |
status |
单一状态 | 仍是 pending/in_progress/completed |
model |
写在 Task 参数 | 仍是派发参数,不变 |
description |
自由文本 | 仍是任务 prompt,必须自包含 |
2.3 标志位:experimental 触发条件收窄
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS 不再是「开了就能跑」的开关。新版要求同时满足三项:标志位存在、模型 ≥ Opus 4.6、当前仓库可写共享任务目录。少任何一项,TeamCreate 都会返回明确的配置错误,而不是静默退化到旧版 Task 派发。
三、落地替换的四个步骤
把存量脚本迁移到新生命周期模型,按以下顺序最稳妥:
- 拆分
Task调用:把团队创建、任务派发、信件发送从同一处拆成TeamCreate+TaskCreate+SendMessage三段; - 引入共享任务目录:监控
tasks/<team_name>/下的 JSON 文件变化,把它当事件源而不是轮询TaskList; - 加锁 TaskList 自取:用
TaskList拿回所有pending且owner为空的条目,按 hash 抢占后再TaskUpdate写 owner,避免两个 Teammate 抢同一份任务; - 显式销毁流程:每个 Teammate 退出前必须主动调用
TeamDelete,而不是依赖主会话关闭。
# Teammate 启动后抢占一个 pending 任务的最小骨架
import json, time, pathlib
tasks_dir = pathlib.Path.home() / ".claude/tasks/blog-qa"
while True:
pending = [
p for p in tasks_dir.glob("*.json")
if json.loads(p.read_text()).get("status") == "pending"
]
if not pending:
time.sleep(1)
continue
target = pending[0]
payload = json.loads(target.read_text())
payload["status"] = "in_progress"
payload["owner"] = "qa-pages"
target.write_text(json.dumps(payload)) # 真实工程中应用原子写 + 锁
break
注意点:共享任务目录不是消息队列,文件写入若未做原子替换就可能被读到半截状态。建议用 write-to-temp + rename 或引入文件锁,避免「认领到一半 owner 字段缺失」造成的死锁。
四、与旧模型的对照检查
| 检查项 | 旧实现 | 新实现要点 |
|---|---|---|
| 团队入口 | Task 派发时附带 |
独立 TeamCreate |
| 任务认领 | Lead 派 | Teammate 自取 + owner 锁定 |
| 跨成员通信 | 经 Lead 转发 | SendMessage 直达 |
| 退出 | 关主会话 | TeamDelete 显式 |
| 状态文件 | config.json | config + tasks + mailbox 三目录 |
如果代码里还残留旧 Task(team_name=...) 调用,应优先排查它所在的派发路径——这些路径大概率也是 token 消耗较突出的链路,迁到新模型后能直接看到成本下降。
常见问题(FAQ)
Q1:v2.1.178 之后 Lead 还需要负责跨 Teammate 协调吗?
Lead 仅在创建、归档、收束三处介入,运行期间不再做中央调度。
Q2:旧 Task 调用完全不能用了?
派发子任务仍走 Task,但团队相关语义必须改用 TeamCreate 等独立工具。
Q3:实验标志位还需要保留吗?
仍然需要,但同时要满足模型版本与共享目录可写两项前提,缺一即报错。