1. 从两起真实越权事件说起:Agent 安全为什么突然成了焦点
过去大半年,智能体(Agent)从"能聊两句的玩具"迅速变成了"能自己调工具、自己写文件、自己发请求"的执行体。能力上去了,问题也跟着来了。最近圈子里讨论最多的两件事,一件是 Anthropic 相关工具链里暴露出来的越权访问路径,另一件是 OpenAI 侧有研究者做的"上千个智能体协同"实验里出现的失控行为实证。这两件事放在一起看,指向的是同一个核心矛盾:我们给了 Agent 执行权限,却没有给它配一套与之匹配的权限边界和熔断机制。
先把这两件事的性质说清楚,避免被标题带偏。Anthropic 越权事件,本质不是模型"变坏了",而是工具调用链路里的权限校验缺失——Agent 在调用外部服务或读写本地资源时,凭证的作用域过大,导致一个本应只读的操作拿到了写权限,或者一个本应只作用于沙箱内的会话触碰到了宿主环境。OpenAI 千智能体暴走实证,本质也不是模型"觉醒",而是多智能体系统在缺乏全局协调与资源约束时,出现了目标漂移、重复调用、互相触发放大效应,最终表现为请求量爆炸、任务偏离原始意图。
这两类问题的共同点是:它们都不是模型推理层面的 bug,而是系统工程层面的设计缺陷。换句话说,你换一个更强的模型,问题照样存在;你把 prompt 写得再严谨,也堵不住权限配置的漏洞。这就是为什么我说 Agent 安全必须当成一个独立的工程领域来做,而不是附属于"提示词工程"的一个小分支。
我自己的判断是,接下来一年,Agent 安全会从"少数团队的内部规范"变成"上线前的强制检查项"。原因很直接:一旦 Agent 能自主执行写操作、能自主发起网络请求、能自主调用付费 API,任何一次越权或失控都是真金白银的损失,甚至是数据泄露。下面我按"权限边界怎么划""多智能体怎么防暴走""实操怎么落地""怎么自查"四个层面,把这件事拆开讲透。
2. 越权到底发生在哪一层:把 Agent 的权限链路拆开看
2.1 一次工具调用背后其实有四层权限
很多人以为 Agent 越权是"模型不听话",其实真正出问题的地方往往在下面这四层里,而且绝大多数事故发生在第 2 层和第 3 层:
| 层级 | 作用 | 典型越权表现 | 排查优先级 |
|---|---|---|---|
| 模型决策层 | 决定要不要调工具、调哪个 | 选错工具、参数越界 | 中 |
| 工具注册层 | 定义工具的能力与入参 | 工具粒度过粗,一个工具能干太多事 | 高 |
| 凭证与作用域层 | 工具执行时用的身份和权限 | 凭证权限过大、作用域过宽 | 最高 |
| 执行沙箱层 | 工具实际运行的环境 | 沙箱逃逸、访问宿主文件系统 | 高 |
Anthropic 越权事件里最值得警惕的一点,就是工具注册层和凭证层没有对齐。一个工具在注册时声明的是"读取配置",但底层用的凭证却拥有"修改配置"的权限。模型只是老老实实调用了这个工具,越权是系统自己给的。这就像你给实习生一张能开全公司所有门的卡,然后怪他进了财务室——卡是你给的。
2.2 最小权限原则在 Agent 场景下要重新定义
传统的最小权限原则是"给完成当前任务所需的最小权限"。但在 Agent 场景下,任务是不确定的,模型可能在任何一步决定调用任何工具。所以你不能按"任务"来授权,必须按"工具"来授权,而且要做到一个工具一个凭证、一个凭证一个作用域。
具体怎么做,我的经验是三条:
- 凭证下沉到工具级:不要用一个全局 API Key 让所有工具共用。每个工具绑定独立的凭证,读的凭证不能写,写的凭证不能删,删的凭证必须二次确认。
- 作用域按资源路径收窄:文件操作类工具,凭证只允许访问指定目录,而不是整个文件系统。网络请求类工具,凭证只允许访问白名单域名。
- 高危操作强制人工确认:删除、转账、发送对外消息这类不可逆操作,Agent 只能生成"待确认动作",由人点确认后才执行。
注意:很多团队图省事,用一个高权限 Key 打通所有工具,上线初期确实快,但这是把越权风险从"可能"变成"必然"。我见过不止一个项目在压测阶段就因为一个循环调用把生产库写脏了。
2.3 一个可落地的权限配置示例
下面这段是工具注册时的权限声明思路,用伪代码表示,重点是"每个工具独立凭证 + 作用域显式声明":
# 工具注册时显式声明能力与凭证作用域 tools = [ { "name": "read_config", "capability": "read", "credential": "cred_readonly_001", # 只读凭证 "scope": "/app/config/*", # 仅限配置目录 "requires_confirm": False }, { "name": "write_log", "capability": "write", "credential": "cred_write_log_002", # 只写日志的凭证 "scope": "/app/logs/*", "requires_confirm": False }, { "name": "delete_record", "capability": "delete", "credential": "cred_admin_003", "scope": "/app/data/records/*", "requires_confirm": True # 高危操作强制确认 } ]关键点在于:凭证不是给 Agent 的,是给工具的。Agent 本身不持有任何凭证,它只能通过工具间接使用权限。这样即使模型决策出错,它能造成的破坏也被限制在工具声明的作用域内。
3. 千智能体暴走:多智能体系统的失控机制与熔断设计
3.1 暴走不是"觉醒",是正反馈放大
OpenAI 侧那个千智能体实验,很多人看完第一反应是"AI 要失控了"。冷静下来看,它展示的其实是一个经典的控制论问题:当多个智能体互相观察、互相触发,且没有全局节流时,系统会进入正反馈,请求量指数级放大。
举个生活化的例子。一个会议室里 1000 个人,规则是"看到别人举手你也举手"。第一个人举手,第二个人看到就举,第三、第四个看到前两个都举了也举……几秒钟内全场举手,而且没人知道最初为什么举。智能体暴走就是这个机制:Agent A 的输出触发了 Agent B,B 的输出又触发了 A,循环放大,任务早就偏离了,但系统还在疯狂运转。
3.2 三类典型暴走模式
我在实际项目里见过和听说过的问题,归纳下来主要是这三类:
- 循环触发型:两个或多个 Agent 互相把对方当作输入源,形成 A→B→A 的死循环。表现为 API 调用量在几分钟内飙升几十倍。
- 目标漂移型:Agent 在长链路任务中逐渐偏离原始目标,开始"自作主张"地扩展任务范围。比如让它整理文档,它开始自动发邮件通知相关人。
- 资源争抢型:多个 Agent 同时操作同一份资源,没有锁机制,导致数据覆盖、状态不一致。
这三类的共同根因是缺少全局协调层。每个 Agent 都只看到自己的一亩三分地,没有谁负责看全局。
3.3 熔断与节流:给多智能体系统装"保险丝"
要防暴走,必须在系统层面加约束,而不是指望每个 Agent 自己"懂事"。我总结的落地手段有这几个:
| 机制 | 作用 | 实现要点 |
|---|---|---|
| 全局调用配额 | 限制单位时间总调用量 | 按分钟/小时设硬上限,超限直接拒绝 |
| 循环检测 | 识别 A→B→A 死循环 | 记录调用链,检测重复模式 |
| 任务步数上限 | 防止长链路无限扩展 | 每个任务设最大步数,超限终止 |
| 目标一致性校验 | 防止目标漂移 | 每 N 步用原始目标做一次对齐检查 |
| 资源锁 | 防止并发写冲突 | 同一资源同一时间只允许一个 Agent 操作 |
其中循环检测是最容易被忽略但最有效的。实现思路很简单:给每个任务分配一个 trace_id,记录调用链上的 Agent 序列,如果检测到某个序列在短时间内重复出现,就判定为循环,强制中断并告警。
# 简化的循环检测逻辑 def detect_loop(trace, window=10, threshold=3): recent = trace[-window:] # 统计最近调用序列里重复出现的子序列 for length in range(2, len(recent) // 2 + 1): pattern = recent[-length:] count = sum( 1 for i in range(len(recent) - length + 1) if recent[i:i+length] == pattern ) if count >= threshold: return True, pattern return False, None这段逻辑不复杂,但能拦住大部分循环触发型暴走。实测下来,加上这个检测之后,压测环境里的异常调用量下降了九成以上。
4. 把安全做进开发流程:从配置到上线的实操清单
4.1 开发阶段:默认拒绝,显式放行
安全设计的第一原则是默认拒绝。Agent 想调用任何工具、访问任何资源,都必须显式声明并经过审批,而不是默认允许然后事后封堵。这个思路和防火墙的默认策略是一样的:白名单模式永远比黑名单模式安全。
具体到开发流程,我建议在工具注册环节加一道"能力审批":
- 新增工具必须声明 capability(read/write/delete/network)和 scope。
- capability 为 write 及以上的工具,必须经过安全负责人审批。
- 任何工具不得使用通配符作用域(如
/*、*)。 - 工具上线前必须跑一遍越权测试用例。
4.2 测试阶段:主动做越权测试
很多团队的安全测试只测"功能对不对",不测"越权能不能成功"。这是大坑。越权测试的核心思路是:用低权限身份去尝试高权限操作,看系统是否拒绝。
我常用的测试用例设计如下:
| 测试项 | 操作 | 预期结果 |
|---|---|---|
| 只读凭证写操作 | 用 read 凭证调 write 工具 | 拒绝并记录 |
| 越界路径访问 | 访问 scope 外目录 | 拒绝并告警 |
| 高危操作无确认 | 直接调 delete 工具 | 拦截,要求确认 |
| 循环调用 | 构造 A→B→A 链路 | 检测并中断 |
| 配额超限 | 短时间内超量调用 | 限流并告警 |
这些用例跑一遍,基本能覆盖 80% 的常见越权场景。剩下的 20% 靠代码审计和渗透测试补。
4.3 上线阶段:可观测性与应急开关
上线不是终点,是安全运营的起点。Agent 系统必须做到每一步可追溯、每一异常可告警、每一事故可熔断。
- 全链路日志:记录每次工具调用的 Agent、工具名、参数、凭证、结果、耗时。日志要能按 trace_id 串起来。
- 异常告警:调用量突增、越权拒绝次数上升、循环检测触发,都要实时告警。
- 应急开关:必须有一个"一键停用所有 Agent 写操作"的开关,出事时能立刻止血。
提示:应急开关一定要在系统设计初期就做进去,不要等出事再临时加。我见过一个团队因为没做这个开关,出事时只能手动改配置重启服务,多损失了十几分钟。
5. 几个容易踩的坑和我的实际体会
5.1 别把安全寄托在提示词上
这是我最想强调的一点。很多团队的安全策略是"在 system prompt 里写清楚不要做危险操作"。这在演示阶段看着有效,但一旦模型遇到没见过的场景,或者被精心构造的输入诱导,提示词防线很容易被绕过。提示词是软约束,权限配置是硬约束。安全必须靠硬约束兜底,提示词只能作为辅助。
5.2 凭证轮换和审计别偷懒
Agent 用的凭证如果长期不轮换,一旦泄露就是长期风险。我的做法是:所有工具凭证设置有效期,到期自动轮换;同时开启凭证使用审计,任何异常时间、异常来源的调用都能查出来。这件事做起来有点繁琐,但比起事后追责,前期多花的时间完全值得。
5.3 多智能体系统要有人"看全局"
千智能体暴走实验给我们的最大启示,不是"智能体危险",而是"没有全局协调的多智能体系统必然失控"。所以如果你在做多智能体编排,一定要有一个协调者角色,负责配额分配、循环检测、目标对齐。这个协调者可以是独立的服务,也可以是编排框架里的一个中间件,但绝不能没有。
5.4 安全配置要能"热更新"
Agent 系统迭代快,工具经常增删。如果每次改权限配置都要重启服务,团队就会倾向于"攒一批再改",导致配置长期滞后于实际需求。所以权限配置最好做成可热更新的,改完立即生效,这样安全策略才能跟得上开发节奏。
6. 一套可复用的 Agent 安全自查表
最后把我自己常用的一份自查表分享出来,上线前逐项过一遍,能挡掉大部分低级事故:
- 每个工具是否绑定了独立凭证?
- 凭证作用域是否收窄到具体资源路径?
- 高危操作是否强制人工确认?
- 是否设置了全局调用配额?
- 是否有循环检测机制?
- 每个任务是否有最大步数限制?
- 是否有目标一致性校验?
- 全链路日志是否可按 trace_id 追溯?
- 异常告警是否覆盖越权、暴走、配额超限?
- 是否有一键熔断开关?
- 凭证是否有有效期和轮换机制?
- 权限配置是否支持热更新?
这份表看起来简单,但真能全部做到位的团队不多。我的建议是先把前六项做扎实,这六项能覆盖绝大多数实际风险,剩下的可以按团队情况逐步补齐。
Agent 安全这件事,说到底不是技术难题,是工程纪律问题。Anthropic 越权事件和 OpenAI 千智能体暴走实证,本质上都是在提醒我们:能力越强的系统,越需要严格的边界。给 Agent 自由之前,先给它画好圈。这个圈画得越清楚,Agent 才能真正被放心地用起来。