[控场AI]
· 8 分钟阅读· 4,297 字

Agenthof 开源治理引擎:给 AI Agent 戴上权限紧箍咒

Agenthof 开源治理引擎:给 AI Agent 戴上权限紧箍咒

Agenthof 用独立治理引擎与授权门,让不可信 Agent 的每次调用都可授权、可追溯、可拒绝。

Agenthof 是一个 Apache-2.0 开源治理平面,核心主张是 Agent 永远不可信,其每次请求都必须穿过一道门完成授权、凭据注入与账本记账。系统将治理引擎与 Agent 拆为两个独立程序,Agent 无网络、无密钥,只能通过模型门、工具门、执行门、派生门请求操作;需要按用户隔离的调用时由网关执行 RFC 8693 Token 交换,以发起人身份访问上游。运行后 `agenthof audit` 打印哈希链账本,一次性回答谁授权、哪个 Agent 做了什么、用了谁的密钥、是否有拒绝四个问题。展示使用真实模型逐轮自决而非脚本写死,越界时由门拦截并记录拒绝,证明的是治理而非管道。作者同时坦诚三个局限:该展示不证明容器隔离、不承诺结果、Agent 自述不是证据。

AI Agent 正在你的系统里行动,出了问题却没人能说清——是谁授权的?用了谁的权限?有没有被拒绝? Agenthof 给出了一个可运行的答案。

rss source: From god-mode to governed: an AI agent that can't exceed its grant

Agenthof 是一个用 Apache-2.0 许可的开源治理平面,核心主张只有一句话:Agent 永远是"不可信"的,但它提出的每一次请求都必须穿过一道门(door),由门来授权、注入凭据、写账本。

核心设计:两个程序,一条规则

Agenthof 把系统拆成两个完全独立的程序,这是整个方案的根基:

  • agenthof 是治理引擎,负责 apply、run、audit、investigate。它从不嵌入 Agent,也不决定 Agent 怎么思考。
  • Agent 是一个独立程序(仓库里是一个小型 LangChain Agent)。agenthof 通过 socket 调用它,并用"门"来驱动它:模型门、工具门、执行门、派生门。每一道门负责授权调用、注入 Agent 从未持有的凭据、写出绑定到发起人的人类身份的一条账本事件。

Agent 运行时没有网络,没有自己的密钥。它无法直接调用后端系统,只能向门请求。当它需要操作某个按用户隔离的系统时,网关执行 RFC 8693 Token 交换——把发起人的已验证 Token 换成作用于上游的 Token——然后以发起人的身份调用系统。密钥从不进入 Agent 进程。

RFC 8693 Token 交换是 IETF 定义的一种 OAuth 2.0 扩展,用于在受信任的身份提供方之间交换令牌,让一个主体能以另一主体(或降权后的角色)的身份调用下游服务,而无需暴露原始凭据。在 Agenthof 的场景中,发起人的已验证 Token 是唯一可信的身份来源;网关用它换取作用范围被收窄到上游系统的 Token,Agent 进程本身自始至终不持有、也看不到任何密钥。这样做的关键在于"以发起人的身份"而非"以 Agent 的身份"调用——审计时能直接追溯到人,权限边界由人的授权决定,而非由 Agent 的运行时账号决定。相比给 Agent 分发长期凭据,Token 交换把密钥管理的重心收敛到了网关一处。

读懂回执:四个问题一次回答

运行结束后,agenthof audit <run> 按顺序打印该次运行的账本,这就是回执。以下来自一次真实密闭运行,只省略了时间戳和路径宽度:

run r-85f417c68560e228 — acceptance (role acceptance-operator)
invoked by dana@example.com (oidc, issuer http://127.0.0.1:50737)
status: succeeded
ledger integrity: verified (13 events)
  workflow started
  model fast — 3 prompt / 5 completion tokens
  exec env — exit 0 (runtime) [runtime-attested: refexec env pid 35795 spawn 1]
  tool whoami — args 44136fa3 (token_exchange)
  spawn acceptance-worker/acceptance-sub → run r-e0fc07e8… succeeded (depth 1)
  workflow finished: succeeded

把它映射到四个问题:

谁授权的? invoked by dana@example.com——打在本次运行上,每个事件都属于它,而不是 svc-agent-bot。生产环境中由你自己的 IdP 签发并逐调用验证。

哪个 Agent,实际做了什么? model fast、exec、tool、spawn 每行都由 Agenthof 或操作者运行时第一手写成([runtime-attested: ...]),而非 Agent 自己写。注意没有出现的东西:没有提示词文本,没有补全文本,model fast 行甚至不透露模型请求了哪个工具——模型的选择只以它变成的门事件形式出现。

用了谁的密钥? tool whoami — (token_exchange)。Agent 调用了一个按用户的工具,但网关交换了发起人的 Token,以其身份调用——步骤自身摘要返回 tool whoami: acting as: u-dana。Agent 只持有自己的运行 Token,从未见过任何密钥。

有被拒绝的吗? 本次运行没有,模型只伸手拿了授权允许的东西。把同一工作流指向一个执行允许列表不含该命令的角色,就能看到 Agent 越过授权边界:

exec env refused — command is not on the exec allowlist
workflow finished: succeeded

门说了"不",并且记录了这个"不"。Agent 被告知 refused by policy,模型继续,步骤仍然完成——账本里的一次拒绝是治理在工作,而不是崩溃。

哈希链账本(hash-chained ledger)是一种把每条记录都绑定到前一条记录摘要上的日志结构:第 N 条事件的哈希由第 N 条内容加第 N-1 条哈希共同算出,任一历史事件被改动,其后所有哈希都会失配。因此它提供的是"防篡改可检测"——篡改必然留下可被校验到的痕迹,但结构本身并不阻止写入。audit verify 正是重算整条链并与存档值比对。文中强调"防篡改可检测,而非不可篡改"就源于此:它不能物理上阻止有写入权限的人改动账本,但任何改动都无法隐藏。这是多数审计系统的现实边界。

大多数演示跳过的一点:它不是预先写死的

用脚本很容易造假:让 Agent 按固定顺序调用工具,审计结果自然干净,因为不可能有别的路径。那只能证明管道通了,不能证明治理有效。

Agenthof 的展示去掉了这层保护:一个真实模型拿到 Agent 的实际能力作为工具,逐轮自行决定调用什么。上面那份回执就来自这个循环——当 Agent 越界时,拦住它的是门,不是脚本。

模型驱动不需要新增门类型。模型门只授权逻辑模型名,改写为提供商的名字,并原样转发工具调用对话的其余部分。Agentic 循环不过是更多受治理的模型调用,加上模型选中的那些门——每个都是一手事件。

Agentic 循环指模型在每轮根据当前上下文自行决定下一步动作——是否调用工具、调用哪个、是否继续推理——而不是按固定脚本顺序执行。这与传统函数调用编排的关键差别在于控制流由模型产生,因此路径不可预知,无法靠事先穷举来保证安全。Agenthof 的看法是:与其试图约束模型的"思路",不如约束它实际能触达的每一次调用。把 Agentic 循环拆开看,它无非是一连串模型调用加一串模型自主选择的工具调用,只要让每一次都穿过对应的门并落账,循环再自由也仍在治理边界内。这也解释了为何模型驱动不需要新增门类型——门治理的是调用,而调用的种类是有限的。

三个诚实的局限

信任恰恰建立在坦诚的局限之上:

一、这个展示不证明隔离。 这里的隔离舱是测试替身启动的主机进程,本次运行中没有任何东西证明 Agent 无法自行访问提供商。那些墙是操作者运行时的职责,项目为此保留了独立的基于 Podman 的证明(真正的 rootless 容器、--network none、检查无出口)。

二、它不承诺结果。 真实模型会变化——运行可能跳过某道门、调用两次、走另一条路。承诺更窄也更可测:无论模型做了什么,都受治理并记录在账本上。

三、Agent 自己的摘要不是证据。 Agent 返回一份整洁的"我做了什么"制品,适合阅读但作为证据毫无价值,因为它是不可信的 Agent 写的。证据是门事件,由 Agenthof 和运行时第一手写成。如果两者冲突,账本说了算。而且账本是防篡改可检测,而非不可篡改——文档明确划出了这条线。

无出口网络隔离(no-egress isolation)是容器安全中一种把进程网络完全切断的做法,典型形式是 Podman 的无根容器(rootless container)配合 --network none,使进程既无对外路由也无监听端口。在这种配置下,Agent 即使被模型引导去直连提供商,也会因没有网络路径而失败。文中之所以反复区分"测试替身启动的主机进程"与"独立的 Podman 证明",正是因为后者才能提供这一层面的强保证:前者只是让进程碰巧不访问网络,后者是从内核能力上剥夺网络。治理平面管的是授权与留痕,隔离舱管的才是物理可达性,两者职责不同,不可互相替代。

自己跑一遍

引擎、Agent、展示、密闭 CI 运行和诚实局限页都在 Apache-2.0 仓库里:

# 密闭模式——无 API 密钥、无网络、无容器;固定模型脚本
./scripts/e2e-acceptance-llm-local.sh

# 真实模型——自带兼容 OpenAI 的密钥;模型自己决定
SHOWCASE_PROVIDER_KEY=sk-... ./scripts/showcase-combined.sh

两者都会打印 agenthof audit <run>,然后对父运行和每个子 Agent 执行 audit verify。你的密钥在任何进程启动前已从环境中剥离,只按命令到达主机上的 agenthof 进程——Agent 永远看不到它。

#Agenthof#AI Agent治理#开源治理引擎#RFC 8693 Token交换#Agent权限控制#防篡改账本#零信任Agent
分享:

相关推荐