dsh-agent-foreman
父智能体派单、子智能体干活的包工头:把任务拆成工单,每张派给你自选的承包商(各自指定 provider、模型、思考等级),交付后逐单验收,打回的单带着你的反馈重新派下去。
安装
dsh plugin --profile web add dsh-agent-foreman
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| 1 安装 | ✓ |
| 2 列装 | ✓ |
| 3 挂载 | ✓ |
| 4 启动 | — |
四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
包工头 · dsh-agent-foreman
父智能体派单,子智能体干活,父智能体验收。
不预置角色、不写剧本:谁干活、用什么模型,由你把关。
最新版本:v0.4.0(2026-10-31) — 原生多模型编队、响应式名册与工地弹层修复。
[安装与升级说明](docs/INSTALL.md)
它解决的问题
DSH 自带的「智能体团队」只能给每个成员一个名字和一段提示词——成员用哪个模型选不了。
而实际干活时,同一批任务里既有需要贵模型把关的部分,也有随手就能做的小改,全部继承
父会话的模型既费钱也慢。
包工头把这件事拆成两半:
- 承包商(contractor):你在设置页里定义的人,名字只是个标签,真正决定"谁干活"的是
provider + 模型 + 思考等级。想按专长分工就多雇几个实例、各起各的名字:便宜的配便宜模型
跑搬砖活,贵的专门挑错,还有一个直接跟父会话同模型。每个承包商还能带一段自己的提示词
(设置页里点「编辑提示词」),派单时原样塞进它的工单里。
- 工单(order):父智能体拆出来的活。每张工单指定任务与验收标准,可以点名某个承包商,
也可以省略点名、由引擎按实时负载自动分配。
父智能体只做两件事:拆单、验收。中间的过程全部由承包商在各自独立的子会话里完成,
产物回收成一块共享看板。
装上它
把仓库放到任意目录,然后在 DSH 里:
dsh plugin add E:/path/to/dsh-agent-foreman
或者手动安装(dev 用法):
1. 把整个目录拷到 <profile>/node_modules/dsh-agent-foreman
2. 在 <profile>/package.json 的 dsh.profile.bundles 里加上 "dsh-agent-foreman"
3. 重启 DSH
装好后打开 设置 → 包工头,添加承包商。
用起来
1. 设置 → 包工头 → 添加承包商(名字、provider、模型、思考等级、并发分组编辑,按钮写提示词)
力工-前端 trae deepseek-v4.1-flash 默认 开 1
力工-渲染 workbuddy-global deepseek-v4.1-flash high 开 2
安全员 deepseek-official deepseek-flash 默认 关 1
分工靠名字:**包工头(父模型)拆单、力工干活、安全员挑错(可选)**。名册里只放你雇的人,
包工头就是驱动这一切的父智能体,不占名册。
**想要专长就多雇几个实例**(两个力工各用各的模型、各写各的提示词)。派单时 `contractor`
写名字就点某一个人,省略就**按实时负载挑人**:跳过正忙的、取最空闲的,负载打平才轮转。
负载跨会话可见,所以多个会话共用一个名册时不会都抢同一个人。
普通模式中每个实例的并发上限默认 1;团队模式中同一个原生成员始终串行,
不同成员可以并行,需要更多并行工人就增加名册实例。
**最简形态只有一个人:力工。** 所有工单都给它,靠它的并发上限和策略里的总并发控制节奏。
2. 在对话里直接说:"用包工头把这三件事分下去:……";或者用 `/foreman` 一句话派单(见下)
3. 父智能体调用 foreman_dispatch 派单 → 等全部落定 → 拿回看板 → 逐单打分
/foreman:一句话派单
插件在宿主里注册了一个运行时 skill(lib/skill.js,ctx.skills.register())。输入框里敲 /
能看到 foreman,选中或直接打 /foreman 加任务即可:
/foreman 把 GraphBlocked 抽成共享逻辑;给新逻辑补回归测试
分号或换行分段,一段一张工单。skill 正文规定四步:看名册 → 拆单(补齐背景/文件/验收)→
一次 foreman_dispatch → 逐单 foreman_review。这条路径不靠常驻系统提示词,只在用到时
注入一次,比每轮都挂着一段守则省。
父智能体手里的四个工具:
工具 · 作用
foreman_roster · 看名册:有哪些承包商、什么模型、提示词多少字、并发几张单、当前策略
foreman_dispatch · 派一轮工单,等全部落定,返回看板(含每单交付摘要)
foreman_review · 逐单 pass / fail;fail 且还有额度就带着反馈重派给同一个人
foreman_status · 回看某一轮看板;省略 runId 取本会话最近一轮
成员在哪看
设置 → 包工头 → 实时工地:一块轮询 api/live 的看板,显示包工头在不在跑、
每个承包商的岗位与模型、本轮每张工单的状态 / 依赖 / 错误 / 产物路径。页面切到后台
就自动停表,不占资源。
关键一点:看板同时显示声明模型和真实模型。声明的是名册里配的那套,真实的是
从子会话的 header 里读回来的实际路由。两者不一致时该行会标出来——这正好回答了
"它到底跑的是谁的模型"。团队模式以实际请求配置核验模型,而不只信原生名册的显示标签。
团队模式下承包商本身就是宿主的「智能体团队」成员,点会话头的 智能体团队 也能看到。
名册要点
- 承包商 = 名字 + 可选岗位(
role,只用于派单路由,不是固定角色体系)+ 提示词 + provider +
模型 + 思考等级 + 并发上限。provider 选「跟随当前会话」时,子智能体直接跑父会话当前的模型,
不需要知道它是什么。
- 想换模型就分两步:先选 provider,模型下拉只列这个 provider 自己的模型(由 provider 推出来,
没有模型的 provider 不会出现在下拉里)。
- 设置页把策略收进「派单策略」折叠区,名册按承包商分组编辑,完整显示配置路由;
模型、思考等级、并发和启用控件不再挤进一行。「编辑提示词」打开该承包商的提示词。
名册就是白名单
宿主自己有一份子智能体模型白名单(设置项 subagent-model-selection),它决定子智能体
被允许跑哪些 provider/模型。这份名单和名册是两处独立配置,一旦不一致就会出现"名册里写着
trae,实际却在跑别的模型"——而且没有任何报错。
本插件把这件事收成一处:**名册里所有启用且配了 provider+model 的承包商,会自动汇总进宿主
白名单**。你只需要维护名册。
- 插件启动时同步一次;设置页保存名册后再同步一次;也可
POST /api/whitelist/sync手动触发。 - 名册里没有任何显式路由(都用「跟随当前会话」)时不动宿主原配置——空名单会让宿主报错。
- 只影响新会话。宿主的白名单在会话首次建立时就被快照进该会话了,已经开着的会话改不了,
所以改完名册要开新会话才生效。
- 同步失败不会影响派单,只记日志;
/api/state的whitelist字段能看当前真实名单。
派单参数要点
orders[].task必须自足:子智能体看不到父会话的任何上下文,背景、要动的文件、
期望结果都要写进去。
orders[].contractor可写承包商名字或 id,也可写role岗位名;名字/id 匹配优先于岗位匹配。
不存在的名字、id 或岗位会直接报错,不会悄悄换人。
- 省略
contractor时按实时负载挑人,不是按名册顺序轮。规则:先只在还有空位的人里挑
(在跑张数 < 该人的 maxParallel),再取在跑张数最少的,负载打平才用轮转游标打破平局。
负载是跨会话的——别的会话正在让力工干活时,这个会话派单会自动换人,不会两个会话一起
压给名册第一个人。轮转游标落盘在 <数据目录>/rotate-cursors.json,重启 DSH 后继续,
不会回到第一个人。
所以:默认就该省略 contractor;只有"这单必须由某个特定的人做"时才写名字。
把每张单都写成 contractor: "力工" 会绕过负载分配,其余承包商闲置、活全串行排队——
只有名册里确实只有一个启用承包商时才这么写。
foreman_roster会显示每个人当前空闲/在跑几单,这是跨会话的真实状态,可据此决定要不要点名。orders[].dependsOn只能引用本轮内的工单。所有依赖都成功完成后,这张工单就会开工,
不需要等整张拓扑层跑完;无依赖关系的工单仍可并行,受总并发默认 4(上限 8)和单人并发上限约束。
- 某张工单失败、超时或被取消后,它的下游工单标记为 skipped;被跳过的依赖继续阻断更下游,
不会在缺少上游产物时硬跑。看板会保留阻断原因,便于验收和排查。
waitSeconds是这一轮的总墙钟上限,到点会中止没跑完的工单并把现状返回——不会让父智能体
拿到一份假的"全部完成"。
- 实时状态会显示依赖关系、错误和产物路径;它是状态视图,不另造一套实时 DAG 编辑界面。
验收与返工
foreman_review 打回时,反馈会原样进入下一次派单的提示词("上一轮被打回,原因:……")。
返工额度由策略里的 maxRework 控制(默认 1 次),额度用完后打回只会记录结论、不再重派,
这一轮转入 closed。
策略
设置页可调,也可以直接改数据文件里的 policy:
字段 · 默认 · 说明
concurrency · 4 · 同时在场的承包商数(1–8);单人的上限在名册里按人设
timeoutSeconds · 900 · 单张工单的墙钟上限
maxRework · 1 · 每张工单最多被返工几次
maxDepth · 1 · 子智能体还能不能再派子智能体
provider · spawn · 走哪个 subagents provider(spawn / fork / cursor)
数据放在哪
- Windows:
%LOCALAPPDATA%/dsh-agent-foreman/ - 其它平台:
<baseDir>/data/dsh-agent-foreman/
roster.json 保存名册(含岗位)与策略;运行快照保存在 runs/。重启后可以查询、验收已经落定的
看板快照,但中断的工作不会自动重新派发或续跑。这里的显式恢复是恢复可检查、可验收的状态,
不是偷偷挂一个后台执行引擎。完整交付正文在可用时另存于 artifacts/,看板通过产物路径关联。
名册坏了不会阻断启动:读不出来的名册会被当成空名册并记一条日志。
安全边界
- 所有 HTTP 接口只接受同源、且落在回环地址上的请求;跨站请求一律 403(有 CSRF 面)。
- 名册只保存
provider/model/ 思考等级等配置,不保存任何密钥。 - 承包商在独立子会话里跑,沙箱与权限沿用 DSH 当前生效的那一套。
开发
npm install --ignore-scripts npm test
默认测试用假宿主跑真实插件(test/harness.test.mjs),不需要启动 DSH。
设置 DSH_HOST_ASAR 可跑已安装宿主的只读契约测试,设置 DSH_BROWSER_EXE 可跑 Chrome
响应式名册与保存交互测试;两个都启用时本版 151 项测试全部通过。
团队模式(实验)
新配置默认开启;已保存的策略不被覆盖。在「设置 → 包工头 → 派单策略」启用
团队模式,然后给不同承包商分别选择 provider、模型和可选思考等级。
1. 正常调用 agentTeams.spawnTeammate,成员真实登记到原生「编队」。
2. 通过单次调用作用域的兼容适配,在原生保留 child id 的创建请求中加入各成员的
request.agentOptions。首轮、持久 descriptor、冷恢复均沿用该路由。
3. 等握手结束,核对实际请求配置中的 provider/model/显式思考等级,然后通过
agentTeams.sendMessage 投递工单;返工复用同一成员会话。
4. 优先收带 run/attempt/token 的 foreman_report;会话正文须等成员不再运行再回收。
兼容范围:已对当前安装的 DSH 0.2.1-rc.5 原生 TeamService/TeamRoster 代码
执行离线契约测试。宿主公开建队 API 尚未透传模型参数,所以这是受保护的内部兼容桥,
不是宿主已新增的公开参数。不会改写共享 startActivation、宿主 ASAR、父模型或全局默认。
宿主升级后若契约不匹配会明确失败,不能保证任意版本兼容。
- 名册不同成员拥有独立的原生队友;名字含稳定身份与路由指纹,中文名留在描述中。
- 团队模式同一成员的工单串行;不同成员可并行。需要
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:5,最后更新 2026-10-30