智能体身份与权限。
当你的智能体调用一个 API 时,它手里握着谁的凭据?事后这个动作又记在谁名下?多数原型的答案是"开发者的密钥"和"没有谁"——这正是它们熬不过第一次安全评审的原因。本条目把常被压成一个的三个问题拆开,并讲清为何在模型出错时,权限是唯一仍然管用的智能体防线。
三个问题,常被混为一谈。
智能体针对真实系统采取的每一个动作,都会引出三个各自独立的问题,而原型通常用环境变量里的同一把 API 密钥回答了全部三个:
- 认证——是谁在调用?向被操作的系统出示的身份。智能体需要一个身份,而"跟其他每个智能体和后台任务共用的那个服务账号"是个很差的身份。
- 授权——这个调用方可以做什么?附着在该身份上的权限。这才是真正限定损害的那个问题,也是最常被搁置成"这把密钥能做什么就是什么"的那个。
- 归属——那件事是谁做的,又是受谁指示?事后的记录。当客户问起自己的记录为何被改动时,"一个智能体干的"不算答案;"用户 X 的请求,智能体 Y 的第 3 版,在授权范围 Z 之下,于 T 时刻"才算。
默认的反模式,是一把被所有用户与所有任务共用的、长期有效、授权宽泛的凭据。它一次性地败在三个问题上:系统分不清各个智能体、智能体能做的远多于任何单个任务所需、而日志上只显示一个身份在做所有事。
委托:代表某人行事。
智能体几乎从不为自己行事。它为某个用户行事,而设计问题在于:这位用户的权限,是如何抵达智能体的。有两种模型:
- 冒充。智能体持有用户本人的凭据,与用户无从区分。搭起来简单,但在两点上是错的:下游系统分不清一个动作出自人还是出自自动化,而且智能体继承了用户能做的一切——包括这个任务用不着的那九十九项权限。
- 委托授权。智能体拥有自己的身份,并被授予一份有范围、有时限的"代表用户行事"的权利——这正是 OAuth 式同意流程与 MCP 授权模型背后的模式。搭建更费事,但是对的:动作可追溯到双方,而且这份授予可以比用户本人的访问权更窄。
由此得出的规则是:智能体的实际权限,应当是"用户可以做什么"与"任务需要什么"的交集——绝不是并集,更绝不是开发者的权限。如果一个客服智能体需要读取订单并在限额内退款,那就授予这些。它不该仅仅因为工程师的密钥能编辑商品目录,就也能编辑商品目录。
同样的逻辑也适用于智能体之间。当一个智能体委托给子智能体时,子智能体应当拿到一份更窄的授予,而不是父级授予的副本。权限在传播中不断变宽,正是小小的失陷演变成大事故的方式。
把最小权限落到实处。
- 按任务定范围,而非按智能体。同一个智能体可能承担许多种工作。请为这一次运行签发凭据、只携带这次运行所需的权限,而不是一次性地把"它将来可能做的一切"的并集配给它。
- 短期优于长期。几分钟就过期的令牌,会大幅削减盗取它的价值,并逼出一条你能吊销的重新授予路径。环境变量里的长期密钥,正是那些最终会出现在追踪、日志与代码仓库里的凭据。
- 把读与写拆开。智能体的多数步骤只是在读。让占多数的探索性步骤跑在一个只读身份上,对少数会改变什么的步骤则另行要求一份更窄的凭据——这就是按后果设闸在权限层的对应版本。
- 让机密处在模型够不到的地方。如果一份凭据在上下文窗口里、在智能体能打印出来的环境变量里,或在智能体掌控的沙箱之内,就当它已经泄露。持久有效的模式是代理:智能体请求一个需要鉴权的动作,由你掌控的组件在智能体够不到的地方把凭据附上去。
- 要有吊销能力。逐智能体的身份之所以存在,一部分原因就是让你能关掉其中一个而不必关掉全部。如果制止一个行为失常的智能体的唯一办法,是轮换一把另外十五个系统也在用的密钥,那你手上并没有紧急停止开关。
为何这是那道撑得住的防线。
多数智能体安全措施都依赖于模型表现正常:审慎的指令、写得很好的系统提示词、一项要求模型自行执行的检查。提示词注入能击穿它们全部,因为它攻击的恰恰是那个被依赖的组件。
权限在种类上就不同:它由被调用的那个系统在模型之外强制执行。一条被注入的指令可以让智能体试图删除生产数据库;它无法赋予那份凭据去这么做的权利。这正是为何权限收窄不是最后才叠上去的合规杂务——对一个"推理可被自身输入操纵"的系统而言,它是真正扛得住的最后一道防线。
与之配套的是记录。每个有后果的动作都需要五个字段:是谁发起的、哪个智能体的哪个版本执行的、依据什么授权、具体改变了什么、以及在什么时候。这就是把"智能体做了点什么"变成一个可调查事件的东西——也正是这份记录,让你能答复客户、满足审计、并复盘事故。
智能体身份与证明深入解析讲如何证明是哪个智能体动的手,MCP 鉴权与 OAuth 2.1 具体讲工具服务器的委托流程,而受限范围凭据与审计轨迹两章,讲的则是把两者都跑到生产环境里去。