工具的分类

工具类型 调用方向 作用对象
感知工具 Agent 主动调用 获取信息
执行工具 Agent 主动调用 改变世界
协作工具 Agent 主动调用 驱动其他 Agent 或人类
用户沟通工具 Agent 主动调用 向用户传递信息
事件触发工具 Agent 注册、外部触发 驱动 Agent 开始执行

工具的设计的通用原则

工具的表现形式

  • 专用代码工具:结构化的函数调用,确定性高、可测试,但每个工具会占据数百个 token,且数量膨胀会破坏 KV Cache。
  • skill+通用工具:用自然语言编写的 Skill 文档来描述操作流程,Agent 通过终端或代码解释器来执行,只需少量的通用工具就能覆盖大量场景

怎么选择专用代码工具还是 skill+通用工具?

  • 参数复杂度:涉及嵌套对象、多字段联合校验、复杂类型约束
  • 工具变更频率:
  • 模型能力:

工具的粒度:分离还是整合

粒度过细会导致工具数量激增,增加 LLM 的选择负担;粒度过粗又会使单个工具过于复杂。当工具数量过多时(比如超过 100 个),即使是最先进的大语言模型也容易在工具选择上出错。
判断标准:功能相似性以及场景重叠度
当功能虽然相似但参数集差异很大、或者某个功能的使用频率极高时,保持独立反而更合理。

工具描述

  • 什么时候用比用来做什么更重要。use when
  • 添加一些反例,Do not use when
  • 参数描述应该用具体的例子代替抽象的规范
  • 返回值也可以用json schema来描述,或者用示例来说明.对于耗时较长的工具,注明执行代价有助于 LLM 合理规划调用顺序
  • 为每个工具附带 1-5 个真实的调用示例

工具的通用性设计

一般来说,通用工具要优于专用工具,给agent一个代码解释器,要比设计加减乘除的专用工具更有价值。前者可以搭配数学计算库完成更多样的计算任务,有时候通用工具的设计也能覆盖到考虑不足的地方
但是对于有特殊权限、复杂配置或有安全风险的操作,封装良好的专用工具仍然是必要的。

参数传递保真性

模型感知到的世界和工具操作的世界是有差异的,要谨防静默参数注入和静默参数转换
如果必须要进行参数的规范化,一定要在工具的文档中明确说明,并且在工具调用前后进行参数的验证和转换,确保传递给工具的参数与模型预期的一致。

感知工具

感知工具设计的核心问题之一,是控制返回信息量,让 Agent 按需获取信息,而不是一次性把所有内容塞进上下文。

当返回结果过长时,可以采用三种方式控制:

  • 压缩:超过一定阈值时,根据 Agent 当前任务对内容做上下文感知压缩,保留与问题最相关的信息。
  • 分页 / limit:搜索工具只返回前若干条候选结果,read 工具通过 offset/limit 只读取文件的一部分,由 Agent 决定是否继续。
  • 显式截断:如果内容被截断,必须明确告诉 Agent“当前展示了多少、还剩多少、如何继续读取”,避免 Agent 误以为已经获得完整信息。

另一个重要设计就是工具的粒度权衡

执行工具

执行工具会真实修改外部环境,因此相比感知工具需要重点保证安全性和可靠性。

执行前检查 → 执行时隔离/审查 → 执行后验证 → 出现异常时安全恢复

执行前检查

  • 输入校验
  • 权限控制
  • 提议者-审核者:事前审批与事后验证

执行时隔离/审查

  • Sidecar 机制:与主思考并行的安全校验。只看这个工具调用是否安全,是一个分类型问题,因此可以用小模型
1
2
3
4
5
6
7
8
9
10
11
主模型生成:
“我要调用 bash("rm -rf /tmp/data")”

├────────────→ 主模型可以继续流式生成文字

└────────────→ Sidecar 开始审查这次 tool call

ALLOW / REJECT

ALLOW → 工具真正执行
REJECT → 工具不执行

Reviewer:
“这个操作从任务角度应不应该做?”

Sidecar:
“这一次具体的 Tool Call 安不安全?”

  • 执行环境的隔离与沙盒:进程级隔离:对低风险的 Agent,可以直接在本地环境中执行代码,例如 Claude Code、Codex、OpenClaw 等都是直接在本地环境中执行代码的。Agent 生成的代码和命令与本地用户拥有相同的权限,因此可以访问、修改或删除用户的任意文件。
    容器隔离:Docker 等容器提供独立的文件系统和网络栈,隔离更完整,但与宿主机共享内核,内核漏洞仍可能被利用来逃逸。
    microVM/虚拟机:Firecracker 等 microVM 提供带独立内核的硬件级隔离,是运行完全不可信代码的最强层级。

执行后验证

如果操作结果可以被验证,就应该自动验证
“执行-验证-反馈”的闭环

还要考虑操作的幂等性,多次操作和单次操作的结果是否一致,避免重复执行带来的副作用。

协作工具

协作工具三大原语:创建/取消、消息传递、Agent 发现

子 Agent 的 Prompt 怎么设计:
角色是谁

拿到了哪些上下文

任务边界是什么

输出格式是什么

人工介入的艺术:

  • 超时和降级策略。
  • 反馈循环的建立。

事件触发工具

定时器(set_timer)处理依赖物理时间的事件。
后台任务监控(monitor_shell)处理来自异步执行的工具或命令行任务的事件。
外部事件通道(connect_channel)
关键在于触发条件的过滤和事件载荷的设计,让世界能够主动唤醒 Agent

用户沟通工具

用户沟通工具用于 Agent 主动向用户传递信息,
主要解决异步 Agent 中“如何触达用户”的问题。

典型工具:

  • reply_to_user
  • send_card_to_user
  • send_user_notification

核心设计

  1. 异步消息模式
    用户不需要一直停留在当前 session,
    Agent 可以在任务完成或事件发生后主动联系用户。

  2. 多渠道选择
    渠道包括 App 消息、Push、短信、邮件、电话等。

根据:

  • 消息紧急程度
  • 用户状态
  • 内容性质
  • 用户偏好

选择合适渠道,并避免重复打扰。

  1. 用户召回
    长任务完成、事件发生或周期任务完成后,
    通过通知重新获取用户注意力。

  2. 消息形态
    除文本外,还可以支持图片、文件、结构化卡片和 Generative UI。

如何从成百上千的工具中选择合适的工具

模型原生工具发现方法(主动发现)

主动声明—语义匹配—动态注入
在系统提示词中仅保留少数几个常用的工具,外加一个工具搜索工具,agent用自然语言描述需求即可检索并加载
两个工程细节

  1. 高效工具搜索需要工具组织的层次化
    1786584363273
  2. 注意KV Cache的使用

这种方式的缺点就是工程上还是很繁琐的,要支持离线的增量更新索引,要考虑KV Cache的使用,弱模型要进行专门的训练

Skills:把工具发现变成“按需查阅”

不再需要那套 “嵌入索引 + 语义匹配” 的基础设施。
Agent 启动时只看到一份薄薄的目录——每个 skill 的 name 与 description(合计数百 token)。当当前上下文真的需要某种能力时,模型才去读取对应的 sub-skill,并顺着其中的引用再往下一层,读取具体的脚本或子文档。“发现” 由模型在上下文里的实际需要驱动,而不是在任务开始时对初始查询做一次性预匹配。

主动工具发现 Skills
核心 Agent 主动声明能力缺口 Agent 主动读取 Skill
发现方式 语义检索 目录 + 文件阅读
是否需要 Embedding 通常需要 不需要
是否需要 Tool Index 需要 不需要
工具定义 JSON Schema 自然语言
灵活性 较强 很强
模型要求 较低 较高
人类维护 相对复杂 简单

缺点就是,模型需要有较强的阅读理解能力和推理能力,才能在目录和文档中找到所需的工具,并正确理解其使用方法。
Skill 对模型提出了更高的要求,在参数复杂的情况下也更容易出错。

这里将主动工具发现和skill并列并不是说它们是互斥的,而是说它们在工具发现的方式上有本质区别。主动工具发现是通过语义检索来找到工具,而 skill 是通过阅读文档来找到工具。通常架构上Skill告诉 Agent:这个任务应该怎么完成。然后调用多个 Tool得到结果,Skill 指导 Agent 如何组织结果