关于 functional-area-resolver
functional-area-resolver 是一种用于压缩 Agent 技能路由表的模式,面向维护大型技能集合的开发者。它将多条技能路由归并为功能领域入口,并通过分发器列表保留子技能的可见性。
主要功能
- 01按功能领域合并路由条目
- 02分发器列表展示可用子技能
- 03提供路由准确性验证流程
- 04包含基于模型的评测方法
适用场景
- 01缩减大型 AGENTS.md 路由表
- 02整理 RESOLVER.md 中的技能入口
- 03压缩后检查意图到技能的路由
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ garrytan/ gbrain --skill functional-area-resolver安装后在 Claude Code 中输入/functional-area-resolver确认已加载。
附带文件routing-eval.jsonl
详细介绍
功能域分发器:压缩路由表的模式
问题
随着技能不断增加,路由文件(RESOLVER.md、AGENTS.md)也越来越大。每个技能各占一行(触发条件 -> 技能路径)。当技能数量达到 200 个以上时,文件大小会达到 25-30KB,占用本应用于实际工作的上下文预算。
解决方案:功能域分发器
用每个功能域一条记录替代每个域的 N 行。每条记录通过 (dispatcher for: ...) 子句列出其可分发到的全部子技能。
之前(270 行,25KB)
- Creating/enriching a person or company page -> `enrich`
- Fix broken citations in brain pages -> `citation-fixer`
- Publish/share a brain page as link -> `brain-publish`
- Generate PDF from brain page -> `brain-pdf`
- Read a book through lens of a problem -> `strategic-reading`
- Personalized book analysis -> `book-mirror`
- Brain integrity -> `brain-librarian`
...
之后(13 行,13KB)
- **Brain & knowledge**: create/enrich/search/export brain pages, filing,
citations, publishing, book analysis, strategic reading, concept synthesis,
archive mining -> `brain-ops` (dispatcher for: enrich, query, brain-pdf,
brain-publish, brain-export, brain-librarian, citation-fixer, book-mirror,
strategic-reading, concept-synthesis, archive-crawler, ...)
为何有效
大模型不需要为每个子技能设置一行。它需要的是:
- 功能域识别:"这与 brain 页面有关" -> Brain & Knowledge
- 子技能可见性:
(dispatcher for: ...)列表展示了可用的选项 - 技能文件本身:大模型读取
brain-ops/SKILL.md后,就能获得完整的路由细节
这是一种两层分发:路由文件负责将请求路由到功能域,功能域技能再将其路由到具体的子技能。每一层各司其职。
A/B 评测结果
在三个 Anthropic 前沿模型(Opus 4.7、Sonnet 4.6、Haiku 4.5)上测试了三种路由架构,使用真实的生产 AGENTS.md 内容,包括 20 个人工编写的训练夹具和 5 个预留的盲测夹具,每个(夹具、变体)组合进行 n=3 的带种子重复实验。采用两种评分规则:STRICT(预测的 slug 与预期完全一致)和 LENIENT(预测结果与预期位于同一分发器功能域内)。两者都很重要:
- STRICT 衡量的是:"大模型是否返回了精确的 slug?"
- LENIENT 衡量的是:"即使大模型从
(dispatcher for: ...)中选择了更具体的子技能,它是否仍落在正确的功能域中?"这更接近生产环境中的行为:对于邮件意图,即使路由条目写的是executive-assistant,落到gmail的 Agent 也算成功。
训练语料(n=20,3 个种子 × 3 个变体 × 3 个模型,LENIENT)
| 变体 | Opus 4.7 | Sonnet 4.6 | Haiku 4.5 | 大小 |
|---|---|---|---|---|
| baseline(270 行项目符号) | 81.7% ± 7.2% | 86.7% ± 7.2% | 73.3% ± 7.2% | 25KB |
| functional-areas(本模式) | 98.3% ± 7.2% | 100% ± 0% | 88.3% ± 7.2% | 13KB |
| resolver-of-resolvers(无分发器子句) | 63.3% ± 14.3% | 41.7% ± 7.2% | 65.0% ± 12.4% | 10KB |
盲测语料(n=5,3 个种子,LENIENT)
| 变体 | Opus 4.7 | Sonnet 4.6 | Haiku 4.5 |
|---|---|---|---|
| baseline | 100% ± 0% | 100% ± 0% | 100% ± 0% |
| functional-areas | 100% ± 0% | 100% ± 0% | 100% ± 0% |
| resolver-of-resolvers | 100% ± 0% | 73.3% ± 28.7% | 100% ± 0% |
数据显示的结果
-
在训练语料上,functional-areas 在三个模型上都优于 baseline(高出 13 至 17 个百分点),而体积仅为其 48%。盲测结果在两者上都已饱和,达到 100%,处于误差范围内。
-
(dispatcher for: ...)子句是起决定作用的信号。 resolver-of-resolvers 去掉了该子句,在 Sonnet 上降至 41.7%,这正是原始 PR 所预测的灾难性失败情形,现已得到验证。 -
该模式之所以有效,是因为大模型能够深入查看分发器列表。 大多数"STRICT 失败"是大模型选择了更具体的子技能(如
gmail而非executive-assistant),这正是模式按设计运作的结果。STRICT 评分会低估结果,而 LENIENT 评分更能反映生产环境中 Agent 的实际表现。 -
该模式的价值随模型层级而提升。 在训练语料上,functional-areas 相对 baseline 的压缩收益(LENIENT)在 Opus 上为 +17 个百分点,在 Sonnet 上为 +13 个百分点,在 Haiku 上为 +15 个百分点。Sonnet 上 functional-areas 与 resolver-of-resolvers 的差距最为明显(100% 对 41.7%),这说明模型能力会影响分发器信号的重要程度。
复现
cd evals/functional-area-resolver
node harness.mjs --model opus # ~225 LLM calls, ~$1.70 at Opus pricing
node harness.mjs --model sonnet # ~$1.00
node harness.mjs --model haiku # ~$0.30
node rescore.mjs baseline-runs/2026-05-11-opus-4-7.jsonl # zero-cost re-score
凭证(model、prompt_template_hash、fixtures_hash、harness_sha、ts):
evals/functional-area-resolver/baseline-runs/2026-05-11-{opus-4-7,sonnet-4-6,haiku-4-5}.jsonl。
方法论注意事项
- 生产提示词很重要。 如果使用简单的"返回技能 slug"提示词(不包含关于
(dispatcher for: ...)的说明),在 Opus 上所有压缩变体的准确率都会降至约 30-60%。支持 dispatcher 的提示词位于evals/functional-area-resolver/harness-runner.ts:PROMPT_TEMPLATE。请将其用作你的 Agent 测试框架模板;否则压缩效果会失效。 - 训练语料与变体由同一版本编写。 保留测试集(held-out corpus)在变体之前编写,且从未调整过;这能缓解但无法彻底消除过拟合。
- 基于 n=3 个带种子重复实验的 t 分布置信区间。 请保持 n=3 的下限:置信区间较大意味着底层样本噪声较多。
- 结果仅来自单一厂商。 三个模型均为 Anthropic。跨厂商验证(Gemini、GPT)是 v0.33.x 的后续工作。
- 盲测集较小(n=5)。 大多数单元格已饱和达到 100%——测试框架无法区分"100%"与"95%,但有一次不确定性失误"。将其扩展至 ≥20 个是 v0.33.x 的后续工作。
已有研究与引用
该模式是层级 Agent 路由的静态提示词类比,属于 2024-2025 年的研究方向:
- AnyTool(arXiv:2402.04253)表明,在 16K 个 API 上,元 Agent → 类别 Agent → 工具 Agent 的层级结构比扁平检索高出 +35.4pp。
(dispatcher for: ...)子句相当于将元 Agent 的视角压缩进单次 LLM 调用中。 - RAG-MCP(arXiv:2505.03275)报告称,通过基于嵌入的预检索,提示词 token 减少 49.2%,准确率提升至 3.2 倍。其 token 削减效果与我们的方案一致(缩小 48%),但机制不同(RAG 与静态 dispatcher)。
- Anthropic Agent Skills(工程博客)提倡渐进式披露:前置元数据(约 80 个 token)始终加载,SKILL.md 正文在匹配时才加载。本技能将同一原则应用于路由表层面,而非单个技能正文层面。
2025-2026 年的文献中尚无关于静态提示词层级路由的公开基准(所有已发表的层级方案都通过第二次 LLM 调用在运行时解析层级)。我们的发现是:层级结构可以内联为单次 LLM 调用的 dispatcher 列表,并保持路由准确率,这是本研究的开放性贡献。方法论细节参见 evals/functional-area-resolver/README.md。
如何压缩
步骤 1:前置条件
若以下任一检查未通过,则拒绝压缩:
- 源路由文件小于 12KB(压缩开销超过收益)。
git status显示路由文件有未提交的更改(压缩器的编辑会与用户正在进行的工作相互干扰)。
如果用户想绕过任一检查,需明确使用 --force 参数。
步骤 2:何时压缩哪个文件
GBrain 工作区通常会在运行时合并两个路由文件(参见 src/core/check-resolvable.ts v0.31.7):skills/RESOLVER.md 以及同级的 ../AGENTS.md。选择压缩哪个文件的规则如下:
- 只有一个文件较大(>12KB):压缩该文件,保留较小的文件不变。
- 两个文件都较大:分别压缩,顺序为先 AGENTS.md(在 OpenClaw 风格的部署中通常更大),再 RESOLVER.md。
- 只有较小的文件较大(罕见):同上规则——压缩它。
如果部署仅使用一个路由文件,则本节无需操作——压缩该文件即可。
Step 3: 划分功能领域
按领域对 Skills 进行分组。常见领域如下(请根据实际部署调整):
- Brain 与知识 — brain-ops 作为调度器
- 内容采集 — ingest 作为调度器
- 日历与日程 — google-calendar 作为调度器
- 邮件与沟通 — executive-assistant 作为调度器
- 研究与调查 — perplexity-research 作为调度器
- X/Twitter 与社交 — x-ingest 作为调度器
- 地点与出行 — checkin 作为调度器
- 产品与构建 — acp-coding 作为调度器
- 基础设施 — healthcheck 作为调度器
- 任务与后勤 — daily-task-manager 作为调度器
- 人物与联系人 — google-contacts 作为调度器
Step 4: 构建领域条目格式
每个领域条目遵循以下模板:
- **{Area Name}**: {comma-separated trigger phrases} -> `{dispatcher-skill}`
(dispatcher for: {comma-separated sub-skill names})
规则:
- 触发短语应足够宽泛,以便捕获用户意图("brain pages、enrich、search、filing、citations、book analysis")
- 子 Skill 列表应尽可能完整,这是 大模型 了解可用能力的途径
- 调度器 Skill 文件应包含其内部路由表
Step 5: 将常驻条目单独保留
Gates 和常驻条目(acknowledge、multi-user、entity-detector 等)应保持为独立行,因为它们在每条消息上都会被检查,而不是被调度。
Step 6(强制):验证路由准确性
在提交压缩后的文件之前,运行两项 Gate。任一项失败则不要提交。
Gate 1:结构验证。 确认你的 routing-eval.jsonl 测试用例在压缩后的路由文件下仍能解析到正确的 Skills。请在你刚刚编辑路由文件的工作区中运行:
gbrain routing-eval --json
如果测试用例的准确率低于 95%,请回滚,并在重新运行前调整领域条目。
Gate 2:对你编辑后文件进行 LLM A/B 验证。 确认前沿 大模型 在你特定的压缩方式下,仍能深入调度器列表并找到子 Skills。此验证需要一个 gbrain 仓库检出副本,因为测试框架位于其中。将你编辑后的路由文件复制到测试框架的 variants 目录,然后使用 --variants 指向该文件来调用测试框架:
# In your agent workspace, identify the routing file you just compressed.
EDITED=/path/to/your/AGENTS.md # or skills/RESOLVER.md, whichever you edited
# In your gbrain repo checkout:
cd /path/to/gbrain/evals/functional-area-resolver
TMP=$(mktemp -d)/variants && mkdir -p "$TMP"
cp "$EDITED" "$TMP/my-edit.md"
# Without --yes the harness prints its cost estimate and exits (no model calls).
ANTHROPIC_API_KEY=... node harness.mjs --variants-dir "$TMP" --variants my-edit \
--model opus --parallel 3
# Only after the user approves that estimate:
ANTHROPIC_API_KEY=... node harness.mjs --variants-dir "$TMP" --variants my-edit \
--model opus --parallel 3 --yes
Gate 2 会产生付费的模型调用。在添加 --yes 之前,请先向用户展示第一条命令打印的费用估算,并获得其同意;--yes 仅跳过测试框架自身的确认提示,并不代表用户的批准。
该测试框架使用 gbrain 自带的测试集,因此它验证的是:"对于 gbrain 自带测试集所覆盖的路由意图,大模型 能否落到正确的子 Skill"——这是对共享 Skills 的回归检查,而不是对你自己测试集的完整重新评估。若需完整的评估覆盖,请镜像本 Skill 的 fixtures.jsonl + fixtures-held-out.jsonl 设置,并使用针对你自身 Skills 的意图。
如果你的 variant 在同领域(lenient)评分上低于 95%,请回滚压缩并调整。常见原因包括:
- 某个子 Skill 被遗漏在
(dispatcher for: ...)列表之外。 - 某个领域的触发短语过窄(大模型 无法识别意图)。
- 领域合并过于激进(领域数量过少——参见反模式)。
- ASCII
->与 Unicode→不匹配——该测试框架现已同时接受两者,但早期版本只匹配 Unicode。请将 gbrain 固定到 v0.32.3.0 或更高版本。
测试框架评估中常见的误判(并非你的压缩存在问题):
- gbrain 自带的测试用例针对的 Skill 名称包括
enrich、query、gmail、executive-assistant。如果你的路由文件根本没有暴露这些 Skills,那么这些测试用例在严格评分下会失败。对于出现在你的(dispatcher for: ...)列表中的任何子 Skill,宽松评分仍然准确。
Step 7: 提交前审查差异
向用户展示拟议的编辑(或实际的 git diff),并在暂存之前等待明确批准。约定与 skills/book-mirror/SKILL.md 相同。
Contract
本技能保证:
- 路由与 frontmatter 中的标准触发词一致。
- 仅当 Step 1 的前提条件满足时才执行压缩(文件 ≥12KB 且工作区干净,或使用
--force)。 - Step 6 中的强制验证关卡作用于用户编辑后的文件,而非示例变体。用户在提交压缩后的文件之前,需要运行
gbrain routing-eval --json以及 gbrain 仓库的 harness(node harness.mjs --variants-dir <tmp> --variants my-edit)。 - 隐私约定得到保持:压缩输出中不泄露任何特定分支的文件系统路径字面量(服务端 brain 主目录、OpenClaw 分支主目录)。
完整的行为约定记录在上方各节中;本节仅用于一致性测试。
Output Format
压缩后的路由文件遵循 Step 4("构建功能区条目格式")中记录的功能区条目模板。每个条目的格式为:- **{Area Name}**: {trigger phrases} -> \{dispatcher-skill}` (dispatcher for: {sub-skill list})。分派箭头既可以是 ASCII ->(本模板的默认写法),也可以是 Unicode →`(部分生产部署中使用);gbrain harness 两种写法均接受。
When it fails
对于任何 gbrain 错误 code、退出码、[AGENT] 块或提示块,请遵循 agent operator protocol。针对本技能的具体情况:
- 任一验证关卡失败(结构性或 LLM A/B):拒绝压缩,并报告失败的关卡;绝不发布路由效果更差的较小 resolver。
- A/B harness 缺少 provider 密钥或触及成本上限:说明 LLM 关卡未运行,并保留原始 resolver。
Anti-Patterns
-
使用管道表的 resolver-of-resolvers。 已测试且失败(参见评估表)。LLM 会从表格中挑选功能区名称,而不是深入到子技能。
-
删除子技能名称。 没有
(dispatcher for: ...)列表,LLM 就无法路由到具体的子技能。该列表即是路由信号。 -
功能区过少。 合并到不足 5 个功能区会使每个功能区过于宽泛。12–15 个功能区是最佳平衡点。
-
功能区过多。 这会违背初衷。如果有 50 个功能区,不如直接保留各个独立条目。
Maintenance
添加新技能时:
- 确定其所属的功能区。
- 将技能名称添加到该功能区的
(dispatcher for: ...)列表中。 - 更新该功能区的技能文件,补充路由细节。
- 运行路由评估(Step 6)进行验证。
添加新的功能区时:
- 创建带有内部路由的分派技能。
- 在路由文件中添加该功能区条目。
- 运行路由评估(Step 6)进行验证。
Changelog
v1.0.0 — 2026-05-11
- 初始版本。该模式随 gbrain v0.32.3.0 发布,并附带留出集 A/B 评估(参见
evals/functional-area-resolver/)。 - 在正式发布前,技能从
compress-agents-md更名为functional-area-resolver;此次贡献的是模式,而非文件名。