Agent 不可靠怎么办?工具权限、参数校验、异常兜底与源码解析
2026/6/15 7:48:53 网站建设 项目流程

1. Agent 不是员工,是实习生

Agent 能规划,能调用工具,能连续执行。

这很强。也很危险。

因为模型会犯错。它可能调错工具,填错参数,误解返回值,重复调用接口,甚至尝试执行高风险动作。

所以生产级 Agent 的第一原则是:模型负责“想”,系统负责“准不准做”。

2. Agent 最容易出问题的 6 个地方

普通聊天机器人答错了,最多是回答不准。

Agent 答错了,可能会真的调用系统。

这就是风险升级。

Agent 常见失控点与治理方式。

这里最核心的是工具。

模型输出的不是“结果”,而是“行动意图”。

一旦行动意图被系统执行,就必须有门禁。

3. 源码视角:一次工具调用到底经过什么?

从表面看,Agent 只是“调用一个函数”。

从源码看,它其实要经过一条完整链路。

Agent 工具调用的源码主链路。

这条链路有三个关键角色。

第一,模型只负责生成 `AIMessage.tool_calls`。它说:“我想调这个工具,参数是这些。”

第二,`ToolNode` 负责调度。它把工具调用包装成 `ToolCallRequest`,再执行工具。

第三,`BaseTool` 负责校验和执行。它会处理输入、回调、异常和输出包装。

源码级理解:ToolNode 是调度层,BaseTool 是执行层,Middleware 是治理层。

4. 工具权限,不让模型随便调

工具不是越多越好。

一次性给模型太多工具,模型会更容易选错。

更重要的是:不同工具风险不同。查天气和删除数据,绝对不能一个权限级别。

工具调用必须先经过 Tool Gate。

生产环境里,工具至少要分三级。

低风险工具,自动执行。比如查知识库、查天气、读取公开数据。

中风险工具,人工审批。比如写文件、发邮件、执行 SQL。

高风险工具,直接拒绝。比如转账、删除核心数据、修改权限、自动下单。

不要把“不能下单”只写进 Prompt。真正的限制要写在工具门禁里。

5. 参数校验,让错误在执行前暴露

模型可能会填错参数。

比如金额应该是数字,模型给了“很多钱”。

比如 SQL 只能 SELECT,模型给了 UPDATE。

比如股票代码应该是 6 位,模型给了公司简称。

这类问题不能等业务接口报错。要在工具入口拦住。

LangChain 的 `BaseTool` 有一个关键字段:`args_schema`。

它可以用 Pydantic 描述工具参数。工具执行前,`_parse_input()` 会根据这个 schema 做校验。

class QueryStockInput(BaseModel): symbol: str = Field(description="6 位股票代码") days: int = Field(default=20, ge=1, le=250) @tool(args_schema=QueryStockInput) def query_stock(symbol: str, days: int = 20) -> str: """查询股票历史行情。""" ...

这个示例不是重点。重点是背后的链路:参数先过 schema,再进业务函数。

参数错了,应该返回可读错误,让模型有机会修正,而不是让整个 Agent 崩掉。

6. BaseTool.run() 的源码分流

Agent 工具执行时,错误不是一个类型。

参数错误、业务错误、系统错误,要分开处理。

BaseTool.run() 中的执行链路和异常分流。

源码里,`BaseTool.run()` 大致做了这些事。

先启动回调。再把输入转成 `args/kwargs`。再调用 `_parse_input()` 校验参数。最后执行 `_run()`。

执行过程中,源码会分流处理 `ValidationError`、`ToolException` 和普通 `Exception`。

`handle_validation_error` 控制参数校验错误怎么返回。

`handle_tool_error` 控制工具主动抛出的 `ToolException` 怎么返回。

普通未知异常默认继续抛出,应该交给 middleware 或外层统一兜底。

源码级结论:BaseTool 不是只执行函数,它还负责参数校验、回调记录、异常分流和输出包装。

7. Middleware,专门处理横切逻辑

权限、限流、重试、缓存、降级,不应该散落在每个工具函数里。

这些是横切逻辑。

LangChain 的 middleware 可以包住工具调用。

`wrap_tool_call` 就是工具层最重要的钩子。

wrap_tool_call 可以拦截、重试、降级和返回 ToolMessage。

一个可靠的工具兜底逻辑,应该是这样:

@wrap_tool_call def safe_tool_call(request, handler): if not has_permission(request): return ToolMessage( content="没有权限执行该工具。", tool_call_id=request.tool_call["id"], ) try: return handler(request) except TimeoutError: return ToolMessage( content="工具超时,请稍后重试。", tool_call_id=request.tool_call["id"], )

注意这里的关键点:返回的是 `ToolMessage`。

它不是普通字符串。它带着 `tool_call_id`,能让模型知道这是哪一次工具调用的结果。

工具失败时,不要只抛异常。能恢复的错误,要转换成模型能理解的 ToolMessage。

8. 高危动作必须人工审批

自动化不是让模型无边界执行。

凡是不可逆、涉及资金、涉及隐私、影响权限的动作,都必须停下来。

LangChain 的 Human-in-the-loop middleware 可以让工具调用在执行前暂停。

Human-in-the-loop 让高危工具在执行前等待人类决策。

它的核心不是“报错”。

它是“暂停”。

暂停后,系统把工具名和参数展示给审核人。审核人可以批准、编辑、拒绝,或者直接给模型反馈。

这里必须配合 checkpointer。因为图执行被暂停后,状态要保存下来,后面才能恢复。

高危动作的正确流程:模型提出动作,系统暂停,人类确认,图再继续。

9. 生产级 Agent 的安全架构

不要只在 LangChain 里面做安全。

企业级系统要从入口、Agent、工具、业务系统、观测系统五层一起治理。

入口层做认证、限流、黑白名单。

Agent 层控制模型、工具、记忆和上下文。

治理层做 middleware、Tool Gate、Guardrails、人工审批。

业务层做二次校验。不要相信上游一定干净。

观测层做 Trace、日志、告警和回放。

最稳的设计是“双重校验”:Agent 工具层校验一次,业务系统再校验一次。

10. 这几个字段必须记住

写工具时,重点看 `BaseTool` 的这几个字段。

`name`:工具名。模型靠它选择工具。名字要短,要明确。

`description`:工具说明。模型靠它判断什么时候用。描述越模糊,误调越多。

`args_schema`:参数 schema。它决定参数校验是否可靠。

`handle_validation_error`:参数校验失败时,是否转成可读输出。

`handle_tool_error`:工具主动抛出 `ToolException` 时,是否转成工具输出。

`return_direct`:是否让工具结果直接返回,不再让模型二次加工。

`response_format`:工具结果是普通内容,还是内容加 artifact。

判断一个工具是否能上线,不看 Demo 能不能跑。看它有没有 schema、权限、异常、审计和降级。

11. 最小落地清单

最后,给一个生产检查清单。

第一,所有工具必须有明确 name、description 和 args_schema。

第二,工具必须按风险分级:只读、可写、高危。

第三,高危工具必须走 Human-in-the-loop。

第四,所有工具调用必须记录 requestId、userId、tool_name、args、result、耗时、错误。

第五,所有可恢复错误都要返回 ToolMessage,不能让 Agent 直接崩。

第六,工具要有超时、重试、限流和降级。

第七,业务系统要做二次校验,不能把权限完全交给模型。

第八,线上要能回放一次完整 Agent 执行链路。

12. 总结

Agent 的价值,是让模型能做事。

Agent 的风险,也是让模型能做事。

所以真正的重点不是“让 Agent 更自由”。

而是让 Agent 在可控边界内行动。

一句话:生产级 Agent 不是靠模型自觉,而是靠系统设卡。


内容来源:Agent 不可靠怎么办?工具权限、参数校验、异常兜底与源码解析:功能变化与行业影响解析_热闻岛

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询