agent-lead

August 28, 2026 · View on GitHub

主 Agent 只负责理解、拆解、分发、验收与监工;改动类工作一律通过 assign 派给后台 subagent。每次派活都弹窗,由选这个 subagent 用哪个模型。

装在 ~/.dsh/plugins/agent-lead/,通过 ~/.dsh/cordis.patch.ymlinsert 行挂到宿主,对所有 agent 预设生效。

怎么用

输入行为
/lead切换带队模式开关(再次输入退出)
/lead off强制退出带队模式(CLI 等适配器的显式写法)
/lead auto开启全自动派活(assign 不弹窗,自动采用上次选择的模型)
/lead manual恢复手动选模型(assign 每次弹窗)
/lead auto <任务>开启全自动派活 + 同时提交任务
/lead manual <任务>恢复手动选模型 + 同时提交任务
/lead <任务描述>进入带队模式并提交任务(auto 状态不变)

进入后:

  • 系统提示里出现带队策略(只在开启时出现,关闭时该区段为空、不进请求)。
  • 主 Agent 调 write / edit / str_replace_editor 会被拒绝,并被告知改用 assign 派活。
  • read / grep / glob / bash 保留——勘察和验收要用。
  • 主 Agent 每次调 assign,你都会收到一个模型选择框。

工具概览

工具用途
assign派活给后台 subagent(唯一的创建子 agent 途径),必须声明职责范围(scope)
redirect推翻性指令:一步完成打断 + 清队列 + 发新指令,可顺带更新 scope
manage_queue查看/操作子 agent 的待执行消息队列
lead_status查看所有子 agent 实时状态与派活台账(含地盘地图),派活前必查

scope — 职责范围契约

每次 assign 必须传 scope: { summary, paths }summary 是一句话职责范围(如「负责数据预处理流水线」),paths 是负责的文件/目录清单(相对或绝对路径,目录按内容前缀匹配理解,至少 1 项)。scope 是该 subagent 的地盘契约,写入台账并在 lead_status 中展示。

重叠预警:派活时对照台账中本会话所有子 agent 的 scope.paths 做路径重叠检测——一方路径与另一方相等或互为目录前缀(按 / 边界,尾斜杠归一化)即算重叠。有重叠且未传 force: trueassign 报错,列出重叠的子 agent、其职责与重叠路径,并提示改用 send_message/redirect 派给地盘主人;确认确需新建(如原 subagent 已退役)时带 force: true 重试。

scope 更新:走 redirect 的可选参数 scope(结构同 assign)——推翻指令时如新工作超出原职责范围,传入新 scope 覆盖台账记录,同样做与其他子 agent 的重叠检测(排除目标自己)+ force 逃生门。

派活决策链(四步)

带队策略要求派活前先调 lead_status 查看地盘地图,按四步决策链路由。

第一步:要不要新建(六条规则,按优先序,前面的一票否决后面的)

  1. R1 单一写者:要改的文件与在编 subagent 地盘重叠 → 必须派给它,绝不新建第二个写者。
  2. R2 返工归原主:验收不合格发回原主;同一问题返工 2 次仍不合格 → 止损换人,prompt 写明失败史。
  3. R3 独立评审必须新人:审查/验收某产出永远不派给原作者或同域老 subagent。
  4. R4 同域延续优先复用:建立在已完成工作之上且未跑偏 → 复用,交底只写增量。
  5. R5 独立新域必新建:无文件、无知识重叠或需真并行 → assign 新建,声明不重叠的 scope。
  6. R6 污染即退役:被 redirect 2 次以上、跑偏或自相矛盾 → 不再派新活,新建接班人。

第二步:复用哪个

由 R1/R2/R4 指向的唯一对象;有歧义时以 lead_statusscope.paths 重叠度为准。

第三步:选投递方式(三选一判定梯)

情形投递方式
新指令推翻/取代目标 subagent 正在跑或已排队的工作redirect(打断+清队+新指令一步完成)
新指令是追加/后续、不与在跑工作冲突send_message 排队为下一轮
不需要新指令、只修正已排队还没执行的指令manage_queue(replace/remove/push_front),不发新消息
拿不准冲不冲突manage_queue list 看队列 + lead_status 看在跑什么,再决定

第四步:撰写指令(复用与新建同一标准)

给老 subagent 的 send_message/redirect 消息和给新 subagent 的 assign prompt 是同一种东西——完整任务书,不是传话。用户的原话只是素材,主 Agent 必须自己补全后再下发。

增量交底模板(复用时):

  1. 承接:「你之前完成了 X/正在做 X」
  2. 变化:什么变了、为什么(用户新决定、其他 subagent 的相关产出、验收结论等它不知道的信息)
  3. 新目标:做什么、不做什么
  4. 涉及路径(超出原 scope 时 redirect 顺带更新 scope)
  5. 验收标准

**增量原则:**老 subagent 已有的上下文不重复,但它不知道的信息必须写全——它看不到主会话。

注意send_message 是宿主全局工具,其使用规范由带队策略文本约束(宿主工具描述不可改),不在本插件代码层面做参数校验。

工作流程

带队模式采用「简版派工单」流程——给人看的简明扼要,给 subagent 的完整自足:

  1. 规划阶段:Agent 勘察现状后,输出简版派工单(每个子任务一行:任务名 + 一句话说清干什么),等用户确认。如果方案已在本会话定案(计划模式或用户直接给出),不复述方案,直接给拆解映射。
  2. 执行阶段:用户确认后(ok/go/执行/没问题等),Agent 按决策链路由——新建用 assign,复用用 send_message/redirect——立即并行派活。下发给 subagent 的指令包含完整背景、目标、路径、验收标准——subagent 看不到对话。
  3. 验收阶段:子任务完成后,Agent 按下发指令里的验收标准读文件、看 diff、跑检查,向用户汇报结论和问题,不复述过程细节。

redirect — 推翻性指令

当你需要彻底推翻子 agent 当前的工作方向时,必须用 redirect(一步完成),不要 interrupt_agent + send_message 两步走(两步走存在中间状态竞态)。

参数:

参数类型必填说明
subagentIdstring目标子 agent 的 session id
messagestring新指令(完整自足,取代一切旧指令)
clearQueueboolean-是否清空待执行队列(默认 true)
scopeobject-新职责范围契约(覆盖台账记录,做重叠检测)
forceboolean-新 scope 与他人重叠仍要覆盖时传 true

执行链路:后代校验 → interrupt → clear inbox → followup(带「指令更替」前缀)→ 写台账。

manage_queue — 队列管理

查看或操作子 agent 的待执行消息队列。支持六种 action:

action需要说明
list查看 next-turn / next-step 两个列表(离线时返回空)
clear清空全部排队消息
removemessageId按 id 删除一条排队消息
replacemessageId + message替换一条排队消息的内容
pushmessage追加一条消息到 next-turn 队尾
push_frontmessage插入一条消息到 next-turn 队首

注意:队列操作只对在线子 agent 生效。子 agent 不在线时,list 返回空并注明离线,其余操作报错要求先用 send_message 唤醒。

lead_status — 状态概览

无参数调用列出所有子 agent;传 subagentId 过滤单个。返回每个子 agent 的:

  • id、标题(label)
  • 活动状态(running / inactive / unknown)
  • 模式(continuable / one-shot)
  • 模型、provider
  • 派活时间、已运行时长
  • 职责范围 scope(summary + paths,旧条目可能缺席)与 redirect 次数(职责=数据预处理[src/preprocess]redirect×2职责=数据预处理[\text{src}/\text{preprocess}] \text{redirect} \times 2
  • 最近一次操作摘要
  • 在线时的队列积压条数

无子 agent 时返回空列表不报错。派活(assign)前必须先调本工具查看地盘地图,决定复用还是新建。

模型只能弹窗选

assign 只有 descriptionprompt 两个参数,没有 model 参数:模型花多少钱、值不值得,是你的决定,不是模型的决定。所以这里既没有自然语言识别,也没有别名、默认值和「记住上次选择」。

弹窗候选按三段组装,按 provider|model 去重(先出现者保留):

  1. 当前主模型 —— 该会话此刻真正在用的路由,标注「(当前主模型)」。读取顺序:request/header 的 config → request/contextagent.options;首轮请求之前读不到,这一段就省略。
  2. 最近最常用的 N 个 —— 来自本插件自己的派活历史,标注「(常用)」。按出现次数降序,同次数看最近一次使用时间。
  3. 配置里固定列出的模型 —— 原序展示,保证弹窗永远非空。

显示名优先用配置里的 label,其次是 provider 目录(ctx.llm.listModels)里的名字,最后退回 model id。标签重复时自动追加 · <provider> 消歧。

配置

写在 ~/.dsh/cordis.patch.yml 的这一行里:

    - id: agent-lead
      name: '/home/jiangjunguang/.dsh/plugins/agent-lead/index.mjs'
      config:
        llmProvider: hfai
        rulesFile: /home/jiangjunguang/.dsh/captain-rules.md
        models:
          - id: anthropic/claude-opus-4.6
            label: Opus 4.6
            description: 强,贵,适合复杂实现与重构
          - id: deepseek-v4-flash
            label: DeepSeek-V4-Flash
            description: 快,便宜,适合批量与机械改动
key含义默认
llmProvider子 agent 默认 LLM 路由必填
models[]{ id, label?, provider?, description? },固定候选段必填非空
includeCurrentModel是否把当前主模型置顶为一项true
recentCount「常用」段条数3
recentWindow统计频次时只看最近多少条派活记录50
usageFile派活历史文件(绝对路径)$DSH_HOME/agent-lead-usage.json
rulesFile全局 captain 规矩文件(绝对路径,Markdown)$DSH_HOME/captain-rules.md
subagentProviderctx.subagents 提供者spawn
toolName派活工具名assign
commandName命令名lead
maxDepth子 agent 深度上限3
lockedTools[]开启时禁止主 Agent 自己调用的工具(空数组=不锁)['write','edit','str_replace_editor']
section带队策略提示文本({{tool}} 会替换成工具名)内置中文文本

配置非法(models 为空、label 重复、recentCount 不是正整数、usageFile 非绝对路径、rulesFile 非绝对路径、commandName 不合法…)会在加载期抛错,而不是等到第一次派活才失败。

rulesFile — 全局带队规范

rulesFile 指定一个 Markdown 文件路径(默认 ~/.dsh/captain-rules.md)。文件存在时,其内容附加到带队策略区段末尾,标题「## 全局带队规范(来自 captain-rules.md)」;不存在静默跳过;读失败 warn 不致命。

用途:把跨项目通用的 captain 规矩(代码风格约束、review 标准、禁止事项等)写在这个文件里,所有带队会话都能看到,不用每个项目的 AGENTS.md 重复写。

assign.taskId

assign 工具的可选参数 taskId(string)保留:对应已发布计划中的子任务 id,派活时带上。不填也不影响派活本身的功能。

状态与数据

  • 模式状态不写新的 session 事件类型:Session.append 无法给事件打 ignorable,而 KNOWN_SESSION_EVENT_TYPES 之外的类型会让日志加载直接拒绝。状态由 commands 注册表本来就会写的 command/runname === commandName)折叠得出——空 args toggle 取反、off 强制退出、auto / manual 精确匹配切模式、auto <任务> 前缀开启 auto + 提交任务、manual <任务> 前缀关闭 auto + 提交任务、其他 args 开启 active(auto 不变)——因此 resume / fork / compaction 之后都能恢复,也满足「模型可见 ⟺ 已记录」。
  • 派活历史存在 usageFile{ schema: 1, entries: [{ provider, model, time }] },只保留最近 200 条,写入串行化并原子替换(*.tmp + rename),文件权限 0600。只在派活成功启动后才记一条,失败的派活不进「常用」排序。
  • 派活台账(内存态):每会话维护 childId → { description, promptHead, provider, model, startedAt, scope, redirectCount, actions } 的 Map。assignredirectmanage_queue 成功后记录;redirect 自增 redirectCount。进程重启后台账丢失(只影响 lead_status 的历史展示与重叠预警,不影响功能);旧会话内没有 scope/redirectCount 字段的条目按缺席/0 处理,不崩。

已知限制

  • 每次派活都要人点一次。 这是设计目标,不是待优化项;不想点就 /lead off
  • 只派后台可续 subagent。 结算通知 + send_message / interrupt_agent 正是监工闭环需要的;本工具没有前台等待路径。
  • 子 agent 不能用 assign 再往下派活。 提问通道只认活着的根 agent(DELEGATED_CALLER),此时工具会报错并要求它把待定决定写进最终结果交回主 Agent。
  • 没有提问通道就直接失败。 没有 model 参数可兜底,headless / ACP 会话里 assign 会报错而不是偷偷挑一个模型。
  • 历史是本机单文件。 多个 dsh 进程并发写为最后写入者赢;读失败只影响候选排序,不影响派活。
  • 台账为内存态。 进程重启后丢失。只影响 lead_status 历史展示,不影响工具功能。
  • 切换模式会让系统提示前缀变化,因此那一次请求的 KV cache 命中会失效一次。
  • 「梁神模式」phase-1 锚定期看不到 assigntool-bootstrap 会把工具裁到两件),晋升后出现——符合该预设的设计。
  • 结算误报 — DSH 核心侧的结算通知有时把正常完成的 subagent 标记为 failed/stopped,属已知核心侧问题,后续跟进。带队策略已要求 captain 先查产物再定性。
  • 消息无 read-ack — 目前无法确认子 agent 实际读到了某条消息(只能确认入队),read-ack 属 DSH 核心侧后续跟进。
  • 队列操作只对在线子 agent 生效 — 不在线的子 agent 无法操作其 inbox(inbox 随 Agent 生命周期),需先 send_message 唤醒。