给 Agent 增加工具,一开始是一件很愉快的事。
读文件、改文件、跑终端、搜索网页、操作 GitHub、连接 MCP……每增加一种能力,Agent 都像又多长出一只手。
直到手越来越多。
我们开始遇到一个很隐蔽的问题:
工具明明存在,模型却根本没有机会使用它。
这不是 Tool Calling 准确率的问题,也不一定是模型“不够聪明”。
问题发生得更早——在模型开始选择工具之前。
正确的工具,可能根本没有进入它这一轮能够看到的上下文。
这篇文章来自两张连续的研究卡:Desktop #243 和 Desktop #300。前者研究 Progressive Disclosure / Tool Search,后者试图把 Current Mira、Mira Progressive 与 Pi-native Progressive 放进同一套真实模型矩阵。
最后我们得到的答案,比“哪个 Tool Search 算法更强”更基础。
从「选错工具」到「工具不可达」#
Mira 原来的 Tool Exposure 机制很直接。
公共工具数量较小时,把满足条件的工具全部暴露给模型;超过阈值后,再通过 embedding recall 与 rerank 选出一部分候选进入 Planner 上下文。
在工具较少时,这很自然。
问题出现在动态 MCP、大量外部集成和越来越丰富的本地能力加入之后。
当候选工具超过 20 个,一个工具可能同时满足:
- 已经注册;
- Runtime 正常;
- 用户有权限;
- 当前任务确实需要;
但因为没有进入 Top 20,它依然不会出现在模型眼前。
更麻烦的是,当 embedding / reranker 不可用时,旧路径会退化到按注册顺序取 first 20。这个行为是确定性的,却不理解任务。
这时候讨论“模型为什么没有选 GitHub Pull Request Tool”已经没有意义。
因为模型从来没有看见过它。
于是我们开始把几个过去很容易混在一起的状态拆开:
registered
≠ ready
≠ authorized
≠ discoverable
≠ disclosed
≠ executable这后来也与另一条工程线汇合:Runtime Readiness 必须回答“能力现在是否真的可用”,而 Progressive Resolution 只回答“模型现在需要看见多少”。
两者不能互相冒充。
第一次实验:不要一开始就把所有 Schema 塞给模型#
#243 最开始做的事情并不复杂。
我们没有立刻重写生产 Planner,也没有重新造 Harness。
只是问:
模型真的需要在任务开始前看到所有 Tool 的完整 Schema 吗?
一个典型任务其实可以逐层获得信息。
例如用户说:
把刚改完的东西提上去给他们审一下。
模型一开始并不需要 GitHub 所有 Tool 的完整参数定义。
它先知道这里存在一个远端协作能力就够了;确定是 Pull Request 场景以后,再知道对应 Tool;真正准备调用时,才需要 repository、base、head、title、body 等完整 Schema。
于是原来的:
所有候选工具
→ 一批完整 Schema
→ 模型选择可以改成:
紧凑能力目录
→ 找到相关领域
→ 披露 Tool metadata
→ 披露具体 Tool Schema
→ 正常执行我们把这条过程叫作 Progressive Resolution。
这个区别非常重要。
Tool Search 也因此不再是每次任务开始前必须运行的一道检索程序。
如果 Tool 已知,直接展开。
如果领域已经非常明确,做结构化匹配。
只有在巨大、动态、模糊的目录里,才真正 Search。
真模型结果:最大的提升不是「选得更准」,而是「重新变得可达」#
最后的真实模型 closeout 使用相同任务与 Tool Catalog,对比 Current Mira 与 Mira Progressive。
结果是:
| 路线 | 成功 case | gold Tool reachability |
|---|---|---|
| Current Mira | 8 / 16 | 5 / 13 |
| Mira Progressive | 14 / 16 | 13 / 13 |
完整 closeout run 记录在 Control Room run #38049572401。
8 → 14 已经足够显眼,但我们更在意 5 / 13 → 13 / 13。
因为这改变了我们对 Tool Discovery 的理解。
过去我们习惯只问:
模型有没有选中正确 Tool?
但这里其实混合了两个完全不同的问题:
A. 正确 Tool 有没有进入模型的可达空间?
B. 当正确 Tool 可达以后,模型有没有选对?如果 A 已经失败,再拿 B 去责怪模型,没有意义。
所以在后来的 Mira 设计里,Reachability 被提升成了一等指标。
Tool Search 没有想象中那么重要#
另一个很有意思的结果是:
Progressive Resolution 表现更好,并不意味着每个任务都应该先跑 Tool Search。
16 个 closeout case 里,Tool Search 只在 2 个 case 中被使用,而且记录到的 unnecessary search 是 0。
绝大多数任务更适合先走:
exact canonical match
→ capability / domain structural match
→ deterministic lexical resolution
→ genuine ambiguity 时才进入 semantic Resolver这也让我们放弃了一个很诱人的方向:
给 Agent 再加一个特别聪明的 Tool Search 模型,每一步都问它下一步该加载什么。
研究 POC 曾经出现明显的 model-call amplification。
它证明 Progressive Disclosure 这个方向有效,却同时提醒我们:
渐进披露是一个上下文机制,不应该变成一个新的“每一步都问模型”的工作流引擎。
生产方案因此反而更朴素:deterministic first,semantic fallback。
然后我们把 Pi 拉进了同一场实验#
研究走到这里,一个很自然的问题出现了:
既然 Pi Coding Agent 已经有成熟的 deferred tools、active loadout 与 tool_search,我们为什么还要自己做?
于是有了 #300。
我们原本设计了三条严格控制变量的路线:
A. Current Mira
B. Mira Progressive
C. Pi-native Progressive保持相同:
- Main model;
- Tool Catalog;
- gold target;
- authority ceiling;
- evaluation contract;
- Mira Harness / Policy / Evidence。
唯一允许替换的是:
Visibility / Disclosure Backend看起来应该是一张非常漂亮的 A/B/C 成绩表。
但最终 Pi 那一列没有分数。
不是它跑输了。
而是我们发现:Pi 成熟的渐进式工具机制,并不是一个可以从系统里轻易拔出来的独立 Tool Search 库。
Pi 为什么没有进入成绩表#
Pi 的成熟机制更接近一个完整的 AgentSession 生命周期:
- active tool loadout;
- deferred tools;
- tool search;
- session state;
- subsequent-turn tool declaration;
- progressive visibility lifecycle。
而 Mira 当前使用的是更底层、更薄的 Pi Agent Core,并没有采用完整的 pi-coding-agent AgentSession。
如果强行给 Pi 做出一个分数,只有两个办法。
第一个办法是自己写一层 shim,模拟 Pi 的 deferred/loadout/search。
但那测到的是:
Mira 模仿 Pi 的效果。
不是 Pi-native。
第二个办法是把 Pi AgentSession 一起接进来。
这样变化的就不再只有 Visibility Backend,Agent session、状态管理、工具生命周期甚至 Agent loop 的边界都会一起变化,对照实验失去公平性。
所以最终研究记录里写得很克制:
no comparable score was fabricated
没有给 Pi 一个 0 分,也没有拿一个自制 shim 冒充 Pi。
它根本没有进入同一张排行榜。
不复用代码,不代表没有复用设计#
恰恰是在这次对照里,Pi 给了我们很多重要启发:
- Tool 不需要始终 direct exposure;
- Tool Catalog 与完整 Tool Schema 可以分离;
- active tool loadout 本身应该是一种 Agent state;
- Skill 可以 summary-first / body-later;
- Tool Search 是 capability discovery 的组成部分,不是执行权限;
- progressive state 必须能够跨 Agent turn 延续。
我们最后没有复制 Pi AgentSession。
但 Mira 的生产方向明显吸收了这些思想。
最终的结构被收敛为:
Authority / Readiness Envelope
↓
Agent Capability View
↓
Progressive Resolution
/ | \
Tool Skill Resource
metadata summary metadata
↓ ↓ ↓
schema body content
↓
Mira Planner / HarnessMain Agent、Generic Child、Skill Child 各自拥有自己的 scoped Capability View。
这里还有一个重要修正:
Parent 当前看见的 Tool
≠
Child 能够发现的能力上限Child 应该继承 authority / eligibility envelope,再在自己的局部任务里逐步发现与披露。
不能因为 Parent 这一轮恰好没有看见某个工具,就让 Child 永远失去它。
Disclosure 永远不等于 Authority#
整轮研究最后还有一个我们非常坚持的边界。
渐进披露只解决:
模型现在知道什么。
它绝不能变成:
模型现在被允许做什么。
所以无论一个 Tool 是 Search 找出来的、metadata 展开的、schema 动态加载的,还是 Skill 推荐出来的,最终执行仍然必须回到原来的治理链:
Normalize
→ Policy
→ Approval
→ Harness
→ EvidenceCapability View 不发许可证。
Tool Search 也不发许可证。
它们只是改变模型的视野。
少一点「智能」,反而可能更像智能#
这次研究最后让我们重新确认了一条越来越稳定的 Mira 工程原则:
不要因为 Agent 看起来应该更聪明,就在每一层都再塞一个模型。
真正成熟的系统,需要把不同问题拆开。
Runtime Readiness 回答:
这个能力现在到底能不能用?
Authority 回答:
当前用户与任务到底允许不允许?
Progressive Resolution 回答:
模型现在需要知道多少?
Tool Search 回答:
在真的不知道具体 Tool 时,怎么找到它?
Planner 回答:
下一步做什么?
Harness 回答:
怎么执行,并留下可信证据?
这些东西如果全部揉进一个“聪明 Agent”里面,看起来很智能,实际上会越来越难解释,也越来越难治理。
我们最后选择的生产方向反而很薄:
先暴露少量信息
需要时再展开
能确定就不用 Search
能确定性解决就不用模型
权限永远由原来的权限系统决定截至 2026 年 10 月 10 日,研究决策已经完成,生产实现由 Desktop #301 承接,并拆成独立的小步实施与最终验收。
所以这篇文章记录的是一次已经完成的研究与架构决策,不是在宣称 Progressive Resolution 的完整生产链已经全部上线。
有时候,Agent 系统真正需要的不是再多一点智能。
而是让正确的信息,在正确的时候,出现在正确的位置。
