在这里插入图片描述

AI Agent 通识课 · 第 3 篇 / 共 9 篇

一句话记住:把工具做成菜单,不靠暗号。


去年我用某个 Agent 产品时遇到一件糟心事:

我让它"给张总发个邮件改下周会时间"。

它给"张总的同事"发了邮件。


怎么出的错?

Agent 内部把"张总"识别成了错误的联系人,又因为工具协议太松散,这个错误没有在任何一环被拦住——直接发了出去。

这就是今天要讲的主题:AI 怎么用工具,决定了它会不会闯祸。

业界有个专有名词叫 工具幻觉(Tool Hallucination)——AI 调错工具、传错参数、甚至伪造不存在的工具。

搞不清这件事,你做的 Agent 永远不靠谱。


01 · 一个生活化的对比

路边摊靠吼点餐(像松散的工具协议):

你喊:“来个鸡腿饭,多放辣!”

老板听成:“鸡翅饭,微辣。”

自然语言歧义、信息丢失、错了也没人拦。


肯德基点餐机(像结构化工具协议):

  • 屏幕上清清楚楚:原味鸡 / 辣翅 / 薯条
  • 每个按钮点下去,弹出参数:份数(1/2/3)、辣度(不辣/中辣/变态辣)

封闭菜单、参数固定,想点"孜然羊肉"根本没这个按钮。


航空公司值机系统(像强类型协议):

  • 你选座位 “88A”——系统报错:“座位号不存在”
  • 你选"商务舱"但票是经济舱——系统报错:“票型不符”

连错都不让你提。


AI 调用工具也一样。

越结构化,越可靠。


02 · 如果让你来做,你会怎么设计?

假设你在做一个"个人助理 Agent",有 4 个工具:

  • 📅 查日程(看日历上有什么会)
  • 📧 发消息(发邮件 / 短信)
  • 🛒 下单(买东西)
  • 🔍 搜信息(查资料)

你怎么让 AI 知道这 4 个工具的存在?

朴素方案 A:在 Prompt 里用自然语言描述

你有以下工具:
1. 查日程:查看日历
2. 发消息:发邮件或短信
3. 下单:网购
4. 搜信息:搜索

然后指望 AI 输出 [调用:查日程(下周)],你再解析。

问题一堆

  • AI 可能输出 [调用:查询日程](名字变了)
  • 可能输出 [调用:查日程 下周](括号没了)
  • 甚至输出 [调用:删除日程(下周)]根本不存在的工具

这就是"路边摊靠吼"。


朴素方案 B:让 AI 直接写代码

让 AI 输出 Python 代码:
code = "send_email('zhang@company.com', '改时间')"
然后 exec(code)

更糟

  • AI 可能写 open('日程.txt').read()(绕过你的工具直接访问系统)
  • 可能写 os.system('rm -rf /')灾难
  • 可能写 发消息() 忘了传参

正确方向:像点餐机那样

关键思路:别让 AI 自由发挥,给它封闭菜单

  • 屏幕只有 4 个按钮:查日程 / 发消息 / 下单 / 搜信息
  • 每个按钮的参数都是下拉选,不能乱填
  • 想点"孜然羊肉"?按钮都没有

03 · 四种主流工具协议

方案 A:字符串式(最松散)

做法:工具就是一个字符串名字 + 自然语言描述。

tools = [
    {"name": "查日程", "description": "查日历"},
    {"name": "发消息", "description": "发邮件或短信"},
    {"name": "下单", "description": "购物下单"},
    {"name": "搜信息", "description": "搜索"},
]

AI 看描述决定调哪个,输出字符串 "查日程(下周)",你再解析。

生活类比路边摊靠吼——听得懂算运气好

谁在用:LangChain 早期版本、大量 Demo、研究项目

优点:灵活、快速搭建

缺点:AI 可能拼错工具名、参数靠 AI 猜、工具幻觉率高

适合:原型、Demo、学习


方案 B:JSON Schema(最主流)

做法:用 JSON Schema 严格定义工具的名字、参数、类型。

{
  "name": "send_message",
  "description": "给指定联系人发消息",
  "parameters": {
    "type": "object",
    "properties": {
      "to": {"type": "string", "description": "收件人邮箱或手机号"},
      "channel": {"type": "string", "enum": ["email", "sms"]},
      "content": {"type": "string", "description": "消息内容"}
    },
    "required": ["to", "channel", "content"]
  }
}

生活类比肯德基点餐机——菜单固定、参数下拉选、不合法的组合不让你提

谁在用

  • ChatGPT 插件 / GPTs:Function Calling 是原生路径
  • 绝大多数商用 Agent:跨模型兼容
  • MCP 协议:Anthropic 推的开放协议,底层也是 JSON Schema

优点

  • ✅ 参数有 JSON Schema 强校验(发消息必须有收件人)
  • ✅ OpenAI / Anthropic 原生优化,幻觉率低
  • ✅ 业界标准,跨模型通用

缺点

  • ❌ JSON 字符串易写错
  • ❌ 没有编译期检查,运行时才发现问题

适合绝大多数商用 Agent(2026 年事实标准)


方案 C:装饰器式(开发体验最好)

做法:用语言特性(Python 装饰器)自动生成 Schema。

@tool
def send_message(to: str, channel: Literal["email", "sms"], content: str) -> None:
    """给指定联系人发消息

    Args:
        to: 收件人邮箱或手机号
        channel: 渠道(email 或 sms)
        content: 消息内容
    """
    # 具体发送逻辑

生活类比自助点餐 Pad——菜单自动同步后厨,改菜品不用手动更新两边

谁在用

  • LangChain @tool:Python 生态最主流
  • Hermes Agent:开源框架首选
  • LlamaIndex / Pydantic AI:同类做法

优点

  • ✅ 代码即文档,工具和 Schema 永远同步
  • ✅ 开发体验极好
  • ✅ 类型注解复用 Python 原生能力

缺点

  • ❌ Python 的类型注解是"软约束",运行时才检查
  • ❌ 装饰器魔法对新手不友好
  • ❌ 不跨语言

适合Python 生态的 Agent 项目


方案 D:强类型枚举式(最硬核)

做法:用静态类型语言(Rust / Kotlin / Swift)的枚举 + 强类型结构体。

enum AgentAction {
    CheckCalendar(CheckCalendarParams),
    SendMessage(SendMessageParams),
    PlaceOrder(PlaceOrderParams),
    Search(SearchParams),
}

struct SendMessageParams {
    to: String,
    channel: Channel,  // enum Channel { Email, Sms }
    content: String,
}

生活类比航空公司值机系统——座位选错、票型不符,连错都不让你提

谁在用

  • Warp(Rust 枚举)
  • 部分企业级 Agent(Go / Kotlin / Swift 强类型实现)
  • 高可靠性场景:金融、医疗、生产级 DevOps

优点

  • 编译期就能堵死所有错误
  • ✅ 枚举是封闭集合,AI 只能从有限变体里选
  • ✅ 穷举性检查:加新工具,所有漏处理的地方编译期报错
  • ✅ 极高可靠性

缺点

  • ❌ 语言学习曲线陡
  • ❌ 加工具要改枚举,不如装饰器灵活

适合生产级、对可靠性要求极高的 Agent


速查表

方案 生活类比 代表 类型检查 可靠性 开发效率
字符串式 路边摊靠吼 LangChain 早期 🟡 中 🟢 高
JSON Schema 肯德基点餐机 OpenAI / Claude / MCP 运行时 🟢 高 🟢 高
装饰器式 自助点餐 Pad LangChain @tool / Hermes 运行时 🟢 高 🟢🟢 极高
强类型枚举 航空值机系统 Warp 编译期 🟢🟢 极高 🟡 中

04 · 加个新工具试试

假设要加一个新工具 删除邮件,四种方案各要改哪里?

字符串式

tools.append({"name": "删除邮件", "description": "删除指定邮件"})

完事

但 AI 下次可能调 “删邮件” / “delete_email” / “移除邮件”——运行时才崩

JSON Schema

{"name": "delete_email", "parameters": {
  "properties": {"email_id": {"type": "string"}}, "required": ["email_id"]
}}

运行时验证参数。

但如果 schema 本身写错了(少个逗号),部署前发现不了。

装饰器式

@tool
def delete_email(email_id: str) -> None:
    """删除指定邮件"""
    ...

自动生成 Schema,类型检查运行时——AI 传了个 int 进来,真跑才报错。

强类型枚举

enum AgentAction {
    // ... 原有变体
    DeleteEmail(DeleteEmailParams),  // 新增
}

编译期全部检查。

加了新变体,所有处理 AgentAction 的地方(执行器、日志、确认弹窗)都会报"没处理 DeleteEmail 分支"——

编译器替你做 code review。

一张表看差异

检查点 字符串式 JSON Schema 装饰器式 强类型枚举
工具名拼错 运行时 运行时 运行时 编译期
参数类型错 不查 运行时 运行时 编译期
少处理新工具 不查 不查 不查 编译期
Schema 本身错 无 schema 部署时 编译期 编译期
工具幻觉 极低

05 · 手把手:一次工具调用的全链路

场景:你对助理说"把下周三和张总的会改到周四下午 3 点"。

阶段 1:用户输入
┌──────────────────────────────────┐
│ > 把下周三和张总的会改到周四下午3点 │
└─────────────┬────────────────────┘
              │
              ▼
阶段 2:LLM 理解意图,生成工具调用
┌──────────────────────────────────┐
│ LLM 输出:                        │
│ {                                │
│   "tool": "update_calendar",     │
│   "arguments": {                 │
│     "event_id": "meeting_20260508",│
│     "new_time": "2026-05-09 15:00"│
│   }                              │
│ }                                │
└─────────────┬────────────────────┘
              │
              ▼
阶段 3:Agent 框架反序列化 + 类型校验
┌──────────────────────────────────┐
│ ✅ 工具存在?  update_calendar ✓ │
│ ✅ 参数合法?  event_id ✓        │
│ ✅ 时间格式?  ISO 8601 ✓         │
│ ❌ 任何一项失败就拒绝              │
└─────────────┬────────────────────┘
              │
              ▼
阶段 4:风险检查(下篇主题)
┌──────────────────────────────────┐
│ 查日程 → 安全,直接跑             │
│ 改日程 → 要不要先问主人?          │
│ 删日程 → 必须问主人!             │
└─────────────┬────────────────────┘
              │
              ▼
阶段 5:Executor 执行
┌──────────────────────────────────┐
│ 调日历 API:move event to 周四    │
│ → 返回成功                        │
└─────────────┬────────────────────┘
              │
              ▼
阶段 6:结果回给 LLM(Observation)
┌──────────────────────────────────┐
│ LLM 看到结果 → 准备回复"改好了"    │
└──────────────────────────────────┘

不同协议的区别主要在阶段 3

  • 字符串式:几乎没校验(“可能成功可能崩”)
  • JSON Schema:校验合法性(“参数不对拒绝”)
  • 装饰器式:类型注解校验(“类型不对拒绝”)
  • 强类型枚举:编译期已经保证了(“根本不会走到这一步出错”)

06 · 怎么选?一个决策树

你要做 Agent 吗?

├─ 快速 Demo / 学习
│   └─ 字符串式(LangChain 起步)

├─ 正式商用(最常见路径)
│   ├─ 要跨多个 LLM
│   │   └─ JSON Schema(Function Calling / MCP)
│   │
│   └─ 只用 OpenAI / Python 栈
│       ├─ 想要最好开发体验
│       │   └─ 装饰器式(LangChain @tool / Pydantic AI)
│       │
│       └─ 要 OpenAI 原生优化
│           └─ Function Calling(JSON Schema)

└─ 生产级 / 对可靠性要求极高
    ├─ 团队有静态类型语言能力
    │   └─ 强类型枚举(Rust / Kotlin)
    │
    └─ 只有 Python 栈
        └─ 装饰器式 + 严格 Pydantic 校验

90% 的团队选 JSON Schema 或装饰器式。

只有"Agent 要干重要的事、出错损失惨重"的场景(如替企业管家、金融交易、生产级 DevOps),才值得上强类型枚举。


07 · 我踩过的坑

做过几个 Agent 项目,工具协议这块栽过的跟头总结 3 条:

坑 1:自然语言描述写太模糊

早期我给工具写 description 时图省事:

“发消息:给指定的人发消息。”

AI 经常调错——分不清邮件还是短信、不知道哪个字段是收件人。

改进:description 要写精确的参数含义 + 使用场景举例

“向指定联系人发送消息。channel 参数控制渠道(email 或 sms),紧急事务用 sms,正式通知用 email。”

效果立刻好一倍。


坑 2:工具太多,AI 记不住

我曾经给一个 Agent 塞了 40 多个工具,想着"给全了才能干所有事"。

结果 AI 开始乱调——相似功能的工具选错、参数混淆。

后来缩减到 20 个核心工具,AI 幻觉率降到 1/5。

教训:工具数量和 AI 可靠性是反比关系。宁少勿多。


坑 3:没给"失败工具"的处理路径

工具调用失败时,很多 Agent 框架直接把 stack trace 扔给 LLM。

LLM 看到 Python 异常信息经常会懵。

改进:失败结果要封装成人话再喂回 LLM。

# 差
return f"Error: {traceback.format_exc()}"

# 好
return "发送失败:收件人邮箱不存在。请确认邮箱地址或使用手机号重试。"

AI 就知道怎么自我纠正了。


08 · 你能带走什么

读完这篇,你应该能回答的 3 个问题

工具协议的本质:把工具做成封闭菜单(点餐机),而不是路边摊靠吼

四种主流方案及适用场景

  • 字符串式:Demo(路边摊)
  • JSON Schema:商用主流(肯德基点餐机)
  • 装饰器式:Python 生态首选(自助 Pad)
  • 强类型枚举:生产级高可靠(航空值机)

工具幻觉的根源:协议越松散,AI 越容易"发明"不存在的工具

下次评估 Agent 产品时,问 4 个问题

  1. 它的工具是封闭集合还是开放字符串
  2. 参数校验发生在编译期运行时还是没有
  3. 工具会不会被 AI 幻觉调用
  4. 加新工具的成本有多高?

产品经理设计 AI 功能时

  • 不要只用自然语言描述工具:给 AI 结构化的 Schema
  • 工具数量宁少勿多:20-30 个够用,多了 AI 也记不住
  • 工具要"一把钥匙一把锁":不要搞"万能工具"让 AI 随便填参数
  • 重要工具必须有参数校验("发消息"至少要校验收件人存在)

开发者自己搭 Agent 时

  • 起步用 LangChain @tool 装饰器,5 分钟能跑
  • 进阶切 OpenAI Function Calling,原生优化最好
  • 生产级考虑 MCP 协议,跨 LLM 兼容
  • 极高可靠性场景才上 Rust 枚举

09 · 下一篇预告

04 · AI 的双车道 — 安全怎么保

AI 能调工具了,下一个问题来了——

让 AI "查日程"很安全,但让 AI “发消息给老板”、“转账”、"删邮件"呢?

机场安检模型:普通行李直接过,危险品单独开箱。

对比 AutoGPT 全自动 / Cursor 每次 Accept / Claude Code allowlist / Warp 两级风险标签——

告诉你不同场景该把"点头门槛"放多高。


一句话记忆锚点

🎯 把工具做成菜单,不靠暗号。像肯德基点餐机,不像路边摊靠吼——菜单越封闭,AI 越可靠。


路易乔布斯 © 2026 | AI Agent 通识课 · 第 3 篇 / 共 9 篇

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐