ruflo nested-leaf:嵌套生成树最底层的"最小权限叶子"Agent 模板实战指南
【免费下载链接】ruflo🌊 The original agent meta-harness. Deploy intelligent multi-player swarms, coordinate autonomous workflows, and build conversational AI systems. Features adaptive memory, self-learning intelligence, RAG integration, and native Claude Code / Codex / Hermes and many more Integrated项目地址: https://gitcode.com/GitHub_Trending/cl/ruflo
ruflo 在plugins/ruflo-agent插件中提供了一整套面向 Claude Code 原生嵌套子代理(nested subagents)能力的 Agent 模板。nested-leaf是这套体系中的叶子节点模板——它位于整棵生成树的底层,只被赋予一个聚焦任务,并且故意不授予Task工具,从而构成 ADR-147 所要求的最小权限边界(least-privilege boundary)。本文以该模板为核心,讲解叶子的职责契约、强制返回结构、为何禁止叶子再派生,以及它与nested-coordinator/nested-researcher/nested-reviewer等编排者模板的配合方式,并结合仓库中的 ADR 与源码给出可验证的底层依据。
为什么需要"叶子":嵌套子代理的上下文管理动机
嵌套子代理的出发点不是并行,而是上下文管理。Claude Code 2.1.169 引入的嵌套能力让每个子代理拥有独立的上下文窗口,子代理自己还能再派生子代理,最深可达 5 层(Anthropic API 上限)。与"扁平扇出"相比,嵌套的最大价值在于:每一层都获得全新的上下文窗口,顶层指令永远不需要阅读内层对话,只有叶子返回的结构化摘要向上爬升,父级上下文因此保持干净。
- 扁平扇出(flat fan-out):
Task× N 一次调用多个子代理,只卸载一层上下文,lead 仍要读完所有摘要; - 嵌套子代理(nested sub-agents):每层可以在自己上下文填满之前,把更深的工作委托给新的窗口——这正是 ruflo 最深的编排者(
ruflo-goals:dossier-investigator、ruflo-sparc:sparc-orchestrator、v3-queen-coordinator)此前遇到的瓶颈。
nested-leaf就是这个模型中的最小工作单元:树的底部。它不做任何派生,只完成一项被分配的任务并返回结构化摘要。
nested-leaf 模板的核心内容
plugins/ruflo-agent/agents/nested-leaf.md的完整 frontmatter 如下:
--- name: nested-leaf description: Leaf-worker template for nested spawn trees — performs one focused task and returns a structured summary. Deliberately does NOT have the Task tool (least-privilege boundary) model: haiku tools: - Read - Grep - Glob - Bash ---注意三个关键点:
model: haiku:叶子只做单一聚焦工作,用轻量模型即可,成本最低;tools仅包含Read、Grep、Glob、Bash:这是最小工具集,足够读取、搜索和操作文件,但没有Task;- 没有任何
Task工具:这是整个模板的设计灵魂,也是与编排者模板最本质的区别。
叶子的三条行为准则
模板正文明确了叶子的行为边界:
- 只做一项被分配的任务。父级用
Task派生你时只给一个单一、有边界的任务,你只做这件事。 - 不做"探索式展开"。如果工作本身需要扇出,父级应该派生多个叶子,而不是让一个叶子自己再扇出。
- 返回结构化摘要而非完整对话记录(约 150–300 tokens)。嵌套的全部意义在于保持父级上下文干净——如果返回大段散文,这次派生就是浪费。
强制的返回结构(LEAF_RESULT)
模板规定叶子必须返回如下形状:
LEAF_RESULT =========== task: <verbatim task your parent gave you> status: <success | partial | failed> result: <the actual answer/output, concise> evidence: - <file:line or command:output> notes: <one line max — anything the parent needs to know that isn't in result>各字段的语义:
| 字段 | 含义 | 说明 |
|---|---|---|
task | 父级给的原样任务文本 | 便于父级与摘要对应,避免歧义 |
status | 执行状态 | 三选一:success/partial/failed |
result | 实际答案/产出 | 要求简洁 |
evidence | 证据列表 | 必须是file:line或command:output形式,可验证 |
notes | 附加说明 | 最多一行,放 result 之外父级必须知道的信息 |
这个形状与nested-coordinator中"每个子节点应返回约 200 tokens 的结构化摘要,而不是工具调用日志"的要求完全一致——结构化摘要就是嵌套通信的最小协议。
为什么叶子不能有 Task 工具
模板给出了三层理由,这也是 ADR-147 P1 的核心决策:
1. 成本归因会被破坏
在 Claude Code 2.1.169 中,嵌套生成的运行时门控是hasTaskTool,它在派生时刻根据父级的工具列表逐次计算。如果父级把Task传给了你,你就会继承它。一旦树中的叶子偷偷派生,AgentDB 里会出现"看似扁平的派生日志、实际是嵌套的真实树"——每份成本报告都会少算。
2. 深度预算被无意识地消耗
Tier-1 叶子"只是想查一下"就悄悄派生,会静默消耗父级根本没有预算的层级。嵌套深度是有限资源(Anthropic API 5 层,ruflo 默认 4 层),必须被有意使用。
3. 混淆代理(confused-deputy)风险
按照 ADR-144 授权传播,每次派生都携带父级的AuthScope。叶子如果能派生,就可能以原始主体从未授权的方式延长作用域链。ADR-144 规定作用域是单调递减的:每一跳只能减少工具/服务器,绝不能增加。叶子再派生意味着作用域链条上多了一环不可控的传播。
因此模板明确规定:如果叶子真的需要派生,不要自己派生,而是带着followups说明返回给父级——父级拥有Task工具,由它决定是否派生后续任务。
源码级的门控证据
ADR-147 对 2.1.169 二进制的实证分析(见 v3/docs/adr/ADR-147-nested-subagent-depth-integration.md)确认了以下事实:
- 运行时门控是布尔值
hasTaskTool(从父级工具列表在派生时刻计算),不是深度计数器,也不是环境变量; - 探测实验显示,即使 YAML 声明了
tools: [Task, Read, Grep, Glob, TodoWrite, Bash](6 个工具),派生子代理实际只继承Read, Grep, Glob, Bash这 4 个——Task和TodoWrite被运行时剥离,且在--permission-mode bypassPermissions、--allowedTools显式授权等各种模式下行为一致; - 结论是:YAML 的
tools:字段确实被加载器接受并传播(恰好 4/6 生效),Task被剥离属于硬编码或服务端 denylist。这意味着当 denylist 解除时,ruflo 的 agent 文件无需任何代码改动即可激活嵌套。
这从底层印证了nested-leaf只声明Read / Grep / Glob / Bash的写法是"声明式正确"的——叶子模板从一开始就按最小权限设计,与运行时的实际行为一致。
深度预算与防护:嵌套体系如何约束叶子
嵌套体系有一套完整的深度预算机制(详见 nested-subagents SKILL):
| 来源 | 上限 |
|---|---|
| Anthropic API | 5 层(2026-06-09 宣布) |
ruflo 默认(pre-task钩子) | 4 层——保留一层余量,可在claude-flow.config.json中配置 |
| 严格模式环境变量 | CLAUDE_FLOW_STRICT_NESTING=true强制执行 ruflo 上限 |
当达到上限时,pre-task钩子返回类型化的NESTING_DEPTH_EXCEEDED错误,payload 中携带完整链,父级可据此决定是汇总、移交还是中止。这个守卫正是 ADR-147 P3 的设计:默认 4 层比 Anthropic 的 5 层少一层,保证 ruflo 的拒绝先于 API 的拒绝触发,且错误信息更清晰。叶子作为第 N 层时,其自身深度已由整条链决定,它不需要、也不应该感知深度——这是父级nested-coordinator通过current_depth=N传参管理的。
何时使用 / 何时不使用
模板自身给出了明确的使用边界:
适用场景:
- 编写一个应当位于树底部的新专家 agent:以本模板为起点,把
nested-leaf改名为你的专家名称; - 需要在一个没有编排职责的 agent 中显式强制最小权限。
不适用场景:
- agent 需要协调子任务——改用
nested-coordinator; - agent 由人类用户顶层直接调用(而非由父 agent 派生)——改用普通平铺 agent 定义(如
coder、tester等)。
与编排者模板的配合:整棵生成树的形状
nested-leaf不是孤立文件,它属于plugins/ruflo-agent/agents/下完整的一套 9 个 agent 模板:
- 编排者(拥有
Task,负责派生):nested-coordinator.md、nested-queen.md、nested-queen-researcher.md、nested-queen-reviewer.md、nested-researcher.md、nested-reviewer.md - 叶子(无
Task,只做事):nested-leaf.md、nested-queen-leaf.md - 另有独立专家模板
wasm-specialist.md
编排者的代表 nested-coordinator 的 frontmatter 是:
--- name: nested-coordinator description: Orchestrator that spawns nested sub-agents (up to depth=5) via Claude Code's native Task tool — for deep delegation where context isolation matters more than throughput model: sonnet tools: - Task - Read - Grep - Glob - TodoWrite - Bash ---两者对比一目了然:
| 维度 | nested-coordinator | nested-leaf |
|---|---|---|
| 角色 | 编排者(树的中间/顶部) | 叶子(树的底部) |
| 模型 | sonnet | haiku |
是否拥有Task | ✅ 是 | ❌ 否 |
| 额外工具 | TodoWrite(先规划树再派生) | 无 |
| 工作方式 | 分解 → 规划 → 派生 → 汇总 | 执行单个任务 → 返回结构化摘要 |
在nested-coordinator的派生规范中,叶子正是它必须遵守的"禁止把Task传给叶子"约束的另一面:coder、tester、pii-detector、security-auditor、aidefence-guardian等叶子 agent 被明确禁止派生。如果树的叶子需要工作,编排者直接通过它们的既有subagent_type派生,而不是"以防万一"再派一个nested-coordinator。
nested-leaf模板提到的可配对编排者还包括nested-researcher/nested-reviewer,以及ruflo-core:coder/ruflo-core:tester(见 plugins/ruflo-core/agents/coder.md)这些"同级叶子"——它们拥有各自的专门提示词,当角色匹配时优先使用它们,只有没有现成叶子匹配时才使用本模板作为起点。
实践路径:如何把模板落成你的叶子 Agent
基于上述设计,落地一个叶子 agent 的推荐流程:
- 复制模板:以
plugins/ruflo-agent/agents/nested-leaf.md为起点,复制为你的专家名(例如pii-detector.md、test-runner.md); - 改写 frontmatter:更新
name与description;model保持轻量(haiku 级别);工具列表保持Read / Grep / Glob / Bash,绝不添加Task——这是最小权限边界的声明式保证; - 改写正文职责:保留"只做一件事、不做探索、返回 LEAF_RESULT"三条准则,把
task语义替换为你的专家职责; - 接入编排树:由
nested-coordinator(或其他声明了tools: [Task, ...]的编排者)通过Task({subagent_type: "<你的叶子名>", ...})派生它; - 遵守深度预算:叶子本身不感知深度;深度由父级通过
current_depth=N传递、由pre-task钩子与CLAUDE_FLOW_STRICT_NESTING=true强制约束。
关联设计文档与验证手段
- ADR-147 嵌套子代理深度集成:本模板的设计依据,含四阶段滚动方案(P1 仅编排者拥有
Task→ P2 从parent_agent_id持久化生成树 → P3 深度感知守卫 → P4 文档与模板对齐),以及 2.1.169 的实证分析; - ADR-144 授权传播:
AuthScope.delegationDepth与嵌套深度共享同一计数器,解释"叶子再派生会延长授权链"的风险; - ADR-099 Dossier Investigator:递归并行研究的教科书用例——树形递归深挖正是嵌套体系的目标场景;
- 验证脚本:
scripts/probe-nested-spawn-depth.mjs是递归深度探针(运行输出见docs/probes/nested-spawn-depth-*.txt),在每次 Claude Code CLI 升级后应首先重跑,一旦返回CAP OBSERVED at depth=N,即意味着嵌套运行时已激活,P2/P3 随之解锁; - 插件烟测:
plugins/ruflo-agent/scripts/smoke.sh是插件契约(12 项结构检查),可验证 agent 文件声明正确。
理解nested-leaf,本质上就是理解嵌套子代理体系的安全底线:树的深度是预算,叶子的职责是执行而非派生,最小权限是声明在 YAML 里的、而不是运行时祈祷来的。把这套模板放进你的编排树底部,你的深层委托才能在上下文隔离、成本归因与授权安全三个维度上同时成立。
【免费下载链接】ruflo🌊 The original agent meta-harness. Deploy intelligent multi-player swarms, coordinate autonomous workflows, and build conversational AI systems. Features adaptive memory, self-learning intelligence, RAG integration, and native Claude Code / Codex / Hermes and many more Integrated项目地址: https://gitcode.com/GitHub_Trending/cl/ruflo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考