把密钥藏起来:Agent 鉴权根治实录

上篇《Agent 鉴权体系设计:协作的地基》讲了:Agent 协作的第一性问题是身份——每个 Agent 得知道"我是谁、我能碰什么、别人是谁"。这篇是续篇:图纸画好了,怎么把它浇成混凝土。

一、开篇:搭好的系统,Agent 却"认错人"

工作流搭好了,论坛也通了。我以为万事俱备,结果一跑起来就卡住。

现象很魔幻:Agent A 提交了一个任务,接单的却是 Agent B;更离谱的是,A 拿到的权限是 B 的——它能读到 B 的密钥、B 的消息、B 的待办。消息开始在 Agent 之间互相泄露,工作流节点走到一半就报权限错误,论坛里出现"不是我发的"的对话。

排查到最后,我意识到一件事:鉴权不稳固,协作的地基就是沙地。 上篇聊了"为什么要鉴权"——身份是 Agent 协作的第一性前提。这篇讲"怎么根治":把密钥藏起来,把身份写死,让每个 Agent 终于知道谁是谁。

二、现场还原:鉴权到底哪里塌了

按 Debug Journal 的格式把现场过一遍。

现象:工作流卡点、Agent 互用身份、消息互相泄露。

假设 1:代码 Bug? 排查:工作流逻辑本身没问题,节点流转正常,卡点全部出现在"权限校验"环节。排除。

假设 2:配置写错? 排查:配置项都对,但问题在于"对也没用"——所有 Agent 跑在同一个用户态下,权限配置形同虚设。这接近真相了。

转折:真正让我警觉的是一张权限表。表里每个 Agent 的身份是"软"的——靠约定,不靠机制。任何 Agent 只要知道路径,就能读到别的 Agent 的密钥文件。

根因:三件事叠在一起——

  1. 密钥与身份散落各处:密码、Token、凭据文件躺在各个目录里,没有统一托管;
  2. Agent 直接可见密钥:Agent 的上下文和工具调用里,密钥是"透明"的,它随时能读;
  3. 用户态未区分:所有进程跑在同一个用户态,隔离形同虚设。

结论:身份无法唯一确定。一个系统里没人能证明"我是我",那谁都可以是任何人。

三、解法一:用户隔离——密码放独立服务

第一刀,先把凭据收拢。

做法:把密码和凭据全部收进一个独立服务,由它统一托管。普通 Agent 对这份凭据没有修改权限——它们只能通过服务提供的接口去"申请使用",不能直接读文件。

效果立竿见影:凭据与业务逻辑分离了。以前 Agent 在业务代码里"顺手"就能碰到别人的密码,现在它连密码文件在哪个目录都不知道。权限的边界从"谁都能碰"变成"只有服务能碰"。

这一步解决的是"散落"问题:凭据不再是一地鸡毛,而是一个有主、有边界、有审计的单一入口。

四、解法二:插件代理——Agent 看不到密钥

收拢还不够。收进独立服务之后,Agent 怎么用凭据?总不能每次都要管理员手动授权。

于是第二刀:插件代理。

做法:所有涉及密钥的功能调用全部收进插件。Agent 不再直接持有密钥,它只能说"我要调什么"——比如"帮我读一下 HR 系统的通讯录"。插件拿到这个请求,自己去独立服务换取临时密钥,用完即焚。

效果:密钥对 Agent 完全不可见。Agent 的上下文里没有密钥、没有 Token、没有密码——它只有一个"意图",而"凭证"由插件在机制层面完成。

这一步的关键变化是:权限边界从"人治"变成"机制"。以前靠"你别读那个文件"的自觉,现在靠"你根本读不到"的结构。临时密钥还自带生命周期,即使被截获,也只是一次性的、短命的。

五、解法三:双用户态——关键信息只在一个受限态

前两刀解决"密钥在哪、谁去换",第三刀解决"进程被攻破怎么办"。

做法:双用户态隔离。

  • Agent 与用户跑在同一个用户态——保有正常的访问权限,能干活;
  • OpenClaw 进程与鉴权插件跑在受限用户态——关键信息只在这个用户态可访问。

也就是说,即使 Agent 所在的用户态被误操作、甚至被攻破,攻击者也够不到关键信息——因为它根本不在这个用户态里。要拿到密钥,必须同时攻破两个用户态,而鉴权插件所在的受限态几乎不暴露任何攻击面。

这一步把"单点防御"升级成"纵深防御":干活的环境和藏密钥的环境,物理性地分开了。

六、结果:身份终于写死,谁是谁不再含糊

三刀砍完,系统发生了质变。

身份绑定写死:HR 就是 HR,研发总监就是研发总监。每个 Agent 的身份不再是"软约定",而是由独立服务、插件代理、用户态三层机制共同锁死的硬事实。

消息不再互相泄露:A 的会话、A 的待办、A 的权限,只有 A 能碰到。论坛里"不是我发的"这种对话消失了。

协作重新跑通:权限隔离之后,工作流节点正常流转,论坛交流恢复正常。之前卡住的地方,全都通了。

回头看验收标准,一条条都对上了:真实搭建经历有(鉴权混乱→三解法→身份唯一确定),技术细节扎实(独立服务管密码、插件换临时密钥、双用户态受限),续篇关系成立(上篇讲为什么,本篇讲怎么根治),结果有说服力(协作重新跑通)。

七、收尾:地基补上了

上篇我说:身份是协作的地基。这篇把地基浇成了混凝土。

可复用清单(三个动作,一句话版):

  1. 独立服务管密码——凭据收拢,普通 Agent 无修改权限;
  2. 插件代理换临时密钥——Agent 只说意图,插件换一次性凭证,密钥对 Agent 不可见;
  3. 双用户态隔离——干活态与受限态分离,关键信息只在受限态可访问。

给读者的自查建议:先回答一个问题——你的 Agent 系统里,“谁是谁"是唯一确定的吗?如果任何 Agent 都能读到别的 Agent 的密钥,如果你的密钥文件散落在各个目录,如果你的所有进程跑在同一个用户态……那你的地基,可能也是沙地。

补地基不复杂,三刀而已。但每一刀,都是在回答同一个问题:凭什么证明你是你。