关于 builtin-tool
面向 Agent 运行时内置工具开发者的指南,说明工具包结构、运行逻辑、客户端 UI 与注册流程。
主要功能
- 01内置工具的五部分架构
- 02清单、类型与系统提示词指引
- 03运行逻辑与执行器分离
- 04客户端 UI 设计指引
- 05注册与本地化检查清单
适用场景
- 01创建新的内置工具包
- 02为现有工具添加 API
- 03构建或更新工具 UI
- 04排查工具缺失或渲染问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ lobehub/ lobehub --skill builtin-tool安装后在 Claude Code 中输入/builtin-tool确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/architecture.mdtool-design.mdreferences/ui/composition.mddiagnostics.mdinspector.mdintervention.mdplaceholder.mdportal.mdprinciples.mdREADME.mdrender.mdshared-rules.mdstreaming.md详细介绍
内置工具编写指南
内置工具是 Agent 运行时可以调用的一个包。它包含 五个方面:
| 方面 | 所在位置 | 面向对象 |
|---|---|---|
| 清单 + 类型 | src/{manifest,types,systemRole}.ts | 大模型(工具规范 + 系统提示词) |
| ExecutionRuntime | src/ExecutionRuntime/ | 服务端 / 桌面端 / 任何运行时调用方 |
| 执行器 | src/client/executor/ | 前端(封装存储和服务) |
| 客户端 UI | src/client/{Inspector,Render,…}/ | 聊天 UI |
| 注册表接线 | packages/builtin-tools/src/*.ts + src/store/tool/slices/builtin/executors/index.ts | 框架 |
请先阅读这些文档
| 问题 | 文档 |
|---|---|
| 文件位于何处?每个方面负责什么?如何接线? | architecture.md |
| 如何为工具命名、设计 API、编写清单、执行器和 ExecutionRuntime? | tool-design.md |
| 如何构建 Inspector / Render / Placeholder / Streaming / Intervention / Portal? | ui/ |
何时使用此技能
- 创建新的
packages/builtin-tool-<name>/包 - 为现有内置工具添加新的 API 方法
- 构建或重新设计工具的 6 个客户端界面
- 将工具接入中央注册表
- 调试“找不到工具 / 找不到 API / 未显示渲染内容 / 占位符卡住”错误
顶层设计原则
- **
lobe-<domain>标识符是永久的。**它会存储在消息历史记录中。重命名时,必须保留旧别名,并与新名称共存(参见packages/builtin-tool-local-system/src/client/Inspector/index.ts中的// Legacy aliases条目;listLocalFiles/searchLocalFiles重命名为listFiles/searchFiles后,这些条目仍被保留)。务必一次就确定正确。 - ApiName 是
as const对象,而不是 TS 枚举。它还会作为运行时列表,供BaseExecutor遍历。 - 三个结果字段,面向三类使用者:
content: string→ 供 LLM 读取state: Record<…>→ UI 的pluginState;仅限结果域,绝不要把所有参数原样回传error: { type, message, body? }→ 供 LLM 和 UI 使用;type是稳定代码
- 将执行逻辑与前端接线分开。
src/ExecutionRuntime/— 纯运行时,不依赖 React 或 Zustand,通过构造函数接收服务。新增逻辑默认放在这里。src/client/executor/— 调用ExecutionRuntime的BaseExecutor子类(或者仅在前端使用时直接存放逻辑或服务)。
- UI 默认“什么也不做”。必须提供 Inspector(标题栏)。只有存在需要展示的特定内容时,才添加 Render/Placeholder/Streaming/Intervention/Portal;注册表为空也没问题。
- 使用
createStaticStyles + cssVar.*设置样式(零运行时开销)。只有确实需要运行时值时,才退回使用createStyles + token。使用@lobehub/ui组件,而不是原生 antd。 - **i18n 键位于
packages/locales/src/default/plugin.ts。**Inspector 标题必须来自t('builtins.<identifier>.apiName.<api>'),这样参数流式传输时也能显示内容。 - **长时间运行的调用失败后,应支持继续执行,而不只是检查。**例如,
callSubAgent中途停止时,用户会说“继续”。因此,解决方案是在callSubAgent中加入可选的subAgentId,将新指令追加到同一子 Agent 线程中;而不是新增一个“查找该次运行”的 API,要求模型在从头重试前记得先调用它。只有当用户会主动单独提出某项需求时,才新增 API。
包布局(推荐,2026 年后的约定)
packages/builtin-tool-<name>/
├── package.json
└── src/
├── index.ts # exports manifest + types + systemRole + Identifier (no React, no stores)
├── manifest.ts # BuiltinToolManifest with JSON Schema for every API
├── types.ts # ApiName const + Params/State interfaces per API
├── systemRole.ts # System prompt teaching the model when/how to use the APIs
├── ExecutionRuntime/ # ✅ Default home for runtime logic (server- or anywhere-callable)
│ └── index.ts
└── client/
├── index.ts # Re-exports for the registries
├── executor/ # ✅ Frontend executor — extends BaseExecutor, often delegates to ExecutionRuntime
│ └── index.ts
├── Inspector/ # required — header chip per API
├── Render/ # optional — rich result card
├── Placeholder/ # optional — skeleton during streaming/execution
├── Streaming/ # optional — live output renderer (e.g. RunCommand, WriteFile)
├── Intervention/ # optional — approval / edit-before-run UI
├── Portal/ # optional — full-screen detail view
└── components/ # shared subcomponents used by the surfaces above
旧版包(如 builtin-tool-calculator)仍将 src/executor/ 放在 src/client/ 旁边。这属于历史兼容;不要在未经审慎重构的情况下调整其位置。新包以及现有包中新添加的 API,应遵循上述布局。
package.json 导出映射:
"exports": {
".": "./src/index.ts",
"./client": "./src/client/index.ts",
"./executor": "./src/client/executor/index.ts",
"./executionRuntime": "./src/ExecutionRuntime/index.ts"
}
编写检查清单
提交 PR 前:
- 标识符遵循
lobe-<domain>,并且保持稳定(保留在消息历史记录中)。 - 每个
<Name>ApiName值都具备:manifest 中的api[]条目、一个执行器方法、一个 Inspector、一个 i18napiName.*键。 -
Params接口与 JSON Schema 相符;State接口与执行器的返回内容以及 UI 表层读取的内容相符。 - 系统提示词能够区分容易混淆的 API,并指向批量处理变体。
- 运行时逻辑位于
ExecutionRuntime/;client/executor/只负责连接存储/服务并委托执行。 - 执行器通过单一的
toResult()汇总路径返回{ success, content, state, error? }——content始终非空(默认使用error.message)。 - Inspector 能处理
isArgumentsStreaming、isLoading、partialArgs和缺失的pluginState。 - Render 在获得数据前返回
null;仅为具有丰富结果的 API 创建。 - 如果 API 执行存在可感知的延迟(搜索、列表、爬取),则添加占位内容。
- 如果 API 会发出增量输出(运行命令、写入文件、代码执行),则添加流式处理。
- 如果 manifest 中设置了
humanIntervention,则添加人工干预。 - 更新所有注册表文件(参见 architecture.md → 注册表连接)。
- 将 i18n 键添加到
packages/locales/src/default/plugin.ts,并在en-US/zh-CN中添加开发用种子数据。 -
bunx vitest run --silent='passed-only' 'packages/builtin-tool-<name>'通过。 -
bun run type-check通过。
参考工具
选择最接近的示例并参考:
| 如果你的工具是…… | 首先阅读 |
|---|---|
| 纯计算,不需要 UI 状态 | packages/builtin-tool-calculator/ — ExecutionRuntime 复用执行器(mathjs/nerdamer 可在各处使用) |
| 对领域实体进行 CRUD | packages/builtin-tool-task/ — 完整的 Inspector + Render 组合,含批量处理变体 |
| 重型 UI(Inspector/Render/Placeholder/Portal) | packages/builtin-tool-web-browsing/ — 搜索式结果 UI,Portal 用于详情视图 |
| 桌面端/文件系统,包含所有界面(包括 Streaming + Intervention) | packages/builtin-tool-local-system/ — ExecutionRuntime 注入 ILocalSystemService,执行器调用该服务 |
| 纯服务端(无客户端执行器) | packages/builtin-tool-web-browsing/ — 仅导出 ExecutionRuntime;聊天客户端不会运行它 |
| 运行前需要人工批准 | packages/builtin-tool-local-system/src/client/Intervention/ — 每个 API 对应的批准组件 |
评论
支持 Markdown