AI Agent的工具调用层该怎么设计
把Agent的工具调用层拆成定义、校验、执行、结果四类职责,说明为什么schema先行、错误要结构化,以及怎样给后续迭代留出空间。
多数AgentDemo跑通一次调用就结束了,真正做进业务里,最先失控的往往是工具层:参数越加越多、错误靠字符串传递、模型一句幻觉就能触发一个有副作用的接口。
先划清四类职责
把工具层拆开,比设计一个”万能Executor”有用得多:
| 职责 | 要解决的问题 | 产物 |
|---|---|---|
| 定义 | 模型能看到什么 | 名称、描述、参数schema |
| 校验 | 模型输出是否可信 | 结构化参数或明确错误 |
| 执行 | 副作用由谁承担 | 幂等调用、超时、重试 |
| 归一 | 结果怎么喂回上下文 | 截断、摘要、错误码 |
关键是描述与实现同源。参数schema用Pydantic或Zod定义一次,既生成给模型的JSON Schema,又负责运行时校验,不允许出现”文档写一套、代码判一套”。
from pydantic import BaseModel, Field
class SearchDocsArgs(BaseModel):
query: str = Field(min_length=1, max_length=120)
top_k: int = Field(default=5, ge=1, le=20)
model_config = {"extra": "forbid"} # 拒绝模型自造字段
extra="forbid"这类约束看着琐碎,却能挡住大量模型自由发挥出来的参数。
错误要结构化回传
工具失败时直接把异常文本塞回上下文,模型通常会选择”再试一次”,然后以同样的方式再失败一次。更好的做法是返回可判定的结构:
{
"ok": false,
"code": "INVALID_ARGUMENT",
"message": "top_k必须在1到20之间",
"retryable": true
}
有了code和retryable,编排层才能决定是修正参数重试、换工具,还是直接终止并向用户报告。这也让日志可以按错误码聚合,而不是靠正则去猜异常文本。
副作用分级
不是所有工具都该一视同仁。按可回滚性分成三档,能显著降低线上事故面:
- 只读:查询、检索、计算,随意调用;
- 可回滚写入:带幂等键的创建操作,允许自动重试;
- 不可逆写入:付款、发消息、删除,强制人工确认或独立审批步骤。
第三类工具不该出现在模型的自动循环里。这不是模型能力问题,而是系统边界问题。
给迭代留余地
工具描述会直接影响调用准确率,所以它属于需要版本管理的内容,而不是散落在代码里的字符串。建议把名称、描述、schema、副作用等级、超时时间集中登记,执行器只按注册表查找。这样加工具不用改编排逻辑,也方便做离线回放与回归对比。
一句话总结:工具层不是模型与业务接口之间的一层胶水,而是一道必须自己写清楚的安全边界。
评论 0
评论保存在本站服务器,无需登录。带「作者」标识的是站主回复,请友善交流。
还没有评论,来写第一条。