CtrlK
BlogDocsLog inGet started
Tessl Logo

subagent-execution-governance

把子代理派发从"监督型治理"升级为"契约型治理":探查/实现/验证角色分离、契约快照(含负空间)、三级有界读取、单写者文件所有权、行动门槛替代轮次门槛、结构化 BLOCKED、token/工具/轮次预算、结构化结果回收与 repair-contract 恢复。用于派发实现型子代理(写代码/写文件类任务)、设计"谁读什么/谁写什么/何时算阻塞"的执行协议、审计子代理空转(反复探查不产出、并行写冲突、上下文膨胀)、或复盘"子代理烧了大量 token 却没产出"的会话。不用于纯问答、单轮小修改、或已有成熟任务流程的普通委派。

71

Quality

87%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

子代理执行治理(Subagent Execution Governance)

本 skill 由一次真实实现会话审计(session-33b69ec9-1abf-454d-9555-f2d4031a9453)提炼而成。那次会话 3 小时、17 个子代理、执行层消耗 309 万输入 token(主会话 4 倍),b21b9211 一个子代理读了 65 个文件后仍被催"直接实现",主会话被迫 28 次 send_message 催促 + 8 次 interrupt_agent,最终目标未 complete、会话中途悬死。根因不是"监督不够凶",而是子代理的工作边界、信息边界、写权限和退出条件没有工程化。

核心原则

不要从"自由探索"直接走向"实现代理完全失去自主权";正确形态是 契约驱动 + 有界自治 + 结构化升级

目标不是"主代理不断管子代理",而是 系统规则让正常子代理根本不需要被管

失败因果链(本 skill 要打断的):

任务设计错误(探查/实现不分)
  → 执行边界过宽(无限读取授权)
  → 监督不得不频繁介入(催促/中断/重派)
  → send_message / interrupt 注入上下文
  → 上下文继续膨胀 → 缓存命中率恶化 → token 爆炸

一、角色分离(Discovery → Contract → Implementation → Validation)

禁止让一个子代理同时承担"先研究、再实现、再测试"四种认知模式:

角色产出
Discovery(探查)自由只读禁止契约快照草案(≤15 条 file:line 事实)
Contract Builder(主会话)验证契约写契约文件最终契约快照(含负空间)
Implementation(实现)有界读取(三级)只写自有文件代码 + 变更清单 + 状态
Validation(验证)只读目标文件/测试禁止(或只改测试)测试结果 + 差异报告

主会话承担 Contract Builder 与 Orchestrator:探查结果必须经主会话验证、确认文件无冲突、写入契约快照后,才能派实现子代理。禁止探查子代理直接产出实现任务。

二、契约快照(Implementation Contract)

每个实现子代理派发前必须有一份契约快照,包含正空间和负空间

GOAL:           一句话目标(可验收)
OWN:            本子代理独占写入的文件(单写者)
MAY READ:       自动允许读取的文件/目录白名单
REFERENCE:      参考实现文件(读但不改)
IN SCOPE:       允许做的事
OUT OF SCOPE:   禁止做的事(防 scope creep)
MUST PRESERVE:  必须保持不变的现有行为/API
MUST NOT:       禁止触碰的模块/文件/顺手重构/兜底路径
EXIT:           完成条件(确定性可判)
BLOCKED:        允许升级阻塞的场景(仅限契约外信息缺失)

负空间(OUT OF SCOPE / MUST NOT)是防"模型顺手优化"最有效的手段,必须有,且比正空间更具体

三、读取策略:三级有界读取(不是"只写不读")

实现子代理不自由探索仓库,但保留必要自治——三级读取权限

Level 0 — 自动允许(无预算消耗)
  目标文件、契约快照、指定参考实现、直接测试文件

Level 1 — 有预算的自主读取(最多 N 个额外文件,需带 reason code)
  API_SIGNATURE_UNKNOWN       类型/签名未知
  TEST_EXPECTATION_UNKNOWN    测试预期未知
  TYPE_DEFINITION_REQUIRED    需要类型定义

Level 2 — 需要升级(禁止自主执行)
  跨模块架构探索、repo-wide grep、超过预算、发现契约错误
  → 走结构化 BLOCKED,不自行扩大范围

不要把读的决策权全部收归主会话(会变成"主代理当 I/O 调度器"的 ping-pong);也不要完全放开(会回到无限探索)。Level 1 的 reason code 让升级可观测、可审计。

四、写入所有权:单写者文件所有权

一个文件在同一时刻只有一个 writer owner。
  • 共享文件:禁止两个子代理同时写;由主会话(或专门的 integration agent)最后统一修改。
  • 派发前主会话必须做文件级冲突检查:把每个实现子代理的 OWN 集合求交,交集为空才并行。
  • 并行写冲突("目标文件已被父代理并行更新")是调度错误,不是模型错误——重派前先改派发拓扑。

五、进度状态机(替代"催促")

实现子代理只允许处于以下状态:

IMPLEMENTING    工作中(每阶段报告当前状态与产出物)
MUTATED         已完成首次有效写入(重点信号)
BLOCKED         结构化阻塞(见下)
DONE            完成,附验证证据
FAILED          失败,附原因

没有 STILL_EXPLORING 状态,也不存在无限期的 STILL_RESEARCHING 正常协议里几乎不存在"催促"——orchestrator 不靠"你做好了吗/赶紧实现/不要再读了"判断执行状态,而是看状态机与资源观测。

探查充分即停(EVIDENCE_SUFFICIENT):证据已足以安全选择下一动作时必须停止读取、进入 MUTATE 或结构化 BLOCKED;"还能再查更多"不是继续探查的理由。每个报告周期必须带 Progress Delta(DONE_CRITERION_CLOSED / MEANINGFUL_MUTATION / BLOCKER_REMOVED / DECISION_RESOLVED / NEW_ACTION_CHANGING_EVIDENCE,见 execution-discipline);无 delta 的重复读取/重复测试不算进展。

空转判定(替代"催两次就判空转"):连续 K 个有效动作窗口内 mutation_count = 0discovery_budget 耗尽 → 自动判定 STALLED,由 watchdog(观测通道)触发,不是人工催促。

六、行动门槛(替代"第 N 轮必须建文件")

轮次门槛会产生 Goodhart(先 touch 一个空文件满足 KPI 再继续探索)。改用行动门槛

在 exploration budget 耗尽之前,必须发生以下之一:
  A. 第一处有效代码修改(mutation)
  B. 返回 BLOCKED(reason, exact_missing_information)

禁止第三种状态:"继续研究。"

实现子代理在首次 mutation 前,允许读取目标文件、契约参考文件、最多 K 次 Level-1 额外查询;预算耗尽而未 mutation 即 STALLED。

七、结构化 BLOCKED(防止"无限问主代理")

BLOCKED 必须是结构化异常,不是自然语言求助。有效性门禁:缺任一关键字段 = BLOCKED_INVALID,orchestrator 不接受停止

BLOCKED:
  blocked_reason:                一句话阻塞原因
  why_it_blocks_done:            为什么它阻止 Done Criterion 闭合
  evidence:                      已收集的证据(含已查文件/命令/输出)
  recovery_steps_attempted:      已尝试的恢复步骤(Diagnose/Reproduce/Local/Search/...)
  alternative_routes_attempted:  已尝试的替代路径(换工具/换通道/换假设)
  what_external_fact_is_missing: 缺失的外部事实(精确到签名/字段/配置项)
  why_agent_cannot_obtain_it:    为什么自己无法获得(所有可用通道均已排除的证据)

# 兼容简写:missing_fact≈what_external_fact_is_missing,why_required≈why_it_blocks_done,
# already_checked≈evidence,requested_context≈希望 orchestrator 补充的上下文

orchestrator 收到 BLOCKED 后,先按五级阶梯自行解决,不得直接转发用户

1. 自己补 context(把缺失信息补进契约 / 直接回答)
2. 派 narrow discovery probe(极窄只读查询)
3. 换 alternate tool / channel / model
4. 创建 repair contract(只处理失败点)
5. 修订本地执行计划(任务设计错误 → 终止并重设计)

五级阶梯走完且符合 execution-discipline「合法停止策略」五类之一,才可向用户报告;否则继续推进。禁止随手回 send_message("继续看看")

八、资源预算(必须存在且可观测)

"不要无限探索"必须转成机器可判断的资源约束:

Discovery:    ≤ 12 次 repo read/search,≤ 2 个 agent turns
Implementation:首次写入前 ≤ 6 次工具调用;额外探索 ≤ 4 次
Validation:   只允许 test / lint / targeted read

具体数字按任务调整,关键是:预算必须存在、写入派发 prompt、并在会话纪律体检时可见

九、上下文回收:结构化结果 only

工作历史不进入 orchestrator 的活动上下文。 子代理完成/报告时只回:

Agent A DONE
Changed:    [foo.ts, foo.test.ts]
Validation: 17/17 passed
Deviations: none
Blocker:    none
Details:    artifact://agent-A/report

报告体积硬约束(≤500 词,业界 LangChain Deep Agents 值):最终报告正文 ≤500 词;原始数据(完整日志、表格、证据)一律写文件,Details 只给路径。超长报告不得 splice 回主上下文——体积保护层配合前缀缓存保护,结构性防炸(实测:大量 inbox/spliced 注入与单步 204,869 输入 token / cache=0 高度相关)。

派发类别标注([PREP]/[EXEC],准备-执行平衡):每次 subagent 派发的 description 必须以 [PREP](调查/审计/验证/合同)或 [EXEC](实现/构建/运行/修复)开头;同一轮次内 [PREP] subagent 数量达到 6 个且 [EXEC] 为 0 时,必须停止派发调查类 subagent,先派一个 [EXEC] 动作(准备压倒执行是复发反模式,2026-08-25 实测:单日 19 个 subagent 全部为调查类、codex 派工 0 个 implementation,用户两次发火)。此约束为流程层,系统层插件版(自动计数拦截)待开发。

禁止把子代理的完整工作过程(大量探查日志、多轮内部推理)splice 回主上下文。这是缓存保护的结构性方案,不是"少发几次消息"。多次大规模 splice 会杀死前缀缓存(实测单步 204,869 输入 token 且 cache=0 与大量 inbox/spliced 高度相关)。

十、恢复:checkpoint + repair contract(失败不重派全新 agent)

真实状态 ≠ chat history

任务状态存盘:
  task-state.json          # 当前阶段、状态机、预算消耗
  implementation-contract.md
  completed-work.json      # 已完成文件与验证
  validation-report.json

失败路径:
  FAIL → 创建 repair contract(只处理失败点)→ 派实现
  而不是:重派全新 agent 重新理解仓库

主会话即使中断,新的 orchestrator 也能凭存盘状态继续,不从零重放。

十一、模型路由(排最后,且不是省钱主杠杆)

模型选择是最后一道配置,不是治理手段:

  • Discovery/Validation:便宜高速档(如 gpt-5.6-luna-max
  • Implementation:工作马档(如 gpt-5.6-terra
  • Orchestrator/决策:前沿档(如 gpt-5.6-sol-xhigh

经验证据:设计不良的任务,用再便宜的模型也能烧掉 300 万 tokens。 任务设计正确优先于模型省钱。

十二、派发协议清单(每次派实现子代理前过一遍)

  1. 契约快照存在?含负空间(OUT OF SCOPE / MUST NOT)?
  2. OWN 文件与并行子代理无交集?(单写者)
  3. 读取白名单 + 三级权限写清楚了?
  4. 预算(工具调用/探索次数/token)数值化并写入 prompt?
  5. 行动门槛(mutation 或 BLOCKED,二选一)?
  6. 状态机字段(IMPLEMENTING/MUTATED/BLOCKED/DONE/FAILED)要求回报?
  7. 结果回收契约(只回结构化摘要,不回工作过程)?

与相邻 skill 的分工

  • execution-discipline:执行层五条铁律(零轮询、不惊群、不肉身读、派发带进度回报)——管"执行纪律",本 skill 是其实现型任务的深化协议
  • decision-gates:决策层不跑偏(checkpoint 证据锚、成本比对)——管"决策正确性"。
  • 本 skill:契约型治理——管"子代理工作边界、信息边界、写权限和退出条件的工程化"。三者可叠加:先按 execution-discipline 自查执行姿势,再按本 skill 出契约,最后按 decision-gates 落 checkpoint。

反面案例速查(本 skill 来源)

场景当时的错误现在该怎么做
实现子代理空转b21b9211 2 轮读 65 文件、grep 30 次、941K tokens 后仍被催"直接实现"契约快照 + 三级读取 + 行动门槛:首次写入前 ≤6 次工具调用,无 mutation 即 STALLED
并行写冲突多个子代理并行写同一文件包,b21b9211 报告"目标文件已被父代理并行更新"派发前文件级冲突检查:OWN 集合求交为空才并行
催收式管理主会话 28 次 send_message + 8 次 interrupt_agent,双方 token 叠加膨胀状态机 + 结构化 BLOCKED + watchdog 判定,正常路径无催促
上下文撑爆缓存169 次 inbox/spliced 注入,单步 204,869 输入 token 且 cache=0结构化结果回收:只回 status/changed/validation/blocker/artifact ref
目标中途悬死第三个 goal 未 complete,会话停在 open stepcheckpoint 存盘 + repair contract 恢复,不从零重放
便宜模型不等于省钱执行层 309 万输入 token(luna-max),是主会话 4 倍任务设计正确优先于模型省钱;模型路由排最后

工具化支撑(P1/P2 落地物)

本 skill 附两套运行时工具,让治理从"靠 prompt 自觉"变成"可观测、可执行":

P1 用量观测插件(subagent-usage-observer)

动态 Cordis 插件(Host 端),注册两个工具:

  • subagent_usage:输入子代理 session id → 输出 tokens(input/output/cacheRead)、models、preset、toolCallsCount、mutationsCount、turns、steps。数据源 sessionQuery.readSession,只读。
  • subagent_stalled_check:基于预算约束(mutationBudget 默认 1 / toolBudget 默认 6 / turnBudget 默认 3)保守判定:成功的 edit/write 结果达到预算 → MUTATED;检测到四字段结构化报告 → BLOCKED;工具行动预算或轮次兜底预算任一耗尽且无 mutation/BLOCKED/潜在写入工具 → STALLED;命令或委派可能写入但日志无法证明时保持 IMPLEMENTING,避免假阳性。

用途:替代"催 2 次判空转"的轮次拍脑袋。watchdog 用工具调用数与 mutation 事实判定,不靠催促。

P2 splice 摘要化插件(subagent-splice-summarizer)

动态 Cordis 插件(Host 端),监听 agent/pre-step waterfall:

  • 对进入步骤的 source.kind === 'subagent-report' 消息,若文本超 8000 字符,替换为结构化摘要(保留 status/changed/validation/deviations/blocker/artifact 各节前几行,其余截断;无结构字段的走首尾截断)。
  • 目的:阻断超长子代理报告全文 splice 回主上下文,保护前缀缓存。非 subagent-report 消息与短报告不动。

注意:这是体积保护层,不是缓存银弹。A/B 实验(scripts/splice-ab-experiment.js)实测:审计会话 117 条注入共 ~55K tokens(仅占总输入 7%),摘要化仅省 2.6%——真正的大头是每步前缀重复(169 次注入/单步 204K 输入/cache=0)。所以 P2 的价值是"结构性防炸"(极长报告不会一次塞爆),缓存命中率仍需 A/B 重放实测。

体检脚本(scripts/)

  • session-discipline-audit.js <session id|zstd 路径>:完整纪律体检(模型路由、每轮 token、子代理清单、催收成本、cache=0 异常、短轮询、全量读风险)。
  • splice-ab-experiment.js <session id|zstd 路径>:A/B 体积对比(全量注入 vs 摘要化的字符/token 节省,按轮聚合,top 条目前 5)。

两个脚本均 Node ≥22(node:zlib 内置 zstd),支持直接传会话 ID 自动定位。

Repository
ooooooooooooooooooop/agent-tools
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.