Skip to main content

工具与工具集

了解小程序接入的工具与权限机制

在 Finch 里,Agent 能调用的一切——读文件、发搜索、改主题、装 Mini Tool、连 MCP server——都叫「工具」(Tool)。这些工具不是单一来源:了解它们分别从哪来、怎么命名、怎么被授权,能帮你判断「这个能力该不该自己写一个 Mini Tool」,以及 Mini Tool 里的工具要怎么和内置工具配合。

工具的四层来源

层级来源特点
Agent 运行时内置Finch 依赖的 Agent 核心(pi 二进制)文件读写、搜索、终端等基础原语,随 Agent 核心分发,不经过 Finch 的工具注册表
工具集Finch 源码Finch 自己实现的「一个工具多个 action」的复合工具,覆盖记忆、Skill、会话、App 控制、自动化等产品能力
Mini Tool 贡献的工具已安装并启用的 Mini Tool,通过 ctx.tools.register() 注册Mini Tools 开发指南
MCP 贡献的工具官方 MCP 桥接 Mini Tool 动态接入的外部 MCP server工具名固定格式 mcp__<server>__<tool>

四层工具在模型看来没有本质区别——都是一次函数调用;区别主要体现在命名规则权限网关上,见下文。

Agent 运行时内置工具

这些工具由 Finch 依赖的 Agent 核心提供,Finch 只持有它们的权限策略(是否需要用户确认、超时时间),不重新实现执行逻辑。

工具用途
Read读文件(支持按行 offset/limit 读取,也能读图片、PDF)
Write创建/覆盖文本文件
Edit对已读取过的文件做精确文本替换
Grep正则内容搜索(支持 glob 过滤、上下文行、多种输出模式)
Glob按文件名模式匹配
Bash执行 shell 命令;危险命令(rmgit reset --hard 等)与只读命令有专门的判定逻辑
WebSearch网页搜索
WebFetch抓取单个网页并转换为文本/Markdown
AskUserQuestion结构化多选问答卡片,Finch 用它替代纯文本提问
TodoWrite维护当前任务的待办清单,供长任务过程中展示进度
SkillComposer 里插入 /skill 引用时,由此工具承载 Skill 的调用

这一层是「基础设施」层,Mini Tool 不需要也不应该重新实现文件读写、搜索这类能力——直接假设它们已经存在。

工具集

Finch 自己的产品能力没有拆成几十个零散工具,而是收敛成 7 个「调度器工具」,每个工具用 action 参数复用同一个工具定义,模型省略 action 时会拿到该工具的完整用法说明(等价于工具自带的 --help)。

工具用途常见 action
Memory中长期记忆管理,落盘到 MEMORY.md / 每日日志 / Space 记忆remember / replace / forget / search
Skills发现并调用 SKILL.md 技能包list / invoke
Session当前会话内的操作search(历史会话)/ extendDir(信任新目录)/ attach(把文件推进输入框)/ rename
AppCallApp 级控制 + 用户画像写入info / setAppearance / listSpaces / listModels / createSpace / checkUpdate / saveProfile
ToolSearch发现并激活当前会话尚未加载的动态工具(详见下文)query/source/limit
MiniTool管理已安装的 Mini Tool(通过 @finchtoys/minitools CLI)list / add / update / remove / enable / disable / reload
Schedule管理定时自动化任务list / create / update / enable / disable / delete / run / history

这套「调度器」设计是 Finch 自己的架构选择,不是 Mini Tool API 的强制要求——Mini Tool 既可以照这个思路把一组相关能力收进一个带 action 的工具,也可以按需注册多个独立工具,取决于你希望模型怎么发现和调用它们。

动态工具与 ToolSearch

不是所有工具都会在新会话一开始就塞进模型的工具表——工具定义本身要消耗上下文,工具越多,模型选择的准确率越低。Finch 用 exposure 区分两种暴露策略:

  • startup(默认):新会话启动时就注入,例如上面列出的内置工具和调度器工具。
  • dynamic:不进初始工具表,需要先被激活才能调用。典型场景是 MCP server 暴露的工具、按需发现的大量 Mini Tool 工具。

模型需要用不常用的工具时,先调用 ToolSearch 按自然语言描述检索,Finch 把匹配到的工具「激活」进当前会话,模型才能在下一步真正调用它们。MCP 贡献的工具遵循固定命名 mcp__<server>__<tool>(例如 mcp__tavily__tavily_search),且永远不会预加载——必须先经过 ToolSearch source="mcp" 激活。

Mini Tool 贡献工具的命名

Mini Tool 通过 ctx.tools.register({ name, ... }) 注册的工具,模型看到的最终名字是 <mini-tool-id>_<name>(例如 id 为 myextension 的 Mini Tool 注册了 search_docs,模型看到的是 myextension_search_docs)。

如果一个 Mini Tool 代表另一个 Mini Tool 的贡献注册工具(比如官方 MCP 桥接为其它 Mini Tool 贡献的 MCP server 注册工具),可以在工具定义里设置 owner 字段,把工具的来源、权限归属、UI 计数都记到贡献方而不是实际注册方名下——这是官方 MCP 桥接自己用的机制,普通 Mini Tool 一般不需要。

权限与执行策略

每次工具调用在执行前都要过一层策略判断,一共三种结果:

策略行为适用对象
完全免审批autoAllow直接执行,不弹权限卡AskUserQuestion/TodoWrite/Skill,以及 Finch 调度器工具里除 MiniTool 外的全部(Memory/Skills/Session/AppCall/ToolSearch/Schedule
快速通道acceptCallsAutoAllow仅在用户把权限模式切到「Accept Calls」时自动放行,默认模式仍需确认Read/Write/Edit/Grep/Glob/WebSearch/WebFetch,以及只读的 Bash 命令
逐次确认(权限卡)每次调用都展示权限卡,用户手动批准危险 Bash 命令、所有 Mini Tool 贡献的工具、MiniTool 调度器工具本身

关键结论:Mini Tool 贡献的工具永远不会自动放行,无论用户处于哪种权限模式——每次调用都要经过权限卡。这是有意的设计:内置工具和 Finch 自身的调度器工具经过审计,Mini Tool 代码来自第三方,不能获得同等信任级别。写 Mini Tool 工具时,把这一点考虑进交互设计:如果某个操作会被频繁调用,尽量把它拆成一次性配置(存进 ctx.storage/ctx.settings)而不是每轮都触发一次新的工具调用。

Bash 单独判定「只读 / 危险」:只读命令(如 lsgit status)走快速通道,rmgit reset --hard 一类命令始终要求确认,与权限模式无关。

给 Mini Tool 开发者的启示

  • 先看这张清单,再决定要不要写新工具:文件读写、搜索、网页抓取、待办清单这些能力已经存在,不要在 Mini Tool 里重新造轮子。
  • 工具名不会和内置工具冲突:模型侧名字自动加了 <mini-tool-id>_ 前缀,但工具描述仍然要写清楚「和 Read/Grep 这类通用工具比,我的工具专门解决什么」,否则模型可能优先选熟悉的内置工具。
  • description 决定被调用的概率:内置工具和调度器工具的 description 都在系统提示词里长期可见、经过反复打磨;你的 Mini Tool 工具只有安装且启用后才会出现,描述要足够具体地说明触发场景,才能在候选工具里被模型选中。
  • 不要假设自己会被无审批调用:设计交互时默认「每次调用都会先给用户看一张权限卡」,把关键信息(会做什么、影响范围)放进 title/description,而不是指望用户去看代码。

参考资料