关于 herdr-agents
herdr-agents 是用于 Herdr 的多 Agent 编排技能,供在 Herdr 面板中运行的 Agent 拆解任务、分派角色并整合工作。它通过 CLI Agent、角色文件和报告文件管理实施与审查流程。
主要功能
- 01按角色分派 CLI Agent
- 02将任务简报分发给工作者
- 03等待并检查报告状态
- 04要求跨模型家族审查
- 05整合、验证并提交成果
适用场景
- 01并行实现一个项目的不同部分
- 02让独立角色研究外部 API
- 03在推送前审查代码变更
- 04协调实施、文档与安全审查
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ djalmajr/ skills --skill herdr-agents安装后在 Claude Code 中输入/herdr-agents确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
config.defaultsREADME.mdagents/openai.yamlreferences/agent-profiles.mdkinds.mdorchestration-contract.mdtroubleshooting.mdroles/designer.mddocumenter.mdimplementer.mdinspector.mdplanner.mdresearcher.mdreviewer.mdscouter.mdsecurity-reviewer.mdsub-orchestrator.mdtasker.mdui-reviewer.mdscripts/herdr-agentsherdr-agents.cmdherdr-agents.mjsscripts/lib/arrival.mjsscripts/lib/commands/clean.mjscollect.mjsdoctor.mjsenv.mjsexplain.mjsfeedback.mjsfriction.mjs详细介绍
/herdr-agents
将调用方 Agent 转变为编排器,并为其配备一组角色 Agent,让它们作为真正的 CLI Agent 在 Herdr 窗格中运行。编排器无需在任何地方配置:从 Herdr 窗格(HERDR_ENV=1)运行此技能的 Agent 就是编排器。其他每个角色都是 roles/ 下的一个文件,其 kind 指定由哪种 CLI Agent 扮演。角色是带有 frontmatter 的 Markdown 文件(类似 omp 的 .omp/agents/*.md);herdr CLI 负责传输。编排器负责拆解任务、撰写简报、等待、整合、验证和提交。工作 Agent 各自实现、研究或审查一个部分,并将结果写入文件。
不可妥协的要求(每一项都是实际发生过的错误)
- 报告文件就是完成信号。 使用
dispatch(等待)、wait或status。绝不要手动编写循环来调用herdr agent get。 - 工作 Agent 的报告缺失时,绝不要对其执行
release --close。 脚本会拒绝此操作;--force仅用于放弃某个工作 Agent。 - 每份简报都必须包含 Goal、Expected result(或 Acceptance criteria)、Forbidden、Report 和一条不提交的说明;角色可以编辑时还须包含 Owned files。
dispatch会对简报进行检查(brief_lint=warn|strict;只读角色无需Owned files部分),并告知每个工作 Agent:没有人会监看其终端(不得提问互动式问题),也绝不能杜撰名称、端点、标志、凭据、URL 或需求。简报中提到的凭据、URL 和种子数据必须先行验证(使用git grep和种子脚本),不得猜测。 - 推送前,审查者必须与实现者来自不同的模型系列。标记为
partial的审查项不算通过。 审查者无法验证该项(通常是因为没有网络,或无法访问相关来源)。应向审查者提供其缺少的信息,或自行验证该项,然后再提交、推送或发布;wait和dispatch会标记含有partial项的报告。 - 状态绝不能放在
.agents/或.codex/下(Codex 沙盒会拒绝访问)。 - 嵌套编排器不得使用沙盒中的 Codex:其沙盒会阻止访问 Herdr 套接字。请使用
claude(或关闭沙盒的 Codex)。 - 每次运行结束时都要读取
$S friction,并记录此技能导致的问题(参见“改进此技能”)。
前置条件
test "${HERDR_ENV:-}" = 1 && command -v herdr >/dev/null && { command -v node >/dev/null && [ "$(node -p 'process.versions.node' | cut -d. -f1)" -ge 20 ] || command -v bun >/dev/null; } && $S init
如果检查失败,请说明你不在 Herdr 环境中(或缺少 Node.js 20+ / Bun),然后停止。绝不要在 Herdr 环境之外控制 Herdr 会话。herdr 技能(herdr --skill)是 CLI 语法的权威来源;此技能在其基础上添加角色层,绝不取而代之。
首次运行
当项目文件尚未选择团队(没有 multi_role、role.<role>.kind 或 lane.<name>.kind),且状态根目录中没有成员名册记录时,$S init 和 $S doctor 会显示 first_run: true。init 也会在其 JSON 中设置 first_run。只有表头的成员名册文件仍属于首次运行。first_run: false 表示此项目已选择团队,或已有 Agent 正在运行。
当 first_run 为 true 时,在启动任何 Agent 之前,先告诉用户即将发生什么,并等待用户同意。使用用户的语言。可参照以下内容调整;不要在同一轮中打开面板。
葡萄牙语:
Vou abrir até 3 painéis ao lado deste (4 no total, contando este). Dois escrevem o código em paralelo (e pesquisam quando preciso) e um revisa. (Com 3 painéis no total, um escreve e um revisa; com 2, um escreve e eu reviso.) Eles não fazem commit nem push; isso fica comigo. Você pode acompanhar qualquer painel ou fechar o que não quiser. Cada assistente gasta a cota da própria conta. Posso abrir?
英语:
我将在当前面板旁打开最多 3 个面板(包括当前面板在内共 4 个)。 两个面板并行编写代码(并在需要时进行研究),另一个面板负责审查。 (总共 3 个面板时,一个负责编写,一个负责审查;总共 2 个面板时,一个负责编写,由我负责审查。) 它们不会执行 commit 或 push;这些由我来做。 你可以查看任何面板,也可以关闭不需要的面板。 每个助手都会消耗各自账户的配额。 我可以打开吗?
用户拒绝后,停止组建团队。用户同意后,如果项目仍未选择助手,则按照设置:引导配置中的步骤操作,写入选择,然后启动 Agent。若 first_run 为 false,则跳过这段说明。
描述工作进展
每个可见操作都用一行说明,使用用户的语言:不要输出 JSON 或退出代码,也不要使用 lane、kind 或 panes 这几个词。
- Abri o painel de implementação para escrever esta fatia.
- O painel de revisão está ocupado; espero ele terminar.
- A revisão da fatia 2 achou 3 problemas.
- 已打开实现面板来编写这一部分。
- 审查面板正忙;正在等待它完成。
- 第 2 部分的审查发现了 3 个问题。
结束时说明谁做了什么:哪个面板进行了研究、编写和审查,以及你整合了什么。
正在发生什么
当用户询问正在发生什么(“o que está acontecendo?”、“what's going on?”)时,运行 $S explain,并根据其文本用用户的语言作答。这是纯文本,而非 JSON:说明面板数量、每个面板正在做什么(工作中、空闲、等待报告或配额不足)、当前任务和助手,以及当前选择建议的内容。若没有任务正在运行,则说明团队情况以及如何启动。
名称:名单中的成员
先运行 $S init。它会运行 doctor(提供诊断信息:是否在 Herdr 内部、Herdr 客户端与服务端版本、是否存在与 herdr --skill 完全一致的官方 herdr 技能、PATH 中是否有 kinds、状态目录是否可写、配置是否合理),然后将调用方自己的 Agent 重命名为 orchestrator(配置项 orchestrator_name;若该名称已被占用,则使用 orchestrator-2),让 Herdr 侧边栏和 roster 显示由谁负责统筹,并打印上下文(窗格、标签页、工作区、布局、状态目录)。启动 Agent 前先处理 warn 行;如果官方技能已过时,你读到的 CLI 语法可能有误。spawn 会在需要时才执行重命名。如果 first_run 为 true,请在启动任何 Agent 前遵循首次运行。
启用泳道时(默认设置),工作 Agent 会以其泳道命名(build;如果该泳道已有一个工作 Agent,第二个则命名为 build-2;还有 review,以及 flex 模式下负责文档的 docs)。Herdr 中的 Agent 名称全局唯一:如果另一个工作区已使用某个名称,就会使用下一个可用的后缀;如果 --name 指定的名称已被占用,也会采用相同方式处理,并发出警告。传入 --name 可指定更有描述性的名称。lanes=off 会沿用旧名称:按角色命名(scouter、implementer……),然后是 implementer-2。嵌套的 orchestrator 使用 sub-orchestrator 角色,且不属于任何泳道,除非某个 lane.*.roles 列表包含该角色。
orchestrator 的窗格也会设置标题:如果窗格尚无标题,init 会将其设为 orchestrator: <project>;$S title "<objective>" 会将其设为 orchestrator: <objective>(objective 最多保留 60 个代码点)。请在 init 后立即设置标题,并在 objective 发生变化时再次设置,这样侧边栏就会显示本次会话负责的任务。
名称表示角色;窗格标题表示任务。每次 dispatch 都会将工作 Agent 的窗格标题设为 <role>: <task>。如果简报以 H1 标题(# Brief — <task>)开头,task 就是简报的首行;否则,task 就是简报的文件名。报告生成后,标题末尾会加上 ✓;不带 --close 的 release 会清除标题。因此,即使同一个工作 Agent 被复用于多个任务,用户也始终能看到每个工作 Agent 正在做什么。
角色
| 角色 | 默认类型 | 工作量 | 模式 | 用途 |
|---|---|---|---|---|
scouter | grok | high | 只读 | 梳理代码、查找路径,并整理精简发现供交接 |
researcher | grok | high | 只读 | 提供经来源验证的外部库/API 答案 |
planner | — | — | — | 协调者。spawn planner 会以状态码 12 退出,且不会打开窗格 |
designer | agy | high | 编辑 | 在项目设计系统(令牌、状态、无障碍)下进行 UI 工作 |
implementer | grok | xhigh | 编辑 | 为一个切片编写生产代码,并逐项提交报告 |
tasker | grok | low | 编辑 | 按照精确约定批量执行机械式编辑 |
reviewer | codex | high | 只读 | 推送前基于补丁发现正确性问题 |
security-reviewer | claude | high | 只读 | 提供有证据支持的漏洞发现 |
inspector | agy | high | 只读 | 在两种主题下截取屏幕截图、发现 UX 问题,不修复问题 |
ui-reviewer | agy | high | 只读 | 根据设计约定对仅涉及 UI 的变更进行轻量审查 |
documenter | codex | high | 编辑(仅文档) | 审查后记录已落地的内容;绝不编写代码 |
sub-orchestrator | claude | medium | 只读 | 从另一个窗格运行此技能;绝不使用 codex 沙盒(套接字受阻) |
不同工作该使用哪个助手。 Default kind 列表示全新安装在未配置任何内容时使用的类型,不是策略。团队由每个用户或每个项目自行选择,并写入配置(引导式设置会询问此项,并且只提供探测结果为可用的助手):选择哪个助手和模型构建版本、由谁审查,以及工作量级别。唯一不变的规则是:切片的审查者必须来自与其实现者不同的模型系列(运行 grok 模型的 cursor 属于 xai 系列,与 grok 相同)。对于工作者,系列检查会强制执行此规则;对于由协调者自己编写的代码,需手动选择审查者所属系列。**选择或更改团队之前,请阅读 references/agent-profiles.md:**了解每个助手在实际使用中承担不同角色时的优缺点,以及各角色的推荐选择。示例:
- 包含 e2e 的 UI 工作应交给能够打开端口的类型,而不是沙盒化的
codex; - 处理不可信输入的切片需要比小型模型更强的模型,或者需要一份列出待测试恶意变体的简报;
codex审查者以high工作量在 2 到 3 分钟内发现了真实的 P1 问题,而xhigh的成本是切片的 2 到 4 倍。
定义位于 roles/。解析顺序:项目 .agents/herdr-roles/<role>.md → 此技能的 roles/<role>.md。生成时的 --kind 会覆盖 frontmatter 默认值。类型映射到模型系列(见 references/kinds.md;对于 cursor,系列取决于解析后的模型 ID — grok-4.7-xhigh 属于 xai);同一切片的审查者必须来自与实现者不同的系列。除非传入 --allow-same-family,否则脚本会拒绝分派给与当前编辑 Agent 同系列的审查者。它无法查看协调者自己编写的代码:遇到这种情况时,需手动选择来自另一系列的审查者类型。角色说明还包含协调者不会在每份简报中重复的工作者规则:只要其他工作者可能共用同一工作树,implementer 就会在仓库外的项目临时副本中运行变更检查(只有在独自工作时才会在原位检查;且仅在文件的 sha256 仍然匹配时才恢复 — 文件已更改表示这是他人的编辑:不予恢复,并进行报告);implementer、tasker 和 designer 会在编写报告前停止自己启动的所有进程,依据保留的 PID 进行检查,且只按 PID 检查(绝不列出所有命令行,因为其中可能包含凭据;沙盒化的 codex 会阻止 ps);designer 会报告 UI 的验证方式(ui_verification)。reviewer 绝不编辑仓库,并且只会在临时副本中进行变更。
工作量、模型、审批
角色 frontmatter、配置和 spawn 标志共用三个参数。优先级从高到低依次为:标志 → lane.<name>.*(同一 lane 中的每个角色共用一种 kind 和一个模型,因为它们属于同一个会话)→ 配置 role.<role>.<knob> → 配置 effort.<kind>(仅 effort)→ 角色 frontmatter → 配置 model.<kind>.<position> → 配置 model.<kind> → CLI 自身的默认值。每一层的 kind 和模型会一起生效:如果某一层以下的 lane 或角色模型低于设置有效 kind 的层级,就会被丢弃(优先级链会继续检查下一个来源);如果设置了不带 --model 的 --kind,所有已配置的 lane/角色模型都会被丢弃——假定通过标志选定的 kind 使用 CLI 的默认模型。角色文件自身的 model 属于该角色文件的 kind:如果有效 kind 来自配置层或标志,该模型也会被丢弃。如果 lane 设置了模型但没有设置 kind,其中的每个角色都会保留自己的 kind,而 doctor 会针对该 lane 中每个角色的 kind 检查 lane 模型。随附默认值:effort.grok=xhigh、effort.cursor=xhigh(grok 4.7 接受 --reasoning-effort xhigh|high|medium|low),因为这些方案很少会耗尽预算。应将预算花在有余量的地方。项目可在 .agents/herdr-agents.conf 中覆盖这些值,无需复制角色文件。
模型会跟随最新版本。 模型值可以是精确 ID、CLI 别名(Claude:fable、opus、sonnet 已表示“最新版本”),或匹配 CLI 列出的 ID 的正则表达式(cursor-agent --list-models、agy models、grok models、Codex 模型缓存);a|b 会按顺序尝试备选项。正则表达式会在启动时解析为匹配的最新模型,因此 opus 始终表示最新的 Opus。对于 sub-orchestrator 角色,位置为 orchestrator;其他所有角色的位置均为 worker。随附默认值:
model.claude.orchestrator=fable model.claude.worker=opus
model.codex.orchestrator=astra model.codex.worker=sol|gpt-5
model.cursor.worker=grok|muse model.agy.worker=gemini|opus
model.grok.worker=grok
规划器不会获得 worker 模型:orchestrator 会在此会话中进行规划。spawn planner 会以状态码 12 退出。
通用 kind(pi、opencode)。 这些多模型 harness 在技能中不提供默认模型(默认值中没有 model.pi.* 或 model.opencode.*):请在用户或项目文件中自行设置 provider/id(model.<kind>.worker、role.<role>.model、lane 的模型,或 --model);如果均未设置,则 CLI 会使用自身的默认值。pi 会将 effort 映射为 --thinking(上限为 max);opencode TUI 不会映射 effort 标志(--variant 仅适用于 opencode run),启动时会发出警告而非失败。审批:opencode 的 full → --auto(不会映射 edits,并会发出警告);pi 则完全没有审批提示(edits 不执行任何操作,并会发出警告)。模型系列由模型决定:除非模型 ID 可识别,否则会跳过同系列审查者检查,因此请手动选择审查者的系列。配置和 provider 示例:
references/kinds.md。
顶层 orchestrator 不会由技能启动;请自行按相同意图启动它(claude --model fable、codex -m gpt-6-astra)。$S model <kind> <spec> [effort] 会显示某个值的解析结果;$S models <kind> 会按从新到旧的顺序列出 ID。对于 Codex,effort 上限取决于所选模型声明的推理等级,而不是 kind。
effort是一套标准化梯度:low < medium < high < xhigh < max, 并映射为各 CLI 自己的标志,且限制为对应类型支持的级别(kinds会打印上限:claude、pi 和 codex 为max;cursor 和 grok 为xhigh;agy、gemini 为high;opencode TUI 不映射 effort)。 对于 Codex,还会根据所选模型声明支持的级别进一步限制;如果~/.codex/models_cache.json未列出某个模型,则该模型保持为xhigh。 在agy上请求max会返回high,并显示警告。未指定任何 effort 时,使用 Agent 自己配置的默认值(例如~/.codex/config.toml中的 Codexmodel_reasoning_effort);此技能绝不会自行猜测默认值。model会传递给对应类型的模型标志。Cursor 没有 effort 标志:effort 是模型 ID 的后缀,因此--model gpt-5.3-codex --effort high会在cursor-agent --list-models列出该模型时变为gpt-5.3-codex-high,否则会使用原模型并显示警告。Cursor 模型 ID 必须严格匹配:如果某个规格无法解析为cursor-agent --list-models中的 ID,就会在创建窗格前失败,因为 CLI 会拒绝未知和不受支持的参数化 ID,而不是将其传递下去。严格性针对的是规格解析:追加 effort 后缀的步骤会重新查询列表;如果列表无法确认解析出的 ID,就会原样传递模型,并显示警告cursor model '<m>' not in --list-models; passing it through unchanged,而不会导致启动失败。请在 Cursor TUI 中确认实际生效的上下文窗口;模型的 原生运行环境可能会提供与 Cursor 不同的窗口。approvals决定工作进程无需人工介入即可执行的操作范围:ask(默认,使用 CLI 的常规提示)、edits(自动接受文件编辑)、full(不提示工具或 MCP 服务,但仍受 CLI 自身沙盒限制)。对于各类型,full分别映射为:claude--permission-mode bypassPermissions+enableAllProjectMcpServers; codex-s workspace-write -a never;grokbypassPermissions --always-approve;agy--dangerously-skip-permissions;cursor--trust --force --approve-mcps。有两个对话框不会被刻意绕过: hook 信任提示(Codex--dangerously-bypass-hook-trust)以及某些 CLI 首次访问时的工作区信任提示。如果你愿意承担风险,请在--后传入 CLI 自己的标志;否则spawn会以退出码 7 退出并显示界面,你需要手动回答一次。
无人值守运行(群组的常见使用方式)需要设置 --approvals full,或在项目角色覆盖配置中设置 approvals: full。角色默认使用 ask,确保全新安装时不会悄无声息地绕过提示。
将自动批准作为后备方案。 如果工作进程仍被阻塞(对应类型没有 full 映射、对话框不受 full 覆盖,或有意使用 ask),auto_approve=on 会让 dispatch/wait 发送 CLI 的默认“是”按键并继续等待,每次 dispatch 最多执行 max_auto_approvals 次。每次回答都会计入 dispatch JSON 中的 auto_approved,并记录在 <state>/wait/<agent>.approvals.log 下。此设置会批准工作进程提出的任何请求,因此应搭配沙盒类型或范围较窄的 approvals 使用。如果同一个对话框连续出现三次,就会保持阻塞状态 ——
auto_approve: the same dialog came back 3 times for '<agent>'; leaving it blocked(不同的对话框会重置计数)——而 blocked JSON 行会在 dialog 中包含对话框内容(最近 20 行非空可见文本)。关闭此设置时,系统会报告被阻塞的工作进程(blocked,退出码 7),由人工决定。
无论是否启用 auto_approve,都不会代替工作进程回答问题:当被阻塞的界面是决策提示(Codex 的回答表单、Claude Code 的选项选择器、OpenCode 的问题对话框)时,wait 会报告 question(退出码 7),并在 JSON 的 question 中包含界面文本。
检测完成状态(唯一可靠的信号是报告文件)
Herdr 报告的是生命周期 状态,而不是轮次;每种集成都可能在任务进行中短暂显示为 idle/done。因此,该技能将报告文件作为完成信号,并提供三种观察方式。切勿自行针对 herdr agent get 编写轮询循环。每个组合提示词(简报和修订)的报告约定都规定:只有工作进程可以写入该报告,并且要等整个简报完成后才写入——子 Agent 或后台任务绝不写入报告,因为编排器会将报告是否存在视为完成信号;约定还规定,报告中的每条命令输出都必须从实际运行结果中粘贴,绝不重新输入或重构。
$S dispatch impl brief.md # blocks until impl's report exists (default)
$S dispatch a brief-a.md --no-wait # fan out…
$S dispatch b brief-b.md --no-wait
$S wait a b # …then block until every report exists
$S wait a b --any # or until the first one lands
$S status a b # non-blocking: done | working | blocked | question | no-report-yet | gone | unavailable | quota | provider-error | capacity | not-received
在执行过程中修订简报。 若要更改工作进程的简报——无论它正忙还是已报告——请将修订内容写入文件,然后运行
$S dispatch <agent> amend.md --amend;切勿手动发送 herdr agent prompt。修订会生成一份新报告供 wait 监视,而窗格会保留当前任务。对于忙碌的工作进程,消息会在 CLI 将其送达时到达(多数情况下会排队)。
wait 会为每个 Agent 输出一行 JSON(done、blocked、question、
settled-no-report、gone、unavailable、quota、provider-error、
capacity、not-received、timeout),并且仅当所有报告都已存在时才以 0
退出(7 表示 blocked/question,6 表示 settled/gone,4 表示
unavailable,9 表示 timeout,11 表示 quota,14 表示
provider-error/capacity,15 表示 not-received)。如果一次
wait 中有多个 Agent 完成,退出码取其中最严重的状态:
4,然后是 11、14、15、7、6。参数顺序不会改变结果。timeout 行包含
elapsed_ms(本次 wait 自身的耗时)和 state(最后一次探测标签,working
或 pending),每个超时的 Agent 还会获得一行 friction,指出状态,并将本次
wait 使用的超时时间加倍:timeout waiting for '<agent>'; it may still be working (state: <state>). Run: herdr-agents wait <agent> --timeout <2×>(超时时间
不是数字时,不会给出建议)。每个组合提示词都会要求报告每项的状态为 [done]、
[partial] 或 [skipped]。当报告代码块以外的 N 行带有 [partial] 时,
done 行会增加 partial: N(仅当 N > 0 时,且位于 report 之后),wait
还会发出警告:report of '<agent>' marks N item(s) partial: a partial item is not a pass; read them before commit, push or release(报告不可读取时按 0 计,且该行
保持不变)。每份报告的警告每个 Agent 只发一次:标记会记录已警告的报告路径,
对同一报告再次执行 wait 时仍保留 partial 键,但不再警告;新报告路径则会
再次触发警告。四种审查角色(reviewer、security-reviewer、ui-reviewer、
inspector)会在报告首行写入精确格式
findings: N (P0 a, P1 b, P2 c, P3 d) | verdict: pass|fail,无论报告语言为何,
该行都使用英文(当仍有 P0 或 P1,或变更不应按现状提交时,使用 fail)。
当 done 报告包含此行时,JSON 行会增加 verdict、findings 和 severity
(紧跟在 report 之后、partial 之前);数字按解析结果保留——如果首行中
P0..P3 的总和与 findings 不一致,则会发出警告
report of '<agent>': findings <N> but P0..P3 add up to <sum>;如果审查角色的
done 报告没有此首行,则会发出警告
report of '<agent>' has no 'findings: N (P0 a, P1 b, P2 c, P3 d) | verdict: pass|fail' first line。审查角色还会告知 worker:在称测试、断言或命令有误之前,
如果任务说明允许,就先运行并引用输出;如果无法运行,则说明原因并降低置信度——
阅读代码并不能证明测试失败。dispatch JSON 也会包含相同的 partial: N,紧跟在
report_exists 之后(如果有 amend,则位于其后);审查字段(verdict、
findings、severity)紧跟在 report_exists 之后(如果有 amend,则位于其
后)。JSON 为单行,且 wait_status 位于首位,因此 dispatch … | tail -1
会返回完整 JSON。当 wait 最终采用的报告与 dispatch 自身的报告不同时——等待期间
发送的 amendment 重新指向了 last-report-<agent>——JSON 会在 report 之后增加
settled_report: <path>,并由 report_exists 指明该报告;如果 wait 使用的是
dispatch 自身的报告,则不包含此键。发送前,如果新任务说明涉及的文件仍由 roster
中的其他 Agent 编辑(其报告仍处于 pending),dispatch 也会发出警告:
brief <path> owns files that '<agent>' is still editing: <paths>(最多列出五个
路径;对于只读角色,则为 reviewing files that '<agent>' is still editing: <paths>)
——这只是提示,不会阻止操作。路径会按文件、目录和 glob 进行比较
(src/**/*.ts 会匹配 src/a/b.ts;roles/reviewer*.md 会匹配
roles/reviewer.md)。如果 codex worker 的启动参数未授予相应访问权限,其组合
提示词(任务说明和 amendment)会附带沙箱说明(danger-full-access 或
--dangerously-bypass-approvals-and-sandbox 会移除两条说明):Your sandbox cannot write under .git: do not run git mv, git checkout, git add or git commit. Describe renames and restores in the report; the orchestrator runs them.;并且——除非
某个参数以 network_access=true 结尾,例如 -c sandbox_workspace_write.network_access=true——还会附带
Your sandbox has no network, local ports included: tests that start a local server fail with "Operation not permitted". Mark them [partial] and say so; the orchestrator runs them. Still write the integration tests the brief asks for, even if you cannot run them here; do not replace them with unit tests of helpers, and add a test seam (an injectable value) when the code depends on something fixed, such as the build type.。
带有 danger-full-access 的参数不会附带任何说明。当同一工作树(相同 roster
cwd)中有其他处于活动状态且承担编辑角色的 roster Agent 时,组合提示词(任务说明
或 amendment)会增加 Another worker edits this same tree now: run the global checks the brief asks for, but report failures in files you do not own as outside your slice (name the files), not as [partial] items of yours.(如果 Herdr 无法列出这些 Agent,
则跳过该行;这只是提示)。
provider-error 表示 worker 处于空闲状态,且其最后一行错误显示模型提供方已中断
(例如 Request timed out、Connection error、Retry failed after N attempts、
503: {…});JSON 中的 cause 就是该行。capacity 表示提供方因容量已满而拒绝
请求(例如错误类型名称中包含 capacity 或 overload,或状态码为 529)。精确模式
统一定义在 scripts/lib/provider.mjs 中。遇到 capacity 时,wait 会先向 worker
发送 "continue",最多发送 provider_retries 次,每次间隔
provider_retry_delay 秒(每次都会记录在 friction 中);只有这些尝试无效时才会
报告 capacity。这两种状态都需要连续两次探测结果相同才会计入,因此短暂的屏幕
状态不会结束 wait。worker 处于 working 状态时,如果屏幕上的计数器在
stuck_warn_minutes(20 分钟)内始终不变,就会收到一行 friction
("may be stuck in one tool call");wait 会继续执行。缺失、为空或非数字的屏幕
年龄标记会从现在开始计时(在原处重写),绝不会从 Unix 纪元开始计时。
dispatch 还会检查提示词是否已送达:在
prompt_check_seconds(15)内,Agent 必须开始工作或阻塞,或者报告必须出现。如果提示词文本仍在 Agent 的输入框中,它会发送一次 Enter(JSON enter_sent);如果屏幕没有变化,则会重新发送一次提示词(resent);如果仍然无效,则返回 not-received(退出码 15)——发送其他内容前请先读取窗格。not-received 的 dispatch 会记录发生时间和 Agent 的 state_change_seq;之后的 wait 会在提示词仍显示在 Agent 输入框中时,每隔一个 prompt_check_seconds 时间窗口重试一次 Enter,最多重试 3 次:如果 Agent 开始工作,或者其状态在标记之后已发生变化(state_change_seq 不同),则会清除标记,并照常继续等待;重试 3 次后,或者提示词已不在输入框中且 Agent 尚未开始工作时,等待会以 not-received 结束(退出码 15)。status 也会以相同方式报告 not-received,但为只读操作(退出码 15,不发送按键);如果序号已变化,也会清除该报告。gone 仅表示 agent_not_found。unavailable 表示 herdr agent get 遇到权限或传输故障(原因会显示在 stderr 和 JSON error 中):请重试或恢复访问权限;查询不可用时,请勿启动替代项,也不要在未指定 --force 的情况下执行 release 或 release --close。如果 herdr agent get 被信号终止(退出码 ≥ 128,例如负载过高时的 137),且没有结构化错误,则视为暂时性故障:等待 1 秒后再试一次,然后等待 2 秒后再试一次,再计入故障;如果仍然发生,原因将是
herdr agent get was killed (exit <rc>, <signal>: memory pressure or an external kill)。报告在两次轮询之间大小不再变化时,即视为已完成。配置中的 notify=on 会为每个已完成的工作进程显示一条 Herdr Toast 通知。roster 会显示 REPORT 列(none | pending | ready),方便快速查看。
配置
纯 key=value 文件,按以下顺序读取;每一层只覆盖自己设置的键:
- 技能中的
config.defaults(文档所述的默认值) ~/.config/herdr-agents/config——用户级<repo>/.agents/herdr-agents.conf——项目级<state>/session.conf——会话层:每个 Herdr 工作区各自一份,位于 Git 忽略的状态目录中,永不纳入版本控制HERDR_AGENTS_<KEY>环境变量- 命令行标志
会话层。 session set <key> <value> 会写入工作区的 <state>/session.conf:它会覆盖项目级和用户级文件,但标志和 HERDR_AGENTS_* 仍具有更高优先级——适合设置“仅本会话生效”的选项(例如,仅本周让每个工作通道都使用个人提供商:
session set lane.build.kind pi + session set lane.build.model my-provider/my-model)。session show 会打印各项配置;session clear [key] 会删除某个键或整个文件。config 会以来源 session 打印会话值。在 Herdr 之外(无法解析工作区时),此层不存在。
$S config 会打印每个生效值及其来源:先按顺序打印标量键,然后打印点分隔键(args.*、role.*、model.*、effort.*、lane.*,按字母顺序排序)——某一层持有该键时,使用文件中的原始拼写;仅存在于环境中的键则使用重建后的点分隔名称。
键:
orchestrator_name、layout(split:在调用方的标签页中使用窗格,直到标签页已满,然后使用 herd 标签页;tab:仅使用 herd 标签页)、max_workers(同时运行的活动工作者数量,不计协调器;默认值为各通道容量之和,四个窗格时为 3;达到上限时 spawn 以状态码 8 退出;0 = 无上限)、split_max_panes(每个标签页的窗格数,包含调用方;默认值为 panes)、split_min_pane(生成工作者后可保留的最小窗格大小,占标签页的比例;默认值为 0.18)、regrid(每次生成/释放后都采用精确网格)、herd_label + herd_label_max(自动 herd 标签页标签的模板和长度;默认 {roles} → impl+rev,16 个字符;参见“Herd tab labels”)、brief_lint(warn|strict|off;只读角色无需 Owned files 部分)、brief_lint_aliases(简报部分标题的备用写法,Section=Heading|Heading 项;以 1–3 级标题开头的标题前缀即可满足该部分要求——参见“Briefs are contracts”)、reuse_workers
(默认值为 on,即使未在任何配置中设置也是如此:spawn 会返回一个同角色、类型和当前工作目录的空闲工作者,前提是它存在上一份报告,而不会打开窗格;复用永远不计入 max_workers;--reuse/--fresh 可覆盖单次调用的设置;复用的工作者会在上下文中保留之前的简报,因此若某个任务片段必须从干净状态开始,请传入 --fresh)、multi_role(默认值为 on;一个空闲 Agent 可以承担另一角色——参见“Setup: guided configuration”)、feedback +
feedback_repo(参见“Improving this skill”)、approvals(未单独设置的角色的默认值)、auto_approve + max_auto_approvals(使用 CLI 的默认“Yes”回答工作者的审批对话框并继续等待;默认关闭,见下文)、max_effort
(全局上限)、family_check(strict|warn|off)、settled_grace、
spawn_timeout、dispatch_timeout、state_dir、report_language、
notify、args.<kind>(始终追加原生标志;可在此处设置你接受的钩子信任或工作区信任绕过选项)、role.<role>.kind
(无需复制角色文件即可替换角色类型)、role.<role>.args
(角色的原生参数,lanes=off 时适用;启用通道时,每个角色都在某个通道中运行,通道会话由其中的所有角色共享,且只有 lane.<name>.args 会生效;两种设置都仅适用于为该角色或通道配置的类型)、panes(2|3|4,
默认值为 4)、lanes(on|off)、pane_mode(strict|flex,默认值为
strict)、flex_extra(flex 可额外添加的临时工作者数量,默认值为 1)、flex_roles(可使用这些临时工作者的角色,默认值为 reviewer,documenter),以及 lane.<name>.roles|kind|model|effort|approvals|panes|args(panes = 通道容量;args = 该通道中所有工作者的原生参数)。作用域参数会追加在 args.<kind> 之后、-- 后的原生参数之前。若配置文件中的作用域键无法由当前通道模式应用,doctor 会发出警告。工作者会保留启动时使用的原生参数(名册第 14 列),因此更改这些键后,使用其他参数启动的空闲工作者不会被复用:lanes=off 会启动一个新工作者;通道则会返回 kind-mismatch(状态码 13),直到你释放该工作者。
命令
所有操作都通过 scripts/herdr-agents 执行(需要 herdr 和 Node.js
20+ 或 Bun——不需要 bash、不需要 jq):
S=<path-to-this-skill>/scripts/herdr-agents # POSIX; Windows: <path-to-this-skill>\scripts\herdr-agents.cmd
$S init # doctor + name yourself `orchestrator`, title an untitled pane, print context (`first_run`)
$S title "<objective>" # this pane's title: `orchestrator: <objective>`
$S title --clear # clear this pane's title
$S doctor [--fix --panes 2|3|4] [--user|--session] # advisory check (`first_run: true|false`); --fix normalizes the project, user or session file
$S explain # plain text: what is running, or how to start
$S setup [--target FILE] [--no-hooks] # AGENTS.md block + Claude hooks (idempotent)
$S setup --detect # JSON: installed kinds, summaries, models (incl. custom providers), recommended reviewer; writes nothing
$S setup --probe [--kind K --model M] # JSON: ready|no-auth|quota|error per kind/model + own pi/opencode models (≤5 per kind; rest in skipped_custom); no panes
$S setup --plan … # diff -u per file (config files: key before → after) of what setup/--set/--user-set/--session-set would write; writes nothing
$S session set <key> <value> # this-session override in <state>/session.conf (above project, below flags/env); also <key>=<value>
$S session show | session clear [key]
$S roles # roles with the kind, model and effort in effect and where each comes from
$S role reviewer # resolved file + frontmatter
$S spawn implementer [--name impl] [--kind codex] [--direction right|down]
$S dispatch impl <brief.md> [--timeout 900000] [--amend] # role prompt + brief → agent, waits; --amend amends the agent's current brief
$S collect impl [--lines N] [--verify] # prints the report file (or recent output); an agent still working or blocked with no report gets a short stderr line and exit 4 (no terminal dump) unless --lines is passed; --verify re-checks the report's sha256 lines (exit 16 on changed/missing, 4 when the report cannot be read)
$S run scouter <brief.md> # spawn + dispatch + collect in one call
$S wait a b [--any] [--timeout MS] # block on report files
$S stats [--since <date>] [--json] # tasks, times and review findings per role, from the state dir; <date> is YYYY-MM-DD or ISO 8601 (other formats exit 2); the review table covers reviewer, security-reviewer, ui-reviewer and inspector
$S friction # errors/warnings of this workspace (review at end)
$S friction add "<text>" [--brief <path>] # record one friction note (level note, command friction; --brief appends ` (brief: <path>)`)
$S feedback send <report.md> "<summary>" # feedback=local: save the report in feedback_dir as from-<project>-<date>.md (never overwrites) and send one line to feedback_to
$S regrid # exact grids: caller's tab (split) + every herd tab
$S tab-label # herd tabs: id, label, auto|manual
$S tab-label "onda 2" [--tab ID] # pin a label (newest herd tab, or --tab); --auto goes back
$S spawn reviewer --tab-label "onda 2" # place the worker in the herd tab of that name (created if needed)
$S layout-plan # where the next spawn lands (anchor, direction, overflow reason)
$S status a b # non-blocking completion check; no names exits 2 and points to `roster`
$S config # effective configuration and sources (incl. the session layer)
$S config set <key> <value> [--project|--user] # write one key (default: the project file); also <key>=<value>
$S roster # live agents with role/kind/pane/state/report and the current task (TASK, from the pane title; '-' when none, cut to 40 characters)
$S release impl [--close] # forget the agent; --close closes a pane we created
$S clean [--older-than 7] # drop gone agents, delete old briefs/reports
$S kinds # kind → executable, family, effort ceiling
$S spawn implementer --effort xhigh --approvals full # normalized effort + no prompts
$S spawn scouter --kind cursor --model gpt-5.3-codex --effort high --approvals full
$S spawn implementer -- -s workspace-write -a never # native agent args after --
scripts/herdr-agents 是一个 POSIX sh 启动器:它会使用 node(20+)运行
scripts/herdr-agents.mjs,如果 Node.js 20+
不可用(缺失或版本较旧),则使用 bun,并传入相同的参数。如果两种
运行时都无法使用,它会输出 herdr-agents: needs Node.js 20+ or Bun 并
以状态码 2 退出。
scripts/herdr-agents.cmd 是适用于 Windows 的同一启动器。setup
SessionStart 钩子会按以下顺序检查这些位置:项目的
.agents/skills、项目的 .claude/skills、$HOME/.agents/skills,然后是
$HOME/.claude/skills。它会调用找到的第一个启动器,执行
sh "<skill-root>/scripts/herdr-agents" doctor。
命名。 启用 lanes 时,Agent 的名称取自 lane(build、
build-2、review、docs)。如果 Herder 中已有同名的运行中 Agent,则会
使用下一个可用的后缀(如果名称来自 --name,则会发出警告)。lanes=off 时,名称取自角色
(implementer,然后是 implementer-2)。传入 --name 可设置自定义名称
([a-z][a-z0-9_-]{0,31})。在 dispatch、collect 和
release 中使用该名称;不要使用 pane ID。
审查者家族检查。 dispatch 遇到 reviewer 或 security-reviewer 时,会将其模型家族与此技能启动的所有编辑 Agent 进行比较。
编辑 Agent 包括 implementer、designer、tasker、任何 frontmatter 中
mode 为 edit 的角色,或 roles 历史记录包含上述角色之一的工作 Agent——即使某个工作 Agent 曾编辑过,之后又被重复用作 scouter,仍会被计入。同一家族 → 除非指定 --allow-same-family,否则以状态码 5 退出。
此检查无法识别编排器自身编写的代码;因此请手动选择审查者类型。
spawn 在 layout=split 下会让工作者留在调用者的标签页中,不会把窗格挤得过于密集:选择面积最大的候选窗格(调用者 + 此技能在该标签页中的工作者),沿较长的一侧将其一分为二(--ratio 0.5;宽度比例 ≥ 高度比例 → right,否则为 down),然后 regrid 将标签页重建为覆盖调用者 + 工作者的精确网格——调用者留在最不拥挤列的左上角(3 个单元格:调用者占满整列高度,两个工作者上下堆叠;4 个单元格:2×2)。当标签页中已有 split_max_panes 个窗格(默认值 4 = 调用者 + 3 个工作者),或没有窗格可以在不低于 split_min_pane(默认值为标签页的 0.18)情况下继续一分为二时,工作者会溢出到一个 herd 标签页——优先选择第一个有空间的标签页,否则新建一个;标签页名称根据其中的角色(impl+rev)或你指定的工作波次生成(spawn 会打印 placement: split|herd;layout-plan 会显示决策及原因)。release --close 会释放名额,因此下一次 spawn 会再次在调用者的标签页中创建工作者。layout=tab 只使用 herd 标签页。每个 herd 标签页也会重建为精确网格(列数 = ⌈√n⌉,行数均衡),并保留其标签名称。regrid 也会执行反向操作:当调用者的标签页重新有空间时(工作者已释放、上限已提高),会先从第一个 herd 标签页的第一个窗格开始,把溢出的工作者移回,直到调用者 + 工作者达到 split_max_panes;清空的 herd 标签页会自行关闭。调用者标签页重排期间,工作者会经过一个临时的 herd-park 标签页,因为 Herdr 不允许在同一标签页内移动窗格;Agent 会继续运行。工作者总数有限制:同时运行的工作者最多为 max_workers(默认 3,与协调器合计为四个窗格),协调器不计入上限——上限按名称和窗格统计运行中的 Agent:只有当某个清单行对应的窗格中存在同名运行中 Agent 时才计入(没有已知窗格的行则按名称统计,且只计一次);过时的行——即该名称的 Agent 在另一个窗格中运行——不计入。超出上限时,spawn 会以代码 8 退出并列出运行中的工作者:对已收集报告的工作者执行 release --close,或让 reuse_workers 分配空闲工作者(multi_role=on 时可能分配其他角色;参见“Setup: guided configuration”)。将工作安排为每波最多三个切片,而不是扩展到更多并行工作者。spawn 会重试几秒,等待新 shell 出现提示符,然后使用 --no-focus 启动 Agent。启动后,spawn 会监视 5 秒:如果某个 CLI 在启动时自我更新后退出(目前观察到的只有 Codex 自动更新),就会在同一窗格中使用相同参数重新启动一次('<name>' (<kind>) updated itself at start and exited; started it again);如果 Agent 在启动后立即退出但没有该标记,或在重新启动后退出,spawn 会以代码 4 退出,并显示最后几行屏幕内容(最多 5 行,以 / 连接);窗格会保持打开以供检查,且不会写入清单行。只有在没有运行中的 Agent 使用该名称时,名称才可用,因此,遗留名称的清单行(或 spawn 重用的窗格)都属于已退出的 Agent:spawn 会移除它(replaced the stale roster line of '<name>' (pane <pane>)),而 roster/status 会将名称在另一个窗格中处于运行状态的行显示为 gone,而不是显示另一个 Agent 的状态。herdr agent start 仍会切换焦点到新窗格;spawn 只会在焦点仍位于该窗格时将焦点切回原先所在的窗格,并会保留你已切换到的窗格。regrid 不会切换到调用者所在的标签页。显式指定 --direction/--ratio 时,会按要求拆分选定的窗格(如果标签页已满,则拆分调用者的窗格),并跳过本次调用的自动重排。
-- 后的所有内容都会传给 Agent CLI(herdr agent start … -- <args>)。
Herd 标签页标签。 Herd 标签页根据其中运行的内容命名,而不是命名为 herd-2。自动标签来自 herd_label(默认值 {roles}:标签页中不同角色的名称,按加入顺序排列并缩写为 impl、rev、insp、des、scout、res、task、sec、sub、plan;项目角色保留其文件名——例如 impl+rev;重复标签会变为 impl+rev 2;还支持 {n} 工作者数量、{i} 标签页位置(从 2 开始)、{orch}),并截断至 herd_label_max(16)个字符;每次 spawn/release/regrid 后都会重新计算。工作有名称时,请根据切片或波次命名标签页,而非根据角色命名:spawn <role> --tab-label "onda 2" 会将工作者放入该标签页(如果标签页不存在则创建,不论调用者标签页是否有空间;已满时会溢出到 onda 2 ·2),而 $S tab-label "paridade" 会固定最新 herd 标签页的标签(要指定其他标签页,请使用 --tab ID)。标签不超过 16 个字符——侧边栏会截断其余部分。固定标签以及在 Herdr 中手动重命名的标签页属于 manual,不会被覆盖(tab-label --auto 会让标签页恢复自动命名);roster 会显示每个工作者所在的 TAB。
dispatch 会将组合提示词(角色正文 + 简报 + 报告约定)写入状态目录,并发送一行指向该文件的内容,因此较长的简报不受终端粘贴长度限制影响。退出代码:2 用法/环境错误,3 未知角色/Agent,4 Herdr 故障(unavailable),5 同一系列的审查者,6 已结束但没有报告,7 Agent 被阻塞(启动或审批),8 已达到 max_workers,9 等待超时,10 工作通道忙,11 配额耗尽,12 spawn planner(协调器负责规划),13 工作通道 kind-mismatch(运行中的会话使用了其他 CLI:释放该工作通道,并设置 lane.<name>.kind 以防再次发生),14 提供方错误或容量不足,15 未收到提示词(dispatch 和 wait),16 collect --verify:报告的文件已更改或缺失(文件存在但无法读取的报告会以代码 4 退出)。
代码 7 也适用于提出了 question 的工作者。多 Agent wait 会采用 4、11、14、15、7 和 6 中最严重的退出代码。每条错误和警告也会追加到 <state>/friction.log($S friction)。
What is implicit (read once)
- 角色是第一条消息,而不是系统提示词。 worker 仍遵循自己的运行框架:项目的
CLAUDE.md/AGENTS.md、钩子、技能、MCP 服务和记忆。当角色与仓库说明冲突时,由 worker 的运行框架决定,而不是此技能。使用worker_context=full时,预计 worker 会花第一分钟阅读项目规则和记忆。worker_context=lean会减少这部分:组合后的提示词禁止读取说明文件,除非任务简述点名要求读取;Codex 会获得project_doc_max_bytes=0,Claude 不会获得技能目录。只有当任务简述引用了所有适用规则时,Lean 才有效;而任务简述模板本来也要求这样做。 - 权限由 worker 决定。 CLI 使用默认批准模式时,会在遇到第一个审批时停止,等待操作会返回
blocked。无人值守运行时使用--approvals full(或edits);映射未涵盖的任何内容都需放在--之后。未经用户同意,绝不要处理blocked对话框。 - 启动对话框。 更新提示、登录和信任对话框会使
agent start返回agent_not_ready;spawn仍会记录该 Agent、打印屏幕内容并以状态码 7 退出。询问用户,然后使用herdr agent send-keys <name> …作答,再运行herdr agent wait <name>。 - 一个 Agent,一个持续增长的会话。 对同一名称多次调用
dispatch会进入同一段对话;worker 会记住先前的任务简述。collect只打印最新报告;较早的报告仍保存在reports/中。如果不同切片之间不得泄露上下文,请启动一个新的 Agent。 dispatch只识别此技能启动的 Agent。 在 Herdr 中手动启动的 Agent 不在名单中;请直接使用herdr agent prompt。- 状态按仓库和 Herdr 工作区分别维护。 其他工作区中的编排器看不到这些 Agent;同一工作区中的两个编排器共享名单。不会自动删除任何内容;请运行
clean。 - 等待跟踪的是状态,而不是轮次。 worker 仍在执行任务时,Herdr 可能报告
idle/done(Codex 在进行 MCP 调用时会出现这种情况)。因此,dispatch和wait会等待报告文件,直到 Agent 不再处于working状态 并且 屏幕在settled_grace秒(45)内没有变化,或者超时耗尽。timeout的意思是“再次运行wait”,而不是“丢失”。 approvals: ask不保证会出现提示。 它表示使用 CLI 自己的默认设置;defaultMode: auto的 Claude Code 永远不会阻塞。要强制手动审批,请在--之后传入原生标志。- 超时。
spawn会等待 60 s 以确认就绪(--timeout)。dispatch和未指定--timeout的wait都会采用角色的有效超时时长:角色文件 frontmatter 中的timeout(ms),否则采用dispatch_timeout(15 min),再按角色的有效 effort 缩放(xhigh× 1.5,max× 2,其他情况 × 1);等待多个 Agent 时,wait会采用这些角色中最大的超时时长。显式指定的--timeout始终优先。无论wait_status显示什么,报告文件都是判断依据。 - Claude Code 编排器的 Bash 会将每次调用限制为 10 分钟,这比长时间审查的时长更短:请在后台运行
wait(或会等待的dispatch),并由运行框架自己的通知唤醒你——不要在它前面加上timeout。wait --any会在每份报告到达时唤醒你:只要有一份报告到达,它就会立即以状态码 0 退出(并打印该报告的 JSON 行),因此请再次运行它来等待剩余 Agent;等待操作自身的超时(见上文的角色有效超时时长)仍然适用。 - Codex worker 的沙盒比它认为的范围更窄。 Codex worker(
-s workspace-write)无法在.git下写入(git mv和git checkout -- <file>会因.git/index.lock而失败),也无法访问网络,包括本地端口。组合后的提示词会说明这一点(见“检测完成情况”中的沙盒备注):worker 会在报告中描述重命名和还原操作,由编排器执行这些操作;网络测试会标记为[partial],并由编排器运行。需要网络的角色或工作泳道:使用args.codex=-c sandbox_workspace_write.network_access=true(每个 Codex worker 都如此),或者在该角色或工作泳道配置为 kind codex 时,使用role.<role>.args/lane.<name>.args并设置相同的标志。这些都是同一个 CLI 的标志:只有当启动操作运行的 kind 是该角色或工作泳道配置解析出的 kind 时,它们才会传递给 worker(传给其他 kind 的--kind标志会丢弃它们,并发出警告),因为 Codex 的-c <key>=<value>对 Claude 来说是--continue,会在同一 cwd 中恢复编排器的对话;对 Cursor 来说则是--cloud。此外,无论来源如何,只要spawn收到传给 Claude 或 Cursor 的恢复标志(-c、--continue、-r、--resume、--cloud),就会在打开窗格前拒绝执行。Herdr 控制套接字也会以相同方式被阻止,因此嵌套编排器不能是受沙盒限制的 Codex。 - 不带
--close的release会让 Agent 继续运行。--close会通过关闭窗格来结束它。通过--pane传入的窗格绝不会关闭。run不会释放 Agent。 - 工作树由你负责创建。 使用
git worktree add .worktrees/<slug>(或herdr worktree create),并通过--cwd传入路径。名单保留在主仓库中;cwd 不在仓库根目录下的 worker,其任务简述和报告会经由$TMPDIR/herdr-agents/<ws>/reports/路由;所有已知沙盒都可以写入此目录。你需要自行将其 diff 合并回来(使用git -C <worktree> diff | git apply,或 cherry-pick)。对于同一 cwd 中其他仍在运行的 edit-role Agent,spawn(新 worker 和复用 worker)都会发出警告:'<a>' and '<b>' both edit <cwd>: builds and test runs see each other's changes in progress; give each a git worktree (spawn --cwd <worktree>) to isolate them——解决办法是每个 worker(或每个分支)使用一个工作树。路由过程中保存在$TMPDIR/herdr-agents/<ws>/reports/下的done报告会尽力镜像回状态目录:同名报告写入reports/,组合后的提示词(去掉.brief)写入其旁边的briefs/;复制失败时会发出警告,但done状态仍然有效,而且last-report-<agent>和wait的 JSON 行仍指向原始报告。 - 不同 kind 的检测质量各异。
claude和codex有 Herdr 集成;grok和agy通过屏幕检测,因此其idle/done状态可靠性较低,且常出现unknown。 - 语言。 你告诉用户的一切都应使用用户的语言:首次运行说明、设置问题、过程说明和最终摘要。任务简述也使用用户的语言。标识符保持英文(角色名称、窗格名称、文件路径)。worker 使用任务简述所用的语言进行报告。
$S explain会输出英文纯文本;回答时请翻译。 - 不支持远程计算机。 不支持
--machine目标;ID 和名单仅限本地此服务。 - 任务简述会逐字复制到磁盘上的组合提示词中。请勿在其中放入密钥和客户数据。
- worker 有自己的命令防护机制。 此类设置中的 Codex 守卫会拒绝
rm -f风格的命令,不受审批设置影响。任务简述应描述预期结果,而不是破坏性的 Shell 命令写法。 - 布局。 同时运行的 worker 最多为
max_workers(3)个,因此调用者的标签页通常会容纳 2×2 网格(split_max_panes4)。仍然无法容纳的 worker(超出split_min_pane,或超过提高后的上限)会转到以角色名称(impl+rev)或你通过--tab-label指定的工作波次名称命名的 herd 标签页;设置layout=tab可让调用者的标签页保持不变。 状态(简报、报告、人员名单)存放在项目内部的<repo>/.herdr-agents/<workspace-id>/下,脚本会将该路径添加到.gitignore。沙盒工作进程可以在此写入:Codexworkspace-write允许访问仓库根目录、/tmp和$TMPDIR,但禁止访问自身的配置根目录 (.agents/、.codex/),因此状态不会存放在.agents/下。 只有在每个工作进程都能写入该目录时,才使用HERDR_AGENTS_DIR覆盖根目录。 根据约定,报告以文件形式保存,因此收集报告不依赖于抓取备用屏幕 TUI。
并行流程
最多保留 panes 个窗格,其中包括当前会话(以及下文灵活模式中的临时窗格)。
编排器负责规划,不会启动工作进程。其他窗格是工作通道:会话按顺序承担
其所属组中的任意角色。一个工作通道可以容纳多个工作进程(即其容量)。
reuse_workers 保持启用。每次 spawn 前,都会查询人员名单:
- 如果工作通道中有空闲或已完成的工作进程,且其报告已存在(或从未收到简报)
→ 复用该工作进程并切换角色(第 4 列加上角色历史记录)。如果
lane.<name>.kind为空,且此角色的 kind、model 或 effort 与当前会话不同,spawn会输出{"status":"kind-mismatch","lane":…,"name":…,"session_kind":…,"requested_kind":…}(以及 model 和 effort),并以状态码 13 退出。如果设置了lane.<name>.kind,那么该通道中的每个角色都会使用此 kind 对应的 CLI: 当前运行于该 kind 的会话会被复用;如果会话仍在运行另一个 CLI(在该键 创建前启动),也会以状态码 13 退出,因为该键不会重定向正在运行的进程。 无论哪种情况:运行release <name> --close,如果lane.<name>.kind尚未设置,则设置它,然后再次运行 spawn; - 没有空闲工作进程,且运行中的工作进程数量少于通道容量 → 打开一个新的
工作进程(
build,然后build-2); - 通道已满(每个工作进程的状态都是
working、blocked,或有待处理的报告) →spawn会输出{"status":"busy","lane":…,"name":…}并以状态码 10 退出, 同时列出所有工作进程。运行wait <name>,然后再分派任务。不要打开另一个窗格 ——灵活模式中的临时窗格除外; - 工作进程状态为
gone→ 删除其人员名单条目,且不计入数量; - 无法查询该通道中的工作进程(
unavailable),且没有空闲工作进程 → 在打开任何新窗格前以状态码 4 退出:该工作进程可能仍在运行;恢复访问后重试, 绝不要为其启动替代进程; - 已满通道中的每个运行中工作进程都修改过内容,且当前角色是审查角色
(
locked)→ 以状态码 5 退出:会话绝不审查自己编写的代码;请使用审查通道, 或释放其中一个工作进程。
预设(未设置 lane.*.roles;运行时根据 panes 和
pane_mode 解析,绝不会写入配置):
| panes | 通道(容量) | 编排器 |
|---|---|---|
| 4(默认) | build(2):实现者、设计者、任务规划者、侦察者、研究者 · review(1):审查者、安全审查者、UI 审查者、检查员 | 负责编排、规划和探索 |
| 3 | build(1)· review(1) | 同上 |
| 2 | build(1) | 也负责审查,使用与 build 通道不同的模型系列(手动选择) |
研究属于 build 工作:空闲的构建者可以梳理代码或阅读另一个仓库,也可以由编排器完成。
除非用户、项目或环境另行设置,max_workers 默认为容量总和(3、2、1),
split_max_panes 默认为 panes。lane.<name>.panes 可更改某个通道的容量。
Strict 或 flex(pane_mode,默认值为 strict)。Strict 不会打开临时工作面板:每个泳道都不会超出其容量(你设置的 lane.<name>.panes 会提高容量;max_workers 只是全局上限,不会为某个泳道打开名额),文档编写也属于构建工作(documenter 角色位于构建泳道)。Flex 最多可在 panes 之上额外打开 flex_extra(1)个临时工作面板,但仅限 flex_roles(reviewer,documenter)中的角色:第二个 reviewer(每个 builder 对应一个;或者让 reviewer 和 security-reviewer 并行处理同一个切片——两者都来自与 builders 不同的模型家族),或 documenter(泳道 docs)。只有一个空闲名额时,优先进行审核:这能解除推送阻塞;文档工作则等待。使用 2 个面板时,flex 的额外 reviewer 会接手审核,让 orchestrator 腾出精力。临时工作面板会在名单中标记为 burst;即使不带 --close,release 也会关闭其面板。在 flex 模式下,max_workers 和 split_max_panes 都会增加 flex_extra,因此额外面板会留在此标签页中。
documenter 只编辑文档(README、指南、参考资料、ADR、CHANGELOG),绝不编辑代码;它会在某个切片通过审核后,根据规范和已提交的差异开展工作。描述行为(命令、标志、配置)的文档应交给 reviewer;其余文档由 orchestrator 检查。仅担任过 documenter 的会话,在 reviewer 的模型家族检查中不算编辑 Agent;之前编辑过代码的会话(历史中有更早的角色)仍然算。
sub-orchestrator 默认不属于任何泳道,除非用户将其加入其中:嵌套的 herd 会打开更多面板,从而突破上限。lanes=off 会保留按角色区分的名称和 multi_role 复用。
将工作拆分为文件互不重叠的小切片。使用 --no-wait 分派,并通过 wait --any 收集结果。builders 工作期间,规划下一个切片,并整合刚返回的报告;优先处理 reviewer 队列中最先阻塞推送的切片。只要还有工作,就不要让 builder 闲置。泳道已满时,应先 wait,再分派,而不是新开面板。
spawn <role> 会解析对应泳道。没有泳道的角色会报错,lanes=off 时除外(并且在 panes=2 时,审核角色会提示由 orchestrator 进行审核)。如果两个 orchestrator 同时向同一泳道分派任务,可能会使其容量超出 1 个名额:Agent 启动前不会预留名额。
Orchestrator 工作流程 — /herdr-agents <objective>
当 first_run: true 时,先执行首次运行,并在打开任何面板前获得用户同意。工作进行期间,每个可见操作都用一行说明(叙述工作进展)。用户询问当前进展时,运行 $S explain(当前进展)。
并非所有任务都要委派。 如果某项任务只涉及一两个文件,且不需要产品决策——例如修改文档或配置、修复几十行代码的一次性小问题、回答问题,或执行一项比撰写任务说明更快的验证——就由 orchestrator 直接完成。经验法则:如果写任务说明比完成修改更费时,就直接修改。应委派多文件切片、符合设计规范的 UI 工作、任何涉及身份验证、机密或输入处理的工作、可并行处理的工作,以及任何需要 reviewer 的修改。研究工作也应委派:为辅助决策而阅读大量文件、其他代码仓库或多个工具的约定,属于 scouter 的工作;orchestrator 应要求对方提交包含建议的报告,再据此决策,而不是亲自调查并消耗自己的上下文。你自己编写的产品代码,在推送前仍需由来自另一个模型家族的 reviewer 审核;模型家族检查无法识别你自己的修改,因此要手动选择审核者的类型。
-
先明确方向。 如果目标中隐含着产品决策,先用一句话提问,再做规划。绝不要在明确方向之前写长篇计划。
-
自行拆分任务。 将任务拆分为文件互不重叠、接口明确且有执行顺序的切片。共享资源(i18n 目录、小型存储、常量)要么在任务说明中准备就绪,要么明确归属一名 Agent。
-
选择角色。 编排者负责规划。不要
spawn planner。 调研 →scouter/researcher(构建者)。UI →designer。代码 →implementer。大量机械性工作 →tasker。每个会修改代码的切片都要由另一个模型系列的reviewer审查;涉及身份验证/密钥/输入处理的切片还要由security-reviewer审查;涉及可见 UI 的切片还要由inspector检查。若切片涉及已知配置类型的薄弱环节,应改用另一名助手处理。薄弱环节列于 references/agent-profiles.md,例如在沙盒环境中的codex处理 UI 或 e2e,或小型模型处理不可信输入。lanes=off时:spawn <role> --name <new> --kind <kind>。- 启用 lanes 时: 一个 lane 对应一个 CLI;对另一个 CLI 的活动会话执行
spawn --kind会以状态码 13 退出。先对该 lane 的所有活动工作者执行release --close(如果该 lane 占用两个工作者,则关闭build和build-2),然后执行session set lane.<name>.kind <kind>(以及设置其模型),再 spawn。
只有目标机器才会显示的行为(路径、shell、OS 服务)无法通过在本机改用另一种类型来修复。工作者会报告无法运行,相关运行会在目标机器上进行。
保持 Fluxo paralelo 中的流水线完整。
-
为每个切片编写一份任务说明,使用 templates/brief.md:目标、负责的文件、禁止修改的文件、按路径列出的本地来源、适用的项目规则、工作者可运行的检查、报告格式。工作者的任务说明中不得包含提交、推送或 PR——git 由编排者负责。
-
启动并分派任务。 默认拓扑:在当前标签页中使用同级窗格、相同的 cwd,并指定
--no-focus。用户提出要求或两个编辑 Agent 共用同一 cwd 时,使用 worktree——spawn会对此发出明确警告(为每个 Agent 指定spawn --cwd <worktree>)。并行编辑 Agent 只运行针对单个文件的检查;完整测试套件只在集成时运行一次。 -
收集并集成。 阅读每份报告,然后查看
git diff。工作者报告“通过”不等于任务完成。收到 N 次交付后的固定顺序为:仓库格式化工具 → 类型检查 → 项目门禁 → 完整测试套件 → 对修改涉及的界面进行冒烟测试。 -
推送前审查。 针对集成后的 diff 分派
reviewer(相关时还要分派security-reviewer)进行审查。自行或通过 implementer 修复 P0/P1 问题,然后重新审查变更部分。 -
报告并释放。 说明已验证的内容,切勿夸大(“在 <tests + smokes> 中未观察到回归”)。只有在报告文件存在后才释放你启动的 Agent(
release --close会在任务中途终止工作者);只关闭本技能创建的窗格,且仅当用户未要求保留时才关闭。
等待返回 blocked 或 question 时,检查 herdr agent read <name>(JSON 中的 question 已包含问题所在的屏幕),并在回答确认或问题对话框之前先询问用户。超时或 agent_prompt_stalled 并不能证明提示已丢失——先读取,不要盲目重发。
Brief 即契约
要让更简单、成本更低的工作者可靠,关键在于编排器给出的 Brief,无论采用何种布局、委派何种角色:明确的目标、预期结果、每项验收标准及其验证命令,以及已做出的决定,这样工作者就不必自行臆造名称、格式、规则或要求。如果工作者必须猜测,问题就在于编排器的规划失误。使用 templates/brief.md,并在每次派发前运行
references/orchestration-contract.md 中的检查清单——其中每一项都是真实存在、曾导致一轮审查的缺口:含糊的判定条件、没有语义说明的选项标签、缺失的不变量(文件模式、原子写入、中断、沙盒、Windows)、缺少输入验证、Brief 条目过多、迭代时未规定要运行哪些测试、写入内容过大、新文件夹中的首次运行对话框。工作者报告缺口时,应在下一份 Brief 中将其作为一项决定明确下来。
Lint 会说明每个缺失部分为何会给工作者造成问题。
dispatch 会对 Brief 结构运行 lint(brief_lint,默认值为 warn;只读角色无需 Owned files 部分)。警告会按章节顺序说明每个缺失部分的原因:brief <path> is missing sections: [Goal] [Expected result] — <reason>; <reason>(严格模式会附加 (brief_lint=strict) 并以状态码 2 退出)。原因如下:Goal——工作者不知道该代码片段的用途;Expected result——没有说明何时算完成;Owned files——没有指定所属文件的工作者会发生冲突;Forbidden——没有任何规定阻止工作者修改其他文件;Report——没有报告部分,工作者可能永远不会编写报告;禁止提交的说明——工作者可能会提交或推送。另有一项独立检查会同时在 warn 和 strict 模式下标记空的行内代码问题——每行最多显示三条警告,之后将其余警告合并为一条;只有 brief_lint=off 才会将其关闭:
brief <path> line <n> has empty inline code (``): a shell heredoc without
quotes may have run the backticks
brief_lint_aliases
(逗号分隔的 Section=Heading|Heading 项)允许以某个章节标题开头(不区分大小写)的 1–3 级标题满足该章节要求:可配置别名的章节包括 Goal、Expected result、Owned files、Forbidden 和 Report(禁止提交的说明没有可配置别名的标题);格式错误的项会被忽略,并显示 brief_lint_aliases: ignored '<item>' (use Section=Heading|Heading),有效项仍会生效。
让规则落实
只有当提示词看起来像委派请求时,才会读取上述触发规则。“配置 X,看看仓库 A 和 B 是怎么做的”看起来不像委派请求,编排器会自行查看 A 和 B。每个项目运行一次:
$S setup # block in AGENTS.md (or a non-symlink CLAUDE.md) + Claude hooks
$S setup --target CLAUDE.md # when CLAUDE.md is the canonical file
$S setup --no-hooks # instruction block only
与 ai-memory 的路由片段类似,setup 会将委派规则写入项目规范说明文件中 / 标记之间,并将两个钩子合并到 .claude/settings.json:UserPromptSubmit(在 HERDR_ENV=1 时,每条提示词都会显示一行提醒)和 SessionStart(doctor 警告)。
该代码块仅包含工作流和 Brief 契约;窗格数量、使用哪些助手和模型仍由配置决定,因此该代码块不会与项目团队配置相矛盾。对于符号链接形式的说明文件或设置文件(AGENTS.md -> CLAUDE.md),写入会通过链接进行:链接本身仍是链接。钩子命令通过 sh 调用,因此只会在有 POSIX shell 的环境中运行(在 Windows 上通过 Git Bash 或 WSL 运行)。重新运行会替换代码块和钩子;如果重写失败,则绝不会触碰文件。生成的项目文件绝不会嵌入安装程序的绝对路径:SessionStart 钩子会优先使用项目的 .agents/skills/ 或 .claude/skills/ 副本,然后再检查用户主目录下的相同位置。找不到可用路径时,setup 会发出警告;缺少代码块或钩子时,doctor 和 init 会发出警告。使用 scripts/run-tests.sh --env outside test-setup.sh 验证设置变更。
Codex、Grok、Cursor 和 agy 没有提示词钩子;对它们而言,代码块就是防护措施。
设置:引导式配置
setup 会写入指令块。它不会猜测这台机器上安装了哪些 CLI。首次运行时,以及 doctor 报告存在缺失或旧版配置时(缺少 panes、空的 lane.<name>.kind 所对应的角色解析为不同类型、split_max_panes 大于 panes、某条通道已有自己的类型却又为其角色单独设置类型、role.planner.*、角色或通道模型因生效类型来自更高层且未设置模型而被丢弃、类型和模型组合无法在该类型的模型列表中解析),或者因配额而停止时(退出码 11),编排器会引导用户逐步完成选择。每一步都使用
运行框架的结构化提问工具(Claude Code:AskUserQuestion,
Codex:ask_user_question,OpenCode:question),并提供三个选项——第一个标记为推荐选项,并附上一行理由——以及一个自由文本字段,供用户准确说明想要什么(使用工具的自由文本/“其他”字段;工具没有该字段时,提供第四个“自己说明”选项)。绝不提出没有建议的开放式问题,也绝不要求用户填写标志、键或模型 ID。项目文件未设置 multi_role、任何 lane.<name>.kind 或任何 role.<role>.kind 时,setup 还会发出警告;单独设置 max_workers(包括 doctor --fix 写入的值)不算作此类选择。
步骤按以下顺序进行,并使用用户的语言(绝不使用 lane、kind 或
panes 这些词):
- 征求同意(首次运行)。 在打开任何面板前,说明团队的组成 (首次运行时的语音),并询问是否打开。选项:是,打开 (推荐——这样可以并行处理工作)、先详细了解,再打开 否,不使用团队 + 自由文本。拒绝后会停止团队。
- 同时运行多少个 Agent。 选项:4 个面板(推荐——两个并行编写
代码,一个负责审查)、3 个面板(更省配额:一个编写,一个审查)、
2 个面板(最精简:一个编写,审查在此处进行)+ 自由文本。映射回答:
4 →
setup --panes 4;3 →setup --panes 3;2 →setup --panes 2。 然后再问:需要时再增加一个面板? 选项:不,绝不超过这个数量 (推荐——默认设置,pane_mode=strict)、是,临时增加一个面板,用于 第二次审查或编写文档(pane_mode=flex)、稍后决定 + 自由文本。 - 每项工作由哪个助手负责。 运行
$S setup --detect(不会写入任何 内容),然后运行$S setup --probe——针对每种类型/模型运行简短超时的 最小非交互提示词,不使用面板;状态为ready | no-auth | quota | error,并提供recommended_reviewer(来自与构建助手不同系列且状态为 ready 的类型)。只有探测状态为ready的助手才会成为选项,包括个人 提供商的模型(--detect的custom_models条目,格式为provider/model,并在有声明时注明最高推理级别)。汇总探测已测试每个 列出的自有模型(每种类型最多 5 个,source: "custom"的行):仅当其 自身所在行状态为ready时才提供该模型。skipped_custom中的模型尚未 测试:先运行$S setup --probe --kind K --model provider/model,仅当该行 状态为ready时才提供。共有三个问题:- 编写代码(构建通道):如果用户文件中已指定用于构建的助手且其探测
状态为
ready,则推荐该助手;否则,推荐能力上限最高的 ready 助手。 提供商之间没有固定排名。 - 审查:必须与构建助手属于不同的模型系列;使用
recommended_reviewer作为推荐选项(codex 优先于 claude)。 - 研究:推荐速度最快/成本最低的 ready 助手——如果探测结果列出了
fast/flash 模型,则使用该模型;否则,选择成本最低的 ready 系列。
在 ready 助手中,让
references/agent-profiles.md 决定推荐选项
并说明理由。该文件会说明各助手在实际使用中擅长哪些工作,以及哪些编写者
与审查者组合发现了实际问题。
每个选项都包含助手名称及其一行
summary(已翻译);推荐项还会附上一行 推荐理由。 在pi或opencode上使用自有提供商: 提供此类provider/model前,读取--detect中其custom_models条目的warnings(与doctor报告的风险相同;绝不会打印任何值):使用字面密钥而非环境变量引用、 pi 的maxTokens未比当前使用的 effort 推理预算多出 8192 个 token、 opencode 模型没有数值型thinking_token_budget。如果存在警告,则询问: 替我修复(推荐——先显示具体改动)、我会自行修复、照原样使用
- 编写代码(构建通道):如果用户文件中已指定用于构建的助手且其探测
状态为
- 将每项选择保存到哪里。 每项选择分别提问:仅限此项目(团队共享—— 项目文件)、作为我的个人默认设置(适用于我的所有项目——用户文件)、 仅限此会话(临时——会话层)+ 自由文本。个人提供商和模型默认保存到 用户层。
- 确认。 根据回答构建一条
setup --plan …命令——为团队设置--panes和--lane name=kind:model:effort,为配置键设置--set key value/--user-set key value,为会话设置--session-set key value——并显示其输出:每个将被修改文件的具体改动; 配置文件显示key before → after,指令文件、.claude/settings.json和(写入时会添加的).gitignore显示统一差异 (不会写入任何内容)。选项:写入(推荐 ——符合你的回答)、调整(用户说明要改什么;重新构建计划并再次显示)、 取消 + 自由文本。 - 写入。
setup --panes 2|3|4 --lane name=kind[:model[:effort]]…、config set <key> <value> [--user]、session set <key> <value>——使用 计划中显示的相同键——然后运行setup(指令块 + hooks)和doctor; 处理所有仍有警告的项目。
答案的构建方式(机制)
setup --detect 会打印 JSON,且不会写入任何文件:对于每种已知类型,它都会输出
installed、family、effort_ceiling、简短的英文 summary(向用户展示时请翻译)、
CLI 有响应时返回最新的至多 3 个模型 ID(CLI 缺失或无响应时返回空列表,不视为失败),以及通用类型的
custom_models——用户在 ~/.pi/agent/models.json(pi)和 opencode.json(项目级和用户级)中声明的模型,
格式为 provider/model,并在存在时附带声明的最高推理等级。密钥仍保留在这些文件中:只读取 ID 和等级。
它还会打印 panes、lanes、生效的 lanes 以及 2、3、4 的预设(每条 lane 都包含其容量 panes)、
max_workers、multi_role、reuse_workers 的生效值及其来源、
每个 role.<role>.kind、每个 model.<kind>.worker,以及
recommended_reviewer(仅限已安装的类型;探测会进一步将其缩小为能响应实际提示词的类型)。
setup --probe [--kind K --model M] [--timeout SECONDS] 会针对每种类型/模型运行一个简短的
非交互式提示词(claude -p、codex exec、grok
-p、agy/gemini -p、cursor-agent -p、pi -p --no-session、opencode
run;--timeout 或 HERDR_AGENTS_PROBE_TIMEOUT 的值为 ≥ 1 的整数秒,默认值为 20),并分类为:
ready、no-auth(登录消息)、quota(wait 会检测到的相同提供商消息)或 error(超时也属于错误)。
cause 不会复制 CLI 文本,而是使用固定类别:
not installed、timeout after <N>s、not authenticated、quota exhausted(仅当续期行包含日期/时间时,才附加 ; renews <date/time>),或 exit <code>。
它不会打开窗格,不需要 Herdr,也绝不会打印 CLI 输出——只打印分类和原因。未指定
--kind 时,它会使用 spawn 将采用的模型探测每种已知类型
(先取 model.<kind>.worker,再取 model.<kind>,否则使用 CLI 默认值;各行包含 source: "configured"),
并探测 --detect 返回的已安装 pi/opencode 各自至多 5 个自定义模型
(source: "custom",按 detect 顺序);其余模型列表会作为 skipped_custom({kind,
id})报告,每个都可通过 --kind K --model provider/model 单独探测。
setup --plan(与 setup/config set/session set 使用相同参数,通过 --panes、--lane、--set、--user-set、--session-set 传入)会在各自的临时目录中模拟每项写入,并打印指令文件
(AGENTS.md/CLAUDE.md)、.claude/settings.json 的 diff -u(a/<path> 和 b/<path>),
以及——在写入会添加内容时——仓库的 .gitignore(setup 和 session set 会刷新其中的
.herdr-agents/ 条目);配置文件(.agents/herdr-agents.conf、用户文件、session.conf)则会保留
key before → after 格式的行。它不会写入任何内容——甚至不会创建状态目录。
请在确认步骤中使用它;每当用户询问“这会有什么变化?”时也应使用它。
doctor --fix --panes 2|3|4 [--user|--session] 会对旧版文件执行相同的规范化
(--session 针对工作区的 session.conf,在无法解析 Herdr 工作区时
以状态码 2 退出)。如果文件中的通道属于预设(无预设、新预设,或旧版
build/explore/review 和 build/read),则不会保留通道角色、
max_workers 或 split_max_panes:预设会在运行时解析。你在预设包含的
通道上设置的容量(lane.build.panes=3)会保留。
如果新预设包含 review 通道,且尚未设置相应键,lane.read.* 会移至
lane.review.*;lane.explore.* 以及预设不包含的通道的键会被移除,并为每项
说明原因。包含自定义通道的文件会保留这些通道,并将 max_workers 设为其
容量总和,将 split_max_panes 设为 panes;在 flex 模式下,两者均加上
flex_extra,以确保临时 worker 也能容纳。两种情况都会设置 panes 和
reuse_workers=on。doctor 本身会对旧版预设以及已不存在通道的键发出警告。对于每个通道,它会
解析每个角色的种类和模型(取该文件中的值,否则取角色 frontmatter 中的值)。
如果它们一致,就会写入 lane.<name>.kind / .model,然后才移除这些
role.<role>.* 键。如果它们不一致,则保留这些键,列出 role=kind,并提示你询问后运行
setup --lane <name>=<kind>[:<model>[:<effort>]]。无论哪种情况,都会移除
role.planner.*。注释会保留。它会以 diff -u 格式打印更新后的文件,并使用
a/<file> 和 b/<file> 标签(如果没有变更,则显示 no changes in <file>),
与 setup --plan 类似。如果没有 --panes,且文件中也没有 panes,--fix 会以状态码 2
退出,并提示你选择 2、3 或 4——它不会自行选择。在这种情况下,请执行上文第 2–5 步
(先回答面板数量问题,再查看计划并确认),最后运行 doctor --fix。
multi_role=on(默认值,包括未设置该键时):不带 --fresh 的 spawn
会复用其他角色的空闲 worker,前提是种类、工作目录和解析后的模型相同,
该 worker 的 approvals 不低于请求的级别(ask < edits < full),并且它启动时使用的原生参数
(名册第 14 列)与本次 spawn 将传入的参数相同(原生参数在整个进程期间保持不变)。会优先尝试
相同角色。曾承担编辑角色——implementer、designer、
tasker 或任何带有 mode: edit 的角色——的 worker,绝不会被复用为
reviewer、security-reviewer、ui-reviewer 或 inspector。随后 spawn 会启动新的
worker,并受 max_workers 限制。multi_role=off 时,只会复用相同
角色的 worker。
名册文件会在原有八列之后新增列。旧行仍然有效,并且仅在 lanes=off 时
才会为相同角色复用。这些列包括 model、approvals、roles(以逗号分隔的历史记录,例如
scouter,implementer)、lane、burst(flex 模式下的临时 worker)和 args(启动时使用的已配置原生参数:
args.<kind> 加上 lane.<name>.args 或 role.<role>.args)。第 4 列
仍为当前角色。
启用 lanes 时,复用仅限于同一通道。lanes=off 时,跨角色复用会就地改写该行,并追加新角色。复用后的
spawn JSON 会包含 previous_role。dispatch 会读取第 4 列,因此组合后的提示词采用新角色。roster 会打印当前角色,并在列宽足够时显示
历史记录。
项目根目录
简报和报告是状态目录下的临时产物,绝不会放在仓库中。如果工作属于规划计划
(planning/<initiative>/ 或项目中与之对应的目录),请将每个切片的最终报告复制到它所实现的
故事旁边;概览中的状态行不能替代该报告。为切片创建的 worktree 位于仓库的
.worktrees/ 下,并会在发布时列出,而不会删除。
提示词
在以下情况下使用 harness 的结构化提问工具:
wait、status或dispatch返回quota(退出代码 11)。JSON 中包含lane、kind、model、经过清理的match,以及屏幕上显示时的renewal。问题格式与设置阶段相同:三个选项 + 自由文本。 切换助手(当另一位助手的探测状态为ready时推荐——优先选择recommended_reviewer;请说明选择了哪一位)、等待续期(当 JSON 中列出时间时)、 在本次会话中完成这部分工作(在自由文本中说明暂停)。当工作在新的工作进程上恢复时, 请在简述中附上部分修改的git diff,以便继续工作,而不是从头开始。wait、status或dispatch返回provider-error或capacity(退出代码 14)。工作进程处于空闲状态且没有报告;JSON 中包含lane、kind、model和cause行(capacity时还包含retries)。选项: 将简述重新发送给同一工作进程(当提供方再次响应时推荐——进行简短探测,或原因是超时)、 切换助手(说明选择了哪位就绪的助手)、等待 + 自由文本。切勿盲目重发: 请先阅读面板内容。- 目标可能与 UI 有关,也可能无关,答案会影响要启动哪些角色。
- 审查者将与实施者来自同一系列,且没有安装其他类型的审查者(选项:接受、替换类型、跳过审查)。
- 释放资源会关闭存在未读输出的面板,或包含未提交更改的工作树。
feedback=ask且你有改进问题要提交时(显示标题和场景摘要;选项:提交、跳过、编辑)。
当 $ARGUMENTS 为空时,请以自由形式询问目标。在不停顿模式下,将这些问题记录为最终报告中的待解决问题,并按推荐选项继续。
改进此技能(遇到阻碍时提交 issue)
编排器最先发现此技能何时造成阻碍:类型映射错误、等待结果有误、缺少所需命令,或角色提示词导致工作器行为异常。将这些问题提交为此技能仓库中的 issue,让维护者逐步改进。
-
**何时:**任何由技能本身造成的阻碍(而非项目或工作器的任务造成的阻碍)。
$S friction会列出此工作区中脚本产生的所有错误和警告;请在运行结束时检查。每个不同的问题提交一个 issue;先运行gh issue list --repo <feedback_repo> --search "<keywords>" --label herdr-agents检查是否有重复项。日志的每一行都保留四列(日期、级别、命令、消息;消息中的换行符会被清理),而friction add "<text>" [--brief <path>]会记录工具本身不会记录的阻碍(级别为note,命令为friction;--brief会追加(brief: <path>))。 -
策略由
feedback配置键控制:ask(默认):告知用户你准备提交的内容,只有获得同意后才提交;on:直接提交,并在最终消息中提及;off:绝不提交,只在最终消息中描述遇到的阻碍;local:此技能的维护者正在这台机器上工作。将报告发送给该维护者,而不是提交 issue(见下文)。
-
**操作方法:**填写 templates/issue.md(场景、实际情况及准确的错误文本或 JSON 行、预期情况、
$S env和$S config的输出、证据路径,以及可选的建议修改),然后:gh issue create --repo "$("$S" config | awk '$1=="feedback_repo"{print $2}')" \ --title "herdr-agents: <one line>" --label herdr-agents --body-file /tmp/herdr-agents-issue.md从证据中删去机密信息和客户数据。绝不要粘贴来自私有仓库的完整报告;只引用能说明问题的行。
-
**使用
feedback=local时:**将相同模板写入文件,然后:$S feedback send /tmp/herdr-agents-friction.md "<one-line summary>"- 报告会保存为
<feedback_dir>/from-<project>-<date>.md;若当天已有报告,则使用-b、-c等后缀;绝不会覆盖现有文件。feedback_dir必须是指向现有目录的绝对路径(否则doctor会发出警告)。 feedback_to中指定的窗格或 Agent 会收到一行摘要和路径。- 未设置
feedback_to时,只会写入文件。 - 操作会打印一行 JSON。退出码为 4 表示文件已保存,但通知发送失败:请自行告知维护者。
- 不要修改此技能、其已安装副本或其他项目的角色或配置来绕过阻碍。维护者会回复,并告知你何时需要修改项目配置。
- 报告会保存为
测试此技能
移植后的命令带有 JS 测试,可在任一运行时下运行:
node --test scripts/test/ # JS tests (Node 20+)
bun test scripts/test/ # the same tests under Bun
回归测试矩阵包含 scripts/test-*.sh 中的所有套件——这些 bash 套件通过 POSIX scripts/herdr-agents 启动器测试 JS;每个套件都要分别在 Herdr 内部(设置 HERDR_ENV=1,并使用测试窗格/工作区)和外部运行。请使用并行隔离执行器运行,绝不要手动编写循环:
scripts/run-tests.sh # every suite × inside+outside, parallel
scripts/run-tests.sh --env outside test-kinds.sh # one suite while iterating
scripts/run-tests.sh --bash /bin/bash # also run the matrix on that interpreter
scripts/run-tests.sh --jobs 4 # cap the parallel jobs
旧版 bash↔JS 一致性测试使用 scripts/test/golden/ 下的基准文件(移植前记录的 bash 行为):有意更改行为时,使用 HERDR_AGENTS_GOLDEN=update 重新记录,然后检查差异。
每次运行都会在临时目录中使用各自独立的 HOME、XDG_CONFIG_HOME 和 TMPDIR,并清除父环境中的所有 HERDR_AGENTS_* 变量,因此不会有套件读取 ~/.config/herdr-agents、~/.pi 或 ~/.config/opencode。除非设置了 HERDR_AGENTS_KEEP_TEST_LOGS=1,否则退出时会删除临时目录(即使失败也会删除)。输出中每次运行占一行,格式为 PASS|FAIL <suite> [<env>, <bash>] <seconds>s,后接摘要;失败时会打印每次失败运行日志的最后 30 行。退出码:0 表示全部通过,1 表示有任一项失败,2 表示用法无效。
简报测试规则:迭代期间,工作器只运行覆盖相应项目的套件(scripts/run-tests.sh --env outside test-<x>.sh);完整矩阵(scripts/run-tests.sh)只在提交报告前运行一次。
安全
- 绝不执行
herdr server stop;绝不关闭此技能未创建的窗格、标签页或工作区。 - 优先使用
--current、明确指定窗格 ID 和唯一的 Agent 名称。从 JSON 中解析 ID,绝不根据侧边栏顺序判断。 - 简报和报告可能包含仓库内容;不要在其中放入机密信息。
参考资料
- references/troubleshooting.md — 已观察到的故障、原因、修复方法,以及验证某种类型的方法;修改脚本前请先阅读
- references/orchestration-contract.md — 此技能强制执行的委派契约
- references/kinds.md — 类型 → 系列表、通用类型(pi/opencode)的配置和提供商示例,以及安装说明
- references/agent-profiles.md — 根据实际使用情况总结的各助手在不同角色中的优势和劣势;选择团队前请先阅读
- templates/brief.md、templates/report.md