@studyzy/pi-lazy-tools
v0.1.0
Published
CodeBuddy-style deferred tools for pi: ToolSearch + DeferExecuteTool. Deferred tool schemas stay out of the prompt until the LLM loads them on demand.
Maintainers
Readme
pi-lazy-tools
为 pi 打造的 CodeBuddy 风格延迟工具(deferred tools)方案。
通过 tool_search + defer_execute_tool 工具对,把工具 Schema 挡在上下文之外,
直到模型真正需要时再加载。
降低 token 消耗 · 压缩上下文窗口 · 保持工具可发现
它能做什么
大多数 coding agent 会把所有可用工具的 JSON Schema 塞进 prompt——哪怕是
模型最终根本不会用到的工具。pi-lazy-tools 反其道而行之:工具默认被
延迟(defer),只有模型主动索要时才进入上下文。
被延迟的工具会从活动工具列表中移除,因此它们的 Schema(甚至名称)不会进入
模型上下文。模型通过 tool_search 按需发现它们,激活后再直接调用。
这是一个纯粹的暴露控制层(exposure-control layer):
- 它不拥有、也不实现任何工具。
- 被延迟的工具是 pi 内置工具或其他扩展提供的工具;本扩展仅为发现之用途
保存它们的
name/description/parameters。 - 它不能代理执行——pi 的扩展 API 不暴露外部工具的
execute函数。tool_search/defer_execute_tool只是激活找到的工具,激活后由模型 直接调用。
由于完全在 agent 层实现,它对任意模型、任意 Provider(DeepSeek、OpenAI、
Anthropic、Gemini 等)都有效,不依赖 Provider 原生的延迟工具协议(如 Anthropic
的 tool_reference 或 OpenAI 的 tool_search 输入项)。
特性
- 🔍 按需发现 ——
tool_search支持按精确名称或关键词(中英文均可)查找 工具,命中后返回完整的 JSON Schema。 - ⚡ 懒激活 —— 命中的工具通过
pi.setActiveTools()激活,下一轮即可直接调用。 - 🧭 紧凑清单(manifest) ——
tool_search的描述内嵌每个延迟工具的一行摘要 (名称 + 参数类型 + 描述),让模型知道有哪些工具存在,而无需完整 Schema。 - 🎛️ 灵活配置 —— CodeBuddy 风格的
Defer(...)/NoDefer(...)模式,支持*通配符与全局deferToolLoading开关。 - 🛡️ 自我保护 ——
tool_search与defer_execute_tool永不延迟,因此Defer(*)不会把系统锁死。 - 🧩 零拥有(zero ownership) —— 在 pi 内置工具和第三方扩展工具之上工作, 无需重新实现它们。
安装
从 Git 安装
pi install git:github.com/studyzy/pi-lazy-tools或在 ~/.pi/agent/settings.json 中添加:
{
"packages": ["git:github.com/studyzy/pi-lazy-tools"]
}从 npm 安装
pi install npm:@studyzy/pi-lazy-tools{
"packages": ["npm:@studyzy/pi-lazy-tools"]
}说明: 当前版本通过 Git 仓库分发,npm 镜像会在后续版本中发布。
工作原理
| 组件 | 作用 |
|---|---|
| tool_search | prompt 中唯一面向延迟工具的工具。其描述内嵌紧凑清单(名称 + 一行描述 + 参数摘要)。支持按精确名称(tool_names)或关键词(queries)查找,命中后返回完整 JSON Schema 并激活工具。 |
| defer_execute_tool | 按名称激活一个延迟工具,使模型可以直接调用它。适用于激活模型已经知道的工具。 |
| 激活机制 | tool_search 与 defer_execute_tool 通过 pi.setActiveTools() 激活命中的工具,之后模型即可用完整 Schema 直接调用。 |
调用流程
Prompt:只可见 tool_search + defer_execute_tool 的 Schema
│
▼
模型:tool_search({ tool_names: ["glob"] })
│ └─ 返回 glob 的 JSON Schema,并激活它
▼
下一轮:模型直接调用 glob(此时完整 Schema 已进入工具列表)配置
哪些工具被延迟,通过 pi 的 settings.json 中 lazyTools 配置,使用
CodeBuddy 风格的 Defer(...) / NoDefer(...) 语法:
{
"lazyTools": {
"defer": ["glob", "web_search", "Defer(fetch_*)"],
"noDefer": ["bash"],
"deferToolLoading": true
}
}| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| defer | string[] | [] | 要延迟的工具名或 Defer(pattern) 条目。裸名称等价于 Defer(name)。* 是唯一支持的通配符——Defer(*) 会延迟除守卫工具之外的所有工具。 |
| noDefer | string[] | [] | 必须保持可直接调用的工具名或 NoDefer(pattern) 条目。裸名称等价于 NoDefer(name)。优先级始终高于 defer。 |
| deferToolLoading | boolean | true | 全局开关。设为 false 时不延迟任何工具。 |
修饰符不区分大小写(defer(bash) ≡ Defer(bash))。优先级(从高到低):
noDefer > defer > deferToolLoading。
示例
// 延迟所有 fetch_* / web_* 工具,始终保留 bash
{
"lazyTools": {
"defer": ["Defer(fetch_*)", "Defer(web_*)"],
"noDefer": ["bash"]
}
}// 延迟除守卫工具对(tool_search / defer_execute_tool)之外的所有工具
{
"lazyTools": {
"defer": ["Defer(*)"]
}
}// 按前缀延迟 MCP 网关工具
{
"lazyTools": {
"defer": ["mcp*"]
}
}延迟 pi 内置工具与其他扩展工具
任何 pi 内置工具或另一扩展提供的工具(web_search、bash、glob 等)都可以
通过 lazyTools 延迟。tool_search 会发现并激活它们:返回 Schema 后,工具从
下一轮起即可直接调用。defer_execute_tool 只负责激活,不能执行工具本身,
因为 pi 的扩展 API 不暴露外部工具的 execute。
如果某个工具在当前会话中并未被延迟(例如被 NoDefer 排除),
defer_execute_tool 会返回错误,提示模型直接调用它。
始终激活的守卫工具
tool_search 与 defer_execute_tool 永不延迟,因此 Defer(*) 不会把系统锁死。
已知限制
- 无法同一轮内直接调用。
tool_search激活工具后,当前模型请求的工具列表 已经固定,因此同一响应中的直接调用会报Tool not found。可在同一轮内先用defer_execute_tool激活,然后从下一轮开始直接调用。 - 延迟工具在搜索前不可见。 模型无法在工具列表中看到延迟工具的名称,
它需要依赖
tool_search描述内嵌的清单。
开发
npm install
npm run typecheck # TypeScript 类型检查
npm test # 单元测试(node:test)