news 2026/5/5 18:01:28

【AI Agent通识九课】03 · AI 的菜单 vs 暗号 — 工具怎么设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【AI Agent通识九课】03 · AI 的菜单 vs 暗号 — 工具怎么设计

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。

@tooldefsend_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)的枚举 + 强类型结构体。

enumAgentAction{CheckCalendar(CheckCalendarParams),SendMessage(SendMessageParams),PlaceOrder(PlaceOrderParams),Search(SearchParams),}structSendMessageParams{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运行时🟢 高🟢 高
装饰器式自助点餐 PadLangChain@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 本身写错了(少个逗号),部署前发现不了。

装饰器式

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

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

强类型枚举

enumAgentAction{// ... 原有变体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。

# 差returnf"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 篇

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/5 18:01:27

蓝桥杯单片机备赛:用NE555和STC15F2K60S2做个简易频率计(附完整代码)

蓝桥杯单片机实战:基于NE555与STC15的智能频率计开发指南 在电子设计竞赛和单片机学习过程中,频率测量是一个经典而实用的项目。对于参加蓝桥杯等赛事的同学来说,掌握NE555定时器与STC15单片机的协同工作方式,不仅能解决具体赛题&…

作者头像 李华
网站建设 2026/5/5 17:53:54

27.人工智能实战:LLM-as-Judge 自动评测到底靠不靠谱?从评分漂移到人工校准的工程化实践

人工智能实战:LLM-as-Judge 自动评测到底靠不靠谱?从评分漂移到人工校准的工程化实践 一、问题场景:人工评测太慢,自动评测又不敢信 大模型系统上线后,评测会变成一个长期工程。 每次你改了: 1. Prompt 2. 模型版本 3. RAG 召回策略 4. reranker 5. Agent 工具描述 6.…

作者头像 李华
网站建设 2026/5/5 17:49:27

终极指南:5分钟搭建你的Obsidian Zettelkasten知识管理系统

终极指南:5分钟搭建你的Obsidian Zettelkasten知识管理系统 【免费下载链接】Obsidian-Templates A repository containing templates and scripts for #Obsidian to support the #Zettelkasten method for note-taking. 项目地址: https://gitcode.com/gh_mirror…

作者头像 李华