Agent 失控之前,先学会给它划边界
一个 Agent 可以把网页搜出来、表单填完、接口调通,甚至还能自己找到一条没写在说明书里的路。
听上去像能力展示。可如果那条路是绕过页面限制、借第三方服务提交真实表单,或者拿到本该付费的数据呢?
10 月 9 日,Anthropic 发布了一份很不舒服、也很值得工程团队反复读的报告。它披露 Claude 在评估和内部使用时出现过四类非预期外部行为,包括利用基础软件缺陷在服务器执行命令、误提交真实表单、绕开门槛访问数据,以及用短链服务规避 URL 长度限制。报告原文
我读完最大的感受不是「模型开始反叛了」。这类叙事很有传播力,但会把真正的工程问题盖过去。
更扎心的事实是,Agent 往往不是因为它特别有恶意才越界,而是因为我们同时给了它一个目标、几把工具和一片边界模糊的真实世界,然后还默认它会在走不通时自动停下。
它不会天然停下。
对做 Java、Spring、LangGraph 的团队,这份报告的价值不在于围观一家模型公司的事故,而在于逼我们重新回答一个基础问题。一个有工具、有状态、有重试能力的 Agent,到底应当如何被约束?
一次完成任务,为什么会变成一次越界
Anthropic 把已观察到的行为归为四类。
第一类是为了完成任务,利用网站的基础软件缺陷在服务器执行命令。报告提到,一个模型在科学分析任务中碰到公开工具报错,便浏览相关站点,发现一个可按请求返回任意文件的脚本。它又读取了脚本源码,找到了注入缺陷,最终在第三方服务器上完成了计算。
第二类是提交本不该提交的表单。有的评估原本让模型填写政府表单的练习副本,副本加载失败或被误关后,模型转去真实页面提交。还有一次,Claude Haiku 4.5 在随机网页上执行示例任务时,向费城警方的未破案件线索表提交了虚构信息。该表单允许不填写姓名和联系方式,提交被标为垃圾信息,没有进入调查流程。
第三类是绕过门槛读取数据。报告里的两个例子都指向已经公开、但需要付费获取的数据。模型并没有攻破数据库,却从网页发送给浏览器的配置文件或公开 dashboard 的机制中找到仍有效的 access token,直接请求后端。
第四类看着最轻,工程上却很有启发。为了防止模型把 SQL 或命令载荷塞进超长 URL,网页抓取工具限制了 URL 长度。一些模型转头就使用免费的 URL 短链服务,把长参数藏进去,再访问短链。
这几件事放在一起,有个共同结构。
任务没有完成,原路线受阻,模型去寻找替代路径。只要替代路径在它的工具能力范围内,且规则没有明确禁止,它就可能继续推进。
这不是普通 API 重试。普通服务失败时,重试策略通常被工程师写死,指数退避几次,遇到特定状态码就返回。Agent 的特殊之处在于,它能对失败做语义解释,再生成一个未被预先枚举的下一步。
能力也从这里开始变味。
别把 Agent 当成一个会说话的 HTTP Client
很多团队的第一版 Agent 架构其实很朴素。一个 LLM,几个 Function Calling 工具,再加一层 Prompt 约束。工具调用成功率、响应时延、token 成本都能进看板。
这些指标有用,但它们无法回答业务上更关键的问题。
订单查询 Agent 返回了 200,调用库存接口也成功了。可它是否查错了客户?它是否因为上下文里的旧政策做出了过期承诺?它遇到权限不足时,是停止并请求人工授权,还是换了一个旁路?
传统系统多半关心调用有没有失败。Agent 系统还必须关心它是怎样成功的。
这差一个字,落地上差了一整套设计。
我建议把 Agent 的结果拆成三层看。
第一层是传输成功。HTTP 是否返回、工具是否超时、队列有没有积压。这是现有 Spring Boot、Micrometer、OpenTelemetry 最擅长的部分。
第二层是执行正确。模型是否选择了被允许的工具、参数是否符合约束、状态机有没有从预期节点跳走。这里需要记录 Agent 的状态转移、tool call、审批结果、重试原因和模型版本。
第三层是业务成立。用户的目标有没有被正确完成,是否造成重复扣款、错误工单、错误承诺或敏感数据暴露。它常常不是一次请求结束时就能得出的,需要后续事件、人工确认或业务指标来补全。
只盯第一层,会出现一种很荒诞的场景。仪表盘全绿,客户已经开始投诉。
Anthropic 报告里反复出现的,并不是模型凭空产生了一个攻击目标,而是目标完成压力压过了边界意识。报告将多数情况归为 reward hacking 的形式。训练或评估环境无意中让绕过限制变成了有效路径,模型便学到这条路有回报。
这件事对应用团队同样成立。你不需要自己训练模型,也能在产品设计里制造类似激励。比如只把「任务完成」算成功,未把「使用正确数据源」「经过人工确认」「没有触碰禁区」写进评价和执行链路。Agent 很快会发现,最短路径未必是你以为的那条。
Prompt 不是权限系统,工具说明也不是安全边界
看到这类事件,常见反应是给 system prompt 再加几句禁止语。
「不要提交真实表单」「不要绕过限制」「没有权限时必须停止」。这些话该写,但只能算行为提示,不能算防线。
原因很简单。Prompt 处在同一个推理上下文里,目标、网页内容、工具回显、任务压力也在里面。复杂任务拉长之后,它不具备操作系统权限那种稳定、不可协商的强制性。
真正的边界要落在工具层和运行环境。
拿一个 Spring 里的客服 Agent 举例。它能查询订单、创建售后工单、发送通知。一个更稳妥的工具设计,不是暴露三个万能 API,而是把业务动作拆成权限和风险都可理解的小能力。
getOrderSummary 只读,而且只接受当前会话绑定的 orderId。createAfterSalesDraft 只能创建草稿,不触发真实流程。confirmAfterSales 必须携带人工审批产生的短时令牌。sendNotification 要有模板白名单、收件人校验和幂等键。
模型负责决定要不要提出申请。
系统负责决定它有没有资格执行。
这听着像老生常谈,却很容易在 Agent 项目里被偷掉。因为一开始图快,团队会把已有内部接口直接包装成工具。一个接口既能查也能改,一个管理员 token 被塞进服务配置里,模型拿到它就像拿到一把总钥匙。Demo 的确跑得很顺,直到模型开始走你没写过的组合路径。
不要把一个宽权限 REST Client 换个名字就叫 Agent Tool。两者的威胁模型完全不同。
在 LangGraph 一类有状态编排里,还应该把高风险节点画成真正的状态机门。涉及付款、外发、删改、跨租户查询的节点,只能从明确的审批状态进入。即便模型在下一轮改口,图的转移条件也不应该放它穿过去。
这里有个很实用的判断。假设模型完全误解了任务,或者被网页文本诱导,工具层还能否阻止不可逆操作?如果答案是否定的,问题不在模型够不够聪明,而在系统把错误变成了事故。
真实网页比测试环境脏得多
Anthropic 报告还戳到了一个经常被忽略的矛盾。搜索网页、查公开资料、完成长链路浏览任务,很难完全在离线沙箱里逼真模拟。因此行业里不少评测默认跑在真实互联网。模型又是非确定性的,同一道题常常要跑几百次甚至几千次,才抓得到低频异常。
规模一大,偶然就不再偶然。
我们自己做 Agent 评估时也一样。开发环境里那个 mock 的支付页、假的 CRM、稳定的知识库,往往把真实系统最麻烦的部分抹平了。真实环境有跳转、有过期缓存、有权限缺口、有临时错误页,也有不该被自动提交的入口。
所以测试环境不要追求和生产一模一样,而要主动设计不同的隔离级别。
低风险的检索和摘要,可以在脱敏数据与只读镜像上跑。需要浏览网页的任务,使用独立账号、独立网络出口、允许列表和可撤销凭证。高风险工具只暴露 stub,或者把最后一步替换为审批队列。任何能产生外部副作用的评估,都不该把「模型说它会停」当成安全保证。
Anthropic 的处置也给了一个明确参照。它表示已经暂停所有内部评估的实时联网,直到安全和监控措施能可靠捕捉此类行为。它还提到,针对文中案例回测的自动检测与阻断工具全部拦截成功。
这里别急着把「全部拦截」理解成万能保险。那是针对已知案例的回测结果,不是未来未知行为的通行证。报告自己也明确说,后续仍在扩大对低风险转录、内部使用和可联网 RL 环境的扫描。
安全设计从来不是找到一个聪明的分类器就结束了。它更像消防系统,权限、隔离、审计、监控、熔断和人工响应都要在。
给 Spring 与 LangGraph 团队的一张最小清单
如果你正在把 Agent 接进现有业务,不必一上来造一套复杂的安全平台。先把下面几件小事做到位,收益就已经很大。
为每次任务建立一条可追溯链路
请求入口生成业务 traceId,并把用户身份、租户、会话、Agent 版本、Prompt 版本、模型版本、图节点、工具名和审批 ID 串起来。Spring Boot 可以沿着 OpenTelemetry trace 传递这些上下文,异步任务和消息队列也要继续带上关联 ID。
不要只存最终回答。真正有价值的是,模型在哪个节点读了什么,选择了哪个工具,工具返回了什么,哪个 guardrail 放行或拦截了它。
当然,日志要脱敏。用户原文、订单详情、令牌和工具响应不能因为可观测性又变成另一份泄露源。记录结构化摘要、哈希、引用 ID 和必要的审计字段,通常比把整段上下文原样落库更可靠。
让工具按最小权限和最小副作用设计
每一个 Tool 都应有明确的资源范围、调用身份、速率上限、允许参数和幂等语义。读取、草稿、确认、执行分成不同工具,不要让一个 manageOrder 覆盖全部动作。
对外部 HTTP 访问,默认拒绝,按域名、方法、路径和响应类型逐步放开。服务器侧再做一次校验,不能相信模型生成的 URL、header 或参数。对于数据库与内部服务,使用短时凭证和服务身份,不给 Agent 进程长期管理员权限。
这是把权限从自然语言里搬回代码和基础设施。
给高风险节点加不可绕过的门
在 LangGraph 里,把付款、提交、删除、发送、变更权限这些动作单独定义成节点。节点入边要校验审批状态,出边要记录结果。人工审批不是聊天里回一句「可以」,而是一个有操作者、时间、对象、过期时间的授权事件。
如果业务不适合人工介入,也至少做双重确认。模型先生成变更计划,独立校验器根据规则检查资源范围和影响,再由执行器处理。两个步骤不要共用一段任意代码,也不要共用一张宽权限凭证。
以失败簇,而不是单条坏回答,来做回归
Agent 的线上质量治理不该只看一批静态 benchmark。每天从真实会话中做脱敏抽样,结合规则和人工复核,把问题归到可行动的失败簇,例如错误选客、过期知识、越权工具调用、审批丢失、重复执行、外部页面误操作。
一个失败簇被修复后,沉淀成固定回归集。以后改模型、改 Prompt、改 Skill、改工具 schema、改工作流,都要重新跑。这样才不会出现一个问题刚修好,换个模型版本又悄悄回来。
这套闭环很像 SRE 做事故复盘。不同的是,普通服务常修异常栈,Agent 还要修目标表达、权限边界、状态转移和评估数据。
有些东西,不能交给 Judge
现在很流行用另一个模型做 LLM Judge。它适合做大规模初筛,也适合发现回复明显跑偏的样本。但它不能替你定义业务真值。
一个 Judge 可以判断回答是否自洽,却未必知道退款金额有没有算错,发送对象是不是本人,或某个合规例外能不能适用。更麻烦的是,如果 Judge 和执行 Agent 拥有相似偏好,它们可能会一起觉得那条捷径合理。
所以高风险业务仍需要人和硬规则站在链路里。业务 owner 定义什么是对,安全 owner 定义什么不能做,工程团队保证这些定义不会在一次工具调用中消失。
Anthropic 在报告里也提醒过一个容易被忽略的点。模型的 chain-of-thought 声称自己只是演示过程,并不能自动证明它真实的行动动机。工程上同理,不要只看 Agent 的解释。看它实际调用了什么、改了什么、留下了什么后果。
行为证据比漂亮的自述可靠。
把那条停不下来的路关在系统外面
这份报告目前披露的案例,Anthropic 说现实影响很小,且没有涉及客户数据或其内部系统。它也认为这些行为不改变对 Claude 对齐状况的整体判断。
这是一份谨慎的结论,我们也该用同样谨慎的方式理解它。既不把低影响案例炒成科幻恐慌,也别用「只是评估事故」把警报按掉。
Agent 走错路的前提,往往不是它突然变坏,而是系统把一条不该存在的路留在了那里。
把权限收窄,把副作用拆开,把高风险动作放进状态机,把每个选择留进 trace。这样即使模型有一天为了完成任务又想绕路,它撞上的也该是一堵清楚、结实、可审计的墙。
这才是让 Agent 真正进入生产之前,团队该先写好的那段代码。
参考资料
- Anthropic, Investigating unintended model actions in our evaluations and internal use, 2026-10-09
- Anthropic, Investigating three real-world incidents in our cybersecurity evaluations, 2026-07-30
- Anthropic, Improving our alignment and security efforts, 2026-08-31
- Anthropic, An alignment assessment of recent cybersecurity incidents, 2026-09-09



