智能体能力管理架构解析
1. 文档目的
本文描述一种面向智能体 Harness 的能力管理架构,用于解决以下问题:
-
系统长期积累大量脚本、操作配方、API、知识说明和工具后,如何避免一次性向模型暴露过多工具。
-
模型如何根据用户的自然语言目标,找到正确的能力。
-
如何按需向模型披露具体工具的参数 Schema。
-
如何在保持统一执行入口的同时,对每个具体动作实施独立的权限、风险、确认和审计控制。
-
多种检索方式如何通过并行分发、结果汇聚、融合和重排形成最终候选。
该架构不应被简单理解为传统“知识库智能体”。更准确的定义是:
分层能力注册表(Capability Registry)
渐进式能力披露(Progressive Capability Disclosure)
并行能力检索(Parallel Capability Retrieval)
受控动作执行(Governed Action Execution)
原始设想中的“领域—范围—工具”可以分别映射为能力包、子能力包和叶子动作,而 README、INDEX、DESCRIBE 等内容则承担局部操作指引、使用边界和能力摘要的职责。
2. 问题背景
在小型智能体中,可以直接向模型提供少量工具,例如:
read
edit
bash
schedule_create
weather_query
但当系统不断积累以下内容时,工具集合会快速膨胀:
-
Codex、npm、Conda 等本地环境维护命令。
-
自建应用的业务 API。
-
日程、出行、用户资料等服务接口。
-
故障诊断经验和操作步骤。
-
封装后的固定 Bash 或 Python 脚本。
-
发布、删除、更新等高风险动作。
如果每轮请求都把所有工具 Schema 发送给模型,会产生以下问题:
-
上下文占用不断扩大。
-
相似工具之间更容易发生误选。
-
模型需要理解大量与当前任务无关的参数。
-
工具更新后,Schema 管理成本上升。
-
高风险能力被无差别暴露。
-
工具数量增长后,调用准确率可能下降。
因此需要将能力组织成层级注册表,只在需要时披露相关能力。
3. 核心概念
3.1 Capability Pack
Capability Pack 是一组相关能力的逻辑集合。
例如:
maintenance
├── codex
├── npm
├── python
└── docker
其中:
maintenance.codex
可以包含:
maintenance.codex.status
maintenance.codex.diagnose
maintenance.codex.update
maintenance.codex.path_repair
maintenance.codex.rollback
能力包主要用于:
-
组织能力。
-
限定搜索范围。
-
提供局部规则。
-
描述该领域的操作惯例。
-
控制能力的整体启用和禁用。
3.2 Action
Action 是一个可以直接执行的叶子动作。
例如:
maintenance.codex.diagnose
maintenance.codex.update
myapp.schedule.create
每个 Action 必须拥有独立定义,包括:
action_id:
version:
title:
summary:
when_to_use:
when_not_to_use:
arguments_schema:
handler:
side_effect:
risk_level:
acl:
requires_confirmation:
timeout:
network_policy:
output_schema:
即使模型侧只看到统一的 capability::run,宿主系统内部也必须保留每个 Action 的独立 Schema、权限和执行合同。
3.3 Recipe / Skill
Recipe 或 Skill 是操作知识,而不是独立执行动作。
适合表示:
-
故障排查步骤。
-
命令组合建议。
-
使用现有 Bash、Read、Edit 完成任务的方法。
-
很少使用且不值得独立封装的操作流程。
例如:
maintenance.codex.path_conflict_guide
它可以告诉模型:
1. 执行 type -a codex。
2. 检查 npm prefix -g。
3. 对比 npm 全局包版本和实际启动版本。
4. 分别检查 Bash 与 Fish 的 PATH。
3.4 元工具
系统常驻的不是所有业务工具,而是一组少量元工具:
capability::search
capability::list
capability::describe
capability::run
其中:
-
search:根据目标搜索能力。 -
list:浏览某个能力包。 -
describe:获取某个能力的完整调用合同。 -
run:执行已注册动作。
4. 为什么统一执行工具需要能力发现系统
假设模型原本直接看到:
{
"name": "maintenance_codex_update",
"description": "使用受控 npm 流程更新 Codex CLI",
"parameters": {
"type": "object",
"properties": {
"channel": {
"type": "string",
"enum": ["stable", "latest"]
},
"dry_run": {
"type": "boolean"
}
},
"required": ["channel"]
}
}
模型可以直接知道:
-
该动作存在。
-
动作用于什么场景。
-
参数名称和类型。
-
参数枚举范围。
-
哪些参数必填。
如果将所有动作统一隐藏在:
capability::run(action_id, arguments)
后面,模型初始只知道存在一个统一执行通道,却不知道:
-
可用的
action_id有哪些。 -
应选择 diagnose、update 还是 rollback。
-
arguments应包含哪些字段。 -
哪个动作会产生写操作。
-
哪个动作需要用户确认。
因此,万能工具减少了表面工具数量,但同时隐藏了 leaf tool 的 Schema。
必须通过 search / list / describe 恢复以下信息:
-
可发现性。
-
参数说明。
-
适用与不适用条件。
-
示例。
-
风险级别。
-
权限和环境要求。
否则系统只是把几十个工具名变成了几十个需要模型记忆的字符串 ID。
5. Capability Search 的职责
capability::search 的定义应当是:
在当前用户、当前环境、当前权限和当前任务约束下,从能力注册表中召回并排序一组可能适用的能力,供模型下一步选择。
它不负责:
-
直接执行动作。
-
返回所有完整 Schema。
-
代替权限校验。
-
直接生成最终用户答案。
它负责:
-
理解当前搜索目标。
-
选择适当的检索通道。
-
并行召回候选。
-
汇聚不同检索器的证据。
-
过滤不可发现或不可用能力。
-
融合候选排名。
-
根据风险、上下文和使用边界重排。
-
返回少量候选摘要。
6. Search 请求协议
推荐的工具定义如下:
{
"name": "capability_search",
"description": "根据当前目标搜索可用的能力包、动作和操作配方,不执行任何动作。",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "当前任务目标,应尽量包含对象、问题、限制和期望结果。"
},
"within": {
"type": "string",
"description": "可选,限制搜索范围,例如 maintenance.codex。"
},
"types": {
"type": "array",
"items": {
"type": "string",
"enum": ["pack", "action", "recipe"]
}
},
"side_effect_max": {
"type": "string",
"enum": ["R", "W-local", "W-shared", "I"]
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 10,
"default": 5
}
},
"required": ["query"],
"additionalProperties": false
}
}
调用示例:
{
"query": "Codex 更新后仍然启动旧版本,先检查 npm 全局安装路径和 Shell PATH 冲突",
"within": "maintenance.codex",
"types": ["action", "recipe"],
"side_effect_max": "W-local",
"limit": 5
}
7. 能力注册表设计
搜索质量首先取决于能力元数据,而不是向量模型。
一个 Action 的推荐定义如下:
action_id: maintenance.codex.diagnose
version: 3
resource_type: action
title: 诊断 Codex 安装与路径冲突
summary: >
检查当前实际启动的 Codex 可执行文件、版本、
npm 全局安装目录、npm 已安装版本以及 Shell PATH 优先级。
aliases:
- codex 更新后还是旧版本
- codex path 冲突
- npm 安装版本与运行版本不同
intents:
- diagnose
- inspect
- verify
entities:
- codex
- npm
- path
- bash
- fish
symptoms:
- active_version_mismatch
- multiple_executables
- npm_prefix_mismatch
when_to_use:
- 更新后实际运行版本仍然较旧
- type -a codex 显示多个路径
- npm 全局版本与当前执行版本不一致
when_not_to_use:
- 用户已经明确要求回滚
- 已确认问题与 PATH 无关
- Codex 并非通过 npm 安装
supported_os:
- linux
- macos
required_executors:
- shell
- npm
side_effect: R
risk_level: low
requires_confirmation: false
produces:
- active_binary
- active_version
- installed_npm_version
- npm_prefix
- path_conflicts
tags:
- maintenance
- codex
- npm
- cli
其中最重要的字段是:
-
aliases:用户可能如何表达。 -
intents:用户想完成什么。 -
entities:涉及什么对象。 -
symptoms:用户观察到什么现象。 -
when_to_use:正向使用边界。 -
when_not_to_use:排除条件。 -
side_effect:动作副作用。 -
required_context:环境是否满足。
8. Search 总体架构
能力搜索适合采用典型的 Fan-out / Fan-in 架构:
┌─ Exact Retriever ──────┐
├─ Lexical Retriever ────┤
Query → Search Planner ──┼─ Semantic Retriever ──┼→ Gather
├─ Metadata Retriever ───┤
├─ Hierarchy Retriever ──┤
└─ History Retriever ────┘
Gather
↓
Policy Filter
↓
Fusion
↓
Rerank
↓
Diversification
↓
Top-K Candidates
完整流程为:
请求校验
→ 查询规范化
→ 搜索计划生成
→ 并行分发 Retriever
→ 汇聚候选和证据
→ 权限与环境过滤
→ 多路排名融合
→ 策略感知重排
→ 多样性控制
→ 置信度判断
→ 返回 Top 3~5
9. Query Normalizer
Query Normalizer 将自然语言目标转换为结构化搜索意图。
输入:
刚更新了 Codex,但 codex --version 还是旧版本,先检查原因,不要直接重装。
输出:
{
"intents": ["diagnose"],
"entities": ["codex"],
"symptoms": ["active_version_mismatch"],
"constraints": ["read_first"],
"forbidden_intents": ["reinstall", "update"],
"desired_outcome": "定位实际运行版本与安装版本不一致的原因"
}
Normalizer 可以由以下方式组合实现:
规则识别明确实体和强约束
+
别名词典识别领域术语
+
必要时使用 LLM 做结构化解析
早期 MVP 不必每次调用 LLM。对于 Codex、npm、PATH、Fish 等明确实体,规则和词典通常足够。
10. Search Planner
Search Planner 根据查询特征决定启动哪些 Retriever。
并行并不意味着每次都执行所有检索器。
明确 Action ID
查询:
maintenance.codex.diagnose
计划:
Exact Retriever
Metadata Retriever
模糊自然语言问题
查询:
我明明升级了,为什么运行出来还是旧的?
计划:
Lexical Retriever
Semantic Retriever
Metadata Retriever
History Retriever
能力浏览请求
查询:
Codex 维护相关能力有哪些?
计划:
Hierarchy Retriever
Metadata Retriever
示例:
def build_search_plan(query: ParsedQuery) -> SearchPlan:
if query.explicit_resource_id:
return SearchPlan(
retrievers=("exact", "metadata")
)
if query.scope and query.is_browse_request:
return SearchPlan(
retrievers=("hierarchy", "metadata")
)
retrievers = ["lexical", "metadata"]
if query.needs_semantic_matching:
retrievers.append("semantic")
if query.use_history:
retrievers.append("history")
return SearchPlan(retrievers=tuple(retrievers))
11. Retriever 设计
11.1 Exact Retriever
负责精确匹配:
-
完整
action_id。 -
action ID 前缀。
-
固定别名。
-
唯一标识。
例如:
maintenance.codex.update
schedule_create
codex_diagnose
精确命中通常应获得最高权重。
11.2 Lexical Retriever
负责关键词和全文检索:
-
标题。
-
摘要。
-
aliases。
-
entities。
-
symptoms。
-
tags。
-
when_to_use。
适合使用:
-
SQLite FTS5。
-
PostgreSQL 全文检索。
-
Elasticsearch BM25。
-
本地倒排索引。
专有名词如 Codex、npm、Fish、AuraTrip 不应只依赖向量召回。
11.3 Semantic Retriever
负责语义近似表达。
例如用户说:
安装明明成功了,但真正执行的好像不是新版本。
即使未出现 PATH shadowing,也应召回:
maintenance.codex.diagnose
maintenance.codex.path_repair
用于 Embedding 的索引文本应包含正反使用边界:
动作:诊断 Codex 安装与路径冲突
用于:
- 更新后仍显示旧版本
- npm 安装版本与实际运行版本不同
- 存在多个 Codex 可执行路径
不用于:
- 单纯执行更新
- 回滚指定版本
11.4 Metadata Retriever
负责结构化字段匹配:
intent = diagnose
entity = codex
symptom = active_version_mismatch
side_effect = R
它通常比纯语义检索更稳定。
11.5 Hierarchy Retriever
负责能力树和范围检索:
within = maintenance.codex
只召回:
maintenance.codex.*
同时可以返回:
-
父能力包。
-
子动作。
-
相邻能力。
-
路径深度。
11.6 History Retriever
负责召回:
-
当前用户过去成功使用的动作。
-
当前项目常用能力。
-
最近加载的能力包。
-
相似任务中的成功路径。
历史只能作为弱信号,不能覆盖权限、当前语义和风险判断。
12. 并行 Dispatcher
Retriever 应通过统一 Dispatcher 并行执行。
from __future__ import annotations
import asyncio
from dataclasses import dataclass
from typing import Protocol
@dataclass(frozen=True)
class RetrievalHit:
resource_id: str
rank: int
score: float | None
source: str
matched_fields: tuple[str, ...] = ()
@dataclass(frozen=True)
class RetrievalContext:
query: str
scope: str | None
user_id: str
limit_per_source: int = 20
class Retriever(Protocol):
name: str
async def retrieve(
self,
context: RetrievalContext,
) -> list[RetrievalHit]:
...
class SearchDispatcher:
def __init__(
self,
retrievers: dict[str, Retriever],
timeout_seconds: float = 1.0,
) -> None:
self._retrievers = retrievers
self._timeout_seconds = timeout_seconds
async def dispatch(
self,
retriever_names: tuple[str, ...],
context: RetrievalContext,
) -> dict[str, list[RetrievalHit]]:
coroutines = [
asyncio.wait_for(
self._retrievers[name].retrieve(context),
timeout=self._timeout_seconds,
)
for name in retriever_names
]
raw_results = await asyncio.gather(
*coroutines,
return_exceptions=True,
)
results: dict[str, list[RetrievalHit]] = {}
for name, result in zip(
retriever_names,
raw_results,
strict=True,
):
if isinstance(result, BaseException):
results[name] = []
else:
results[name] = result
return results
每个 Retriever 应配置独立超时,并支持部分成功。
示例:
Exact:50 ms
Metadata:100 ms
Lexical:200 ms
Semantic:500 ms
History:300 ms
不能因为 Semantic Retriever 超时而使整个能力搜索失败。
13. Gather 阶段
Gather 不是简单拼接列表。
它至少需要完成以下工作。
13.1 统一结果格式
不同检索器分数不可直接比较:
-
BM25 是全文分数。
-
向量检索是相似度。
-
Metadata 是规则命中。
-
Hierarchy 是路径关系。
-
History 是使用频率。
因此统一保留排名和原始证据:
@dataclass(frozen=True)
class CandidateEvidence:
source: str
rank: int
raw_score: float | None
matched_fields: tuple[str, ...]
@dataclass
class GatheredCandidate:
resource_id: str
evidence: list[CandidateEvidence]
13.2 按 resource_id 去重
以下结果:
Lexical → maintenance.codex.diagnose
Semantic → maintenance.codex.diagnose
Metadata → maintenance.codex.diagnose
应聚合为一个候选,并保留三份召回证据。
13.3 保留来源证据
{
"resource_id": "maintenance.codex.diagnose",
"evidence": [
{
"source": "lexical",
"rank": 1,
"matched_fields": ["aliases", "symptoms"]
},
{
"source": "semantic",
"rank": 2,
"raw_score": 0.89
},
{
"source": "metadata",
"rank": 1,
"matched_fields": ["intent", "entity"]
}
]
}
这些证据可用于:
-
解释命中原因。
-
调试检索质量。
-
离线评估。
-
调整权重。
-
生成可观测日志。
13.4 控制候选规模
例如:
每路 Top 20
→ 最多 100 条原始结果
→ 去重后保留 Top 30
→ 进入精排
→ 最终返回 Top 5
14. Policy Filter
权限过滤应分成两层。
14.1 召回前硬过滤
适合处理:
-
租户隔离。
-
禁止发现的高敏感动作。
-
disabled action。
-
明确不支持当前操作系统。
-
明确超出
within范围。
14.2 Gather 后统一过滤
适合处理:
-
当前执行权限。
-
Feature Flag。
-
动态依赖状态。
-
凭据是否存在。
-
当前环境是否满足。
-
版本是否兼容。
-
当前预算是否允许。
安全判断最终必须由统一 Policy Service 再执行一次,不能只相信 Retriever 已正确过滤。
权限还应区分:
discover permission
describe permission
execute permission
模型可以知道某个能力存在,不代表能够查看完整参数;能够查看参数,也不代表能够执行。
15. Fusion
Fusion 回答的问题是:
多个 Retriever 综合认为,哪些候选最相关?
由于不同检索器的分数空间不同,第一版建议使用 Weighted Reciprocal Rank Fusion。
公式:
FusionScore(d)
=
Σ source_weight(i) / (k + rank_i(d))
示例权重:
SOURCE_WEIGHTS = {
"exact": 2.0,
"metadata": 1.4,
"lexical": 1.2,
"semantic": 1.0,
"hierarchy": 0.8,
"history": 0.4,
}
实现:
def weighted_rrf(
candidate: GatheredCandidate,
k: int = 60,
) -> float:
return sum(
SOURCE_WEIGHTS[evidence.source]
/ (k + evidence.rank)
for evidence in candidate.evidence
)
History 权重应保持较低,防止系统因过去经常使用某个动作而形成强化偏差。
16. Rerank
Rerank 回答的问题是:
在当前任务、环境和风险约束下,哪个候选最适合作为下一步?
Rerank 可以考虑:
intent match
entity match
symptom match
when_to_use
when_not_to_use
side effect
risk level
environment fit
permission state
current workflow stage
historical reliability
示例:
用户:先检查原因,不要直接更新。
候选:
maintenance.codex.diagnose
maintenance.codex.path_repair
maintenance.codex.update
重排规则应使:
diagnose > path_repair > update
其中 update 虽然语义相关,但命中了用户的禁止约束和自身的 when_not_to_use,因此需要明显降权。
示例评分:
FinalScore
=
FusionScore
+ IntentMatch
+ EntityMatch
+ SymptomMatch
+ ContextFit
- RiskPenalty
- NegativeUsagePenalty
Fusion 和 Rerank 的职责必须分开:
Fusion:多路检索认为它是否相关
Rerank:当前任务中它是否合适
17. 风险模型
建议统一使用以下副作用等级:
|
等级 |
含义 |
示例 |
|---|---|---|
R |
只读 |
查询版本、列出日程 |
W-local |
修改本地环境 |
安装工具、修改 PATH |
W-shared |
修改远端或共享数据 |
创建业务日程、更新团队数据 |
I |
高影响或不可逆 |
删除、发布、付款、外发 |
当用户目标不明确时,默认排序应偏向:
R
> 可逆 W-local
> W-shared
> I
当用户明确要求写操作时,不应因风险等级完全压制正确动作。
风险控制不是万能工具级别的统一权限,而应在解析 action_id 后,针对叶子动作执行。万能的只能是执行通道,不能是权限。
18. Diversification
搜索结果不能全部是同一类动作。
例如以下五个结果价值较低:
codex.update.stable
codex.update.latest
codex.update.specific
codex.update.force
codex.update.reinstall
建议加入以下多样性规则:
-
同一父能力包最多返回 3 个。
-
同一主要意图最多返回 2 个。
-
模糊查询至少保留一个只读动作。
-
高风险动作不能占满候选。
-
当多个 leaf action 得分接近时,可返回父 Pack。
示例:
def diversify(
ranked: list[RankedCandidate],
limit: int,
) -> list[RankedCandidate]:
selected = []
parent_count: dict[str, int] = {}
intent_count: dict[str, int] = {}
for item in ranked:
if parent_count.get(item.parent_id, 0) >= 3:
continue
if intent_count.get(item.primary_intent, 0) >= 2:
continue
selected.append(item)
parent_count[item.parent_id] = (
parent_count.get(item.parent_id, 0) + 1
)
intent_count[item.primary_intent] = (
intent_count.get(item.primary_intent, 0) + 1
)
if len(selected) >= limit:
break
return selected
19. 置信度与模糊处理
搜索系统不能在低置信度情况下硬选一个动作。
查询:
帮我处理一下开发环境。
可能同时匹配:
maintenance.codex
maintenance.python
maintenance.npm
maintenance.docker
此时应返回 Pack 级候选或标记为模糊:
{
"resolution": "ambiguous",
"matches": [
{
"resource_type": "pack",
"resource_id": "maintenance.codex"
},
{
"resource_type": "pack",
"resource_id": "maintenance.python"
}
]
}
可区分:
confident
ambiguous
no_confident_match
阈值必须通过真实日志和离线评估校准,而不是长期写死。
20. Search 返回协议
Search 只返回候选摘要,不返回完整参数 Schema。
{
"query": "Codex 更新后仍启动旧版本,先检查 PATH 冲突",
"scope": "maintenance.codex",
"resolution": "confident",
"matches": [
{
"rank": 1,
"resource_type": "action",
"resource_id": "maintenance.codex.diagnose",
"title": "诊断 Codex 安装与路径冲突",
"summary": "检查活动二进制、版本、npm prefix 和 Shell PATH。",
"matched_entities": ["codex", "npm", "path"],
"matched_intents": ["diagnose"],
"matched_symptoms": ["active_version_mismatch"],
"side_effect": "R",
"risk_level": "low",
"requires_confirmation": false,
"availability": "available",
"score": 0.94,
"next_step": {
"tool": "capability_describe",
"arguments": {
"resource_id": "maintenance.codex.diagnose"
}
}
}
],
"search_meta": {
"planned_retrievers": [
"lexical",
"semantic",
"metadata"
],
"completed_retrievers": [
"lexical",
"semantic",
"metadata"
],
"candidate_count": 17,
"returned_count": 3,
"partial": false
}
}
21. Describe 与动态 Schema 披露
模型选中候选后调用:
{
"action_id": "maintenance.codex.diagnose"
}
describe 返回:
{
"action_id": "maintenance.codex.diagnose",
"version": 3,
"summary": "检查 Codex 安装、版本和路径冲突。",
"when_to_use": [
"更新后仍显示旧版本",
"存在多个可执行路径"
],
"when_not_to_use": [
"已明确要求回滚"
],
"arguments_schema": {
"type": "object",
"properties": {
"include_shell_resolution": {
"type": "boolean",
"default": true
},
"include_registry_check": {
"type": "boolean",
"default": true
}
},
"additionalProperties": false
},
"side_effect": "R",
"requires_confirmation": false
}
随后可以选择两种执行方式。
方式一:统一 Run
{
"action_id": "maintenance.codex.diagnose",
"action_version": 3,
"arguments": {
"include_shell_resolution": true,
"include_registry_check": true
}
}
方式二:动态注册 Leaf Tool
Harness 在下一次模型请求中加入真实工具:
maintenance__codex_diagnose
方式二的参数 Schema 更清晰,更适合 API 和高风险动作;方式一更适合稳定脚本和中低风险注册动作。
22. 完整执行 Loop
用户请求:
Codex 更新后还是旧版本,帮我检查并修好。
Round 1:Search
{
"query": "Codex 更新后仍启动旧版本,检查 npm prefix 和 PATH 冲突",
"within": "maintenance.codex"
}
返回:
1. maintenance.codex.diagnose
2. maintenance.codex.path_repair
3. maintenance.codex.update
Round 2:Describe Diagnose
模型获得诊断动作的详细 Schema。
Round 3:Run Diagnose
返回:
{
"active_binary": "/home/user/.local/bin/codex",
"active_version": "0.141.0",
"installed_binary": "/home/user/.npm-global/bin/codex",
"installed_version": "0.144.6",
"issue": "PATH shadowing",
"recommended_actions": [
"maintenance.codex.path_repair"
]
}
Round 4:Describe Path Repair
获取修改范围、参数和风险。
Round 5:Confirmation
Harness 返回:
{
"status": "confirmation_required",
"summary": "将调整 Bash 和 Fish 的 PATH 优先级。",
"affected_resources": [
"~/.bashrc",
"~/.config/fish/config.fish"
],
"confirmation_token": "confirm-abc123"
}
Round 6:Run Path Repair
完成修复并验证:
type -a codex
codex --version
npm list -g @openai/codex --depth=0
完整链路为:
Search
→ Describe
→ Run
→ Observe
→ Search/Describe next action
→ Confirm
→ Run
→ Verify
23. 推荐代码模块
capabilities/
├── models.py
├── registry.py
├── indexer.py
├── query_normalizer.py
├── search_planner.py
├── search_dispatcher.py
├── gatherer.py
├── policy_filter.py
├── fusion.py
├── reranker.py
├── diversifier.py
├── search_service.py
├── describe_service.py
├── action_executor.py
└── retrievers/
├── exact.py
├── lexical.py
├── semantic.py
├── metadata.py
├── hierarchy.py
└── history.py
Search Service 主流程:
class CapabilitySearchService:
async def search(
self,
request: CapabilitySearchRequest,
runtime_context: RuntimeContext,
) -> CapabilitySearchResult:
parsed_query = self.query_normalizer.normalize(
request.query,
runtime_context,
)
plan = self.search_planner.plan(
request=request,
parsed_query=parsed_query,
runtime_context=runtime_context,
)
retrieval_results = await self.dispatcher.dispatch(
retriever_names=plan.retrievers,
context=RetrievalContext(
query=request.query,
scope=request.within,
user_id=runtime_context.user_id,
),
)
gathered = self.gatherer.gather(
retrieval_results
)
allowed = self.policy_filter.filter(
gathered,
runtime_context=runtime_context,
)
fused = self.fusion.fuse(allowed)
reranked = self.reranker.rerank(
candidates=fused,
parsed_query=parsed_query,
runtime_context=runtime_context,
)
selected = self.diversifier.select(
reranked,
limit=request.limit,
)
return self.result_builder.build(
request=request,
plan=plan,
retrieval_results=retrieval_results,
candidates=selected,
)
24. MVP 实施建议
第一阶段不必立即引入向量数据库。
推荐 MVP:
YAML / JSON Capability Registry
+
Exact Retriever
+
SQLite FTS5 Lexical Retriever
+
Metadata Retriever
+
Hierarchy Retriever
+
asyncio.gather
+
Weighted RRF
+
规则 Rerank
第一阶段实现:
capability_search
capability_describe
capability_run
第二阶段再增加:
Semantic Retriever
History Retriever
动态 Leaf Tool 注册
学习排序
搜索质量评估
初始检索流程:
1. 校验请求。
2. 解析 scope、实体、意图、症状和约束。
3. Search Planner 选择 Retriever。
4. 并行执行 Exact、Lexical、Metadata、Hierarchy。
5. 按 resource_id 汇聚并去重。
6. 执行权限和环境过滤。
7. 使用 Weighted RRF 融合。
8. 根据 when_to_use、when_not_to_use、风险和上下文重排。
9. 执行多样性控制。
10. 返回 3~5 个候选。
11. 模型选中候选后调用 describe。
25. 评估指标
能力搜索应建立独立测试集。
每条测试样本至少包含:
query:
runtime_context:
expected_top_actions:
forbidden_actions:
expected_resolution:
建议关注:
检索指标
-
Recall@K。
-
MRR。
-
NDCG@K。
-
Top-1 Accuracy。
-
正确 Pack 命中率。
安全指标
-
无权限能力泄露率。
-
高风险动作误排 Top-1 的比例。
-
when_not_to_use违反率。 -
未确认写操作执行率。
系统指标
-
P50/P95 搜索延迟。
-
各 Retriever 超时率。
-
部分降级成功率。
-
平均候选数量。
-
平均披露 Schema 大小。
业务指标
-
Search 后正确 Describe 的比例。
-
Describe 后正确 Run 的比例。
-
用户澄清次数。
-
动作执行成功率。
-
错误动作撤销率。
26. 常见错误
错误一:把 Search 做成普通文档 RAG
能力搜索不仅是语义相似度,还必须考虑:
-
权限。
-
环境。
-
副作用。
-
使用边界。
-
当前流程阶段。
错误二:只依赖 Embedding
专有名词、Action ID、枚举值和明确症状通常更适合关键词和结构化检索。
错误三:Search 直接返回完整 Schema
Search 应返回候选摘要,Describe 才返回单个候选的完整 Schema,否则候选一多,上下文仍会膨胀。
错误四:统一 Run 使用统一权限
权限必须在解析 action_id 后按叶子动作判断。
正确顺序:
解析 action_id
→ 读取 ActionDefinition
→ 校验版本
→ 校验参数
→ ACL
→ 风险判断
→ 确认
→ 执行
错误五:并行等于无条件调用所有 Retriever
应由 Search Planner 根据任务选择检索通道。
错误六:Gather 只是数组合并
Gather 必须去重、保留来源证据、限制候选数量,并为 Fusion 提供统一结构。
错误七:历史使用频率权重过高
历史是弱信号,不能让系统不断推荐过去使用过但当前不适用的动作。
27. 设计结论
这套系统的核心不是减少注册表中的能力数量,而是减少每轮向模型暴露的能力数量。
推荐总体模式:
少量常驻核心工具
↓
Search Planner
↓
并行 Retriever Fan-out
↓
Gather / Policy / Fusion / Rerank
↓
少量候选摘要
↓
Describe 单个能力
↓
统一 Run 或动态 Leaf Tool
↓
叶子级权限、确认和审计
各组件职责可以概括为:
Registry:定义系统拥有什么能力
Retriever:负责找得到
Gatherer:负责聚合证据
Fusion:负责合得起来
Reranker:负责选得正确
Policy:负责能不能发现和使用
Describe:负责披露准确合同
Executor:负责安全执行
最终形成的不是传统知识库,而是一个:
可搜索、可解释、可校验、可授权、可审计,并支持渐进式披露的个人能力插件系统。
对于操作经验、包装脚本和业务 API 混合存在的场景,建议采用:
Recipe / Skill
+
注册动作执行器
+
动态 Typed Leaf Tool
+
受控 Raw Bash
其中:
-
普通经验放入 Recipe。
-
稳定包装脚本放入注册动作执行器。
-
API 和高风险操作使用独立 Typed Tool。
-
Raw Bash 仅作为强沙箱和确认机制下的兜底能力。
这种混合方案既保留了 Harness 的通用性,又避免将所有异构动作伪装成无约束字符串参数。
更多推荐


所有评论(0)