site logo

Marico's space

AI Agent 权限继承:让 Agent 无需 API Key 即可行动

AI技术与应用 2026-08-06 17:35:47 5

最近折腾了 AI Agent 的权限继承问题,踩了几个坑,这篇把核心问题说清楚。

当一个 AI Agent 需要做实际工作时,最危险但省事的做法就是给它一个 API Key,然后祈祷 prompt 能管住它。

这条路走不通。一个有用的 Agent 现在可以读取工单、创建 issue、更新 CRM 记录、运行查询、触发工作流、调用内部工具。如果这些都通过一个宽泛的 Key 来做,你有的不是用户权限,而是一个拿着借来的万能钥匙的机器人。

更安全的做法是 AI Agent 权限继承:Agent 以当前用户的受限权限来行动,仅限一个任务,有明确的边界、可撤销、有审计记录。

这篇说说怎么给生产环境的 AI 工具设计这套模式。

为什么现在权限继承变得重要

最近的 AI 平台讨论一直在绕同一个问题:Agent 变得有用是因为它们能行动,而不只是回答问题。但行动需要访问权限。

压力来自多个方向:

  • 内部团队需要跨客服、销售、工程、文档、数据系统工作的 Agent
  • 开发者通过 MCP 服务器、工作流平台、浏览器工具、私有 API 连接 Agent
  • 安全团队看到宽泛的 Key、复制的令牌、在实验中出现 prompt 可见的凭证
  • AI 网关和 Agent 平台在增加可观测性、访问控制、降级和成本控制,因为模型调用正在变成基础设施
  • 围绕 Agent 环境配置错误的安全事故提醒开发者:"测试"和"生产"的边界必须是真实的

实战教训不是"永远不让 Agent 行动"。那太粗暴了。教训是:Agent 应该从用户和任务继承受限的权限,而不是从永久的共享密钥继承

常见反模式:一个 Key 给所有 Agent 用

小团队经常从这个架构起步:

User request -> AI agent -> tool router -> service API key -> internal systems

看起来很快。演示也容易。还避免了 OAuth 的复杂性。但同时也埋下了一堆问题:

问题 实际会发生什么
没有用户边界 Agent 可以访问用户正常情况下访问不到的数据
撤销能力弱 禁用一个用户不会停掉共享的 Key
审计困难 日志显示"agent-service",而不是真正的行动者和目的
prompt 注入爆炸半径大 恶意输入可以引导 Agent,而工具仍然有广泛权限
多租户隔离困难 多租户过滤器变成可选的应用逻辑,而不是强制的策略
密钥暴露 Key 可能通过 trace、错误、截图或调试 prompt 泄露

这不仅是安全问题,也是产品质量问题。如果用户无法理解一个 Agent 被允许做什么、实际做了什么、如何撤销或回滚,那在关键时刻他们不会信任这个功能。

什么是 AI Agent 权限继承

AI Agent 权限继承意味着 Agent 收到一个临时的、任务作用域的授权,这个授权派生自用户的身份、角色、租户、同意和当前工作流。

Agent 不会拿到用户的原始密码。不会拿到宽泛的服务 Key。它收到的是一个委托令牌或权限信封,里面写着:

  • 谁发起了这个任务
  • 属于哪个租户或工作空间
  • 哪些工具可以被调用
  • 哪些记录或资源在范围内
  • 哪些操作是只读、草稿还是可执行
  • 允许多少支出、时间或工具调用
  • 权限何时过期
  • 必须记录哪些证据
  • 什么需要人工审批

一个简单的模型是这样的:

User session -> permission service -> task-scoped delegation token -> agent runtime -> policy-checked tool calls -> audit log + revocation path

核心思想:Agent 的权限不由 prompt 决定。prompt 可以解释任务,但后端强制执行什么被允许。

权限信封

从一个普通对象开始。不要把设计藏在 prompt 里。

{ "delegation_id": "dlg_01J8...", "actor_user_id": "user_123", "tenant_id": "tenant_456", "agent_id": "support_refund_agent", "task_id": "task_789", "purpose": "draft_refund_response", "allowed_tools": ["tickets.read", "orders.read", "refunds.draft"], "resource_scope": { "ticket_ids": ["ticket_234"], "customer_ids": ["cust_987"], "max_order_age_days": 90 }, "action_mode": "draft_only", "budget": { "max_model_calls": 12, "max_tool_calls": 20, "max_runtime_seconds": 180 }, "approval_required_for": ["refunds.execute", "emails.send"], "expires_at": "2026-08-06T10:30:00Z", "policy_version": "agent-policy-v4"
}

这个对象成了产品、安全、工程、支持之间的契约。它也比"只访问用户能访问的内容"这种模糊指令更容易测试。

把工具映射到用户权限,而不是模型意图

Agent 可能会声称它需要一个工具。这个声称不够。

每个工具调用都应该通过一个策略检查,结合:

  1. 用户权限:这个用户在没有 AI 的情况下能执行这个操作吗?
  2. 任务范围:这个资源是当前任务的一部分吗?
  3. Agent 模式:Agent 处于只读、草稿、副驾驶还是自动驾驶模式?
  4. 风险等级:这个操作会转账、删除数据、给客户发邮件、改权限或暴露密钥吗?
  5. 证据:Agent 用来构造参数的来源可信吗?
  6. 预算:这次运行是否超过了工具、token 或时间限制?

一个简化版的 TypeScript 风格策略检查:

type ToolCall = { tool: string; args: Record<string, unknown>;
}; type Delegation = { actorUserId: string; tenantId: string; allowedTools: string[]; actionMode: "read_only" | "draft_only" | "supervised" | "bounded_autopilot"; resourceScope: { ticketIds?: string[]; customerIds?: string[]; }; approvalRequiredFor: string[]; expiresAt: string;
}; function authorizeToolCall(call: ToolCall, delegation: Delegation) { if (new Date(delegation.expiresAt) < new Date()) { return deny("delegation_expired"); } if (!delegation.allowedTools.includes(call.tool)) { return deny("tool_not_delegated"); } if (!userCanUseTool(delegation.actorUserId, delegation.tenantId, call.tool)) { return deny("user_lacks_permission"); } if (!resourceInScope(call.args, delegation.resourceScope)) { return deny("resource_out_of_scope"); } if (delegation.approvalRequiredFor.includes(call.tool)) { return requireApproval("human_approval_required"); } if (delegation.actionMode === "draft_only" && isStateChanging(call.tool)) { return deny("draft_mode_blocks_state_change"); } return allow();
}

注意漏掉了什么:没有"LLM 说这安全"这个分支。

模型可以提议。运行时决定。

使用短生命期的委托令牌

委托令牌应该很无聊。这是夸奖。

好的委托令牌是:

  • 短生命期的
  • 限定在一个租户
  • 限定在一个任务或工作流运行
  • 绑定到用户和 Agent 身份
  • 在 Agent 运行时外部不可用
  • 可撤销的
  • 每次授权工具调用时都记录日志

避免那种变成影子账户的长期"Agent 令牌"。如果需要一个后台 Agent 继续后续工作,持久化工作流状态,然后在重新检查策略后发放新的委托。

对于长时间运行的工作,使用租约:

run starts -> delegation valid for 10 minutes
run pauses -> lease released
run resumes -> policy re-check -> new delegation issued

这有助于处理用户角色变更、客户记录被锁定、租户禁用了集成、或支持经理撤销了审批的情况。

分离读、草稿、执行模式

大多数有用的 Agent 工作流在第一天并不需要完全自主。

使用模式:

模式 Agent 可以做 适用于
只读 搜索、摘要、检查 研究、客服分流、分析解释
仅草稿 准备变更但不应用 邮件草稿、退款草稿、CRM 更新预览
监督模式 审批后执行 账单变更、用户消息、账户更新
受限自动驾驶 在硬限制内执行低风险操作 打标签、路由、丰富、小型内部更新

权限信封应该包含模式。工具处理器应该强制执行它。

不要只依赖 UI 标签。如果产品说"草稿模式",后端必须拒绝状态变更调用。

上线前设计好撤销机制

撤销是很多 Agent 系统变得模糊的地方。

你需要至少四条撤销路径:

  1. 用户撤销:用户取消 Agent 运行
  2. 管理员撤销:管理员禁用用户、角色、租户或集成
  3. 策略撤销:风险引擎因为限制或证据规则变更而阻止运行
  4. 事件撤销:安全团队禁用工具、提供方、连接器或 Agent 类型

Agent 运行时应该在每次工具调用前检查撤销,而不只是运行时开始时。

async function beforeToolCall(call, delegation) { const status = await delegationStore.getStatus(delegation.delegation_id); if (status.revoked) { throw new Error(`Delegation revoked: ${status.reason}`); } return authorizeToolCall(call, delegation);
}

这看起来严格,但能防止 Agent 失败的最坏版本:工作流在用户以为停止后继续行动。

存储委托收据

每个有意义的 Agent 操作都应该留下一张收据。

好的收据回答:

  • 谁发起的?
  • 哪个 Agent 行动的?
  • 哪个权限信封允许的?
  • 哪个工具运行的?
  • 触碰了哪些资源?
  • 操作是读、草稿还是执行?
  • 需要审批吗?
  • 结果是什么?
  • 可以重放、审查或回滚吗?

收据示例:

{ "receipt_id": "rcpt_01J9...", "delegation_id": "dlg_01J8...", "actor_user_id": "user_123", "tenant_id": "tenant_456", "agent_id": "support_refund_agent", "tool": "refunds.draft", "resource_ids": ["order_555"], "decision": "allowed", "approval_id": null, "policy_version": "agent-policy-v4", "created_at": "2026-08-06T10:18:14Z"
}

收据不只是为了审计。它们帮助开发者调试错误输出、支持团队解释 Agent 行为、产品团队判断哪些工作流可以进一步自动化。

内容缺口:大多数指南跳过的东西

围绕 AI Agent、OAuth、MCP、API 安全的高排名内容经常把某一层讲得很好:

  • 如何连接工具
  • 如何存储密钥
  • 如何构建 OAuth 流程
  • 如何添加 prompt 护栏
  • 如何记录模型调用
  • 如何使用 AI 网关

缺失的实战价值是这些层之间的连接。权限继承就是那个连接。

问题不只是"我把密钥存在哪?"而是:

这个 Agent 应该从用户继承什么确切权限来做这个任务,系统如何证明它强制执行了那个权限?

这是小团队应该尽早填补的架构缺口。

实施清单

在给 Agent 访问真实工具之前用这个清单检查。

1. 对每个工具分类

按风险给工具打标签:

  • 读取客户数据
  • 读取内部数据
  • 写草稿
  • 写生产状态
  • 发外部消息
  • 花钱
  • 改权限
  • 访问密钥

如果一个工具无法分类,它就不应该对自主 Agent 可用。

2. 每次运行创建权限信封

不要让 Agent 从 prompt 发现自己的权限。在检查用户会话、租户、角色、套餐、同意和集成状态后,在后端生成权限信封。

3. 把工具调用绑定到可信参数

如果 Agent 想退款一个订单,order_id 应该来自可信的查询或选中的 UI 记录,而不是单纯从自由文本获得。

4. 为高风险操作添加审批门

审批应该显示 diff、来源证据和确切操作。"批准 Agent"太模糊了。"批准退款草稿 order_555 金额 $42.00"才可以审查。

5. 记录收据,不只是 trace

模型 trace 显示 Agent 想了什么。收据显示系统允许了什么。两个都需要。

6. 测试跨租户拒绝

添加回归测试,让 Agent 尝试在错误的租户、错误的客户、错误的记录或过期的委托上使用有效工具。这些测试应该失败并关闭。

7. 给用户一个停止按钮

可见的停止按钮应该撤销委托、取消排队的步骤、阻止同一运行的未来工具调用。

实际用例

客服 Agent

客服 Agent 可以读取当前工单、检查近期订单、起草退款、准备回复。它不能执行退款或给客户发邮件,直到人类审批确切的操作。

分析 Agent

分析 Agent 可以查询用户已经能访问的指标。委托包含行级租户过滤器、指标定义、查询预算和屏蔽列。Agent 不能通过写原始 SQL 绕过分析权限来访问更宽泛的仓库角色。

工程 Agent

编码 Agent 可以读 issue、检查仓库文件、创建分支、起草 PR。它不能轮换密钥、改部署设置或未经审批合并。

销售运营 Agent

销售 Agent 可以丰富线索、起草 CRM 备注、建议下一步。它不能导出完整客户列表或不经同意和速率限制发外联消息。

一个简单的参考架构

[User Session] | v
[Permission Service] ---- checks roles, tenant, consent, integration status | v
[Delegation Token / Envelope] | v
[Agent Runtime] | v
[Tool Policy Gateway] ---- checks tool, resource, mode, budget, approval | v
[Internal Tools / MCP Servers / APIs] | v
[Delegation Receipts + Audit Logs]

这个架构适用于 REST API、MCP 服务器、队列、浏览器操作、SQL 查询或内部 SDK 调用。重要的是每条行动路径都经过策略网关。

要度量什么

追踪揭示权限继承是否正常工作的指标:

  • 按原因分类的被拒绝工具调用
  • 按操作类型的审批率
  • 被撤销的委托
  • 被重用的过期委托
  • 通过的跨租户拒绝测试
  • 每次运行的工具调用数
  • 每个成功委托任务的花销
  • 涉及权限范围过宽的事件
  • 用户信任信号,如审批编辑和取消率

如果每个操作都被批准,你的 Agent 可能限制太严了。如果没有任何操作被拒绝,你的策略可能没有真正在工作。

给开发者的结论

AI Agent 需要访问权限才能有用。但访问不等于给模型宽泛的密钥、隐形的权限或永久的授权。

权限继承给了开发者更好的中间路径:Agent 可以用用户的受限权限行动,针对特定任务,有收据、可撤销、每次工具调用都有策略检查。

这才是从炫酷 Demo 走向用户真正能信任的 Agent 工作流的方式。

FAQ

什么是 AI Agent 权限继承?

AI Agent 权限继承是一种模式,Agent 收到临时、任务作用域的权限,派生自当前用户的权限、租户、同意和工作流模式。Agent 不会收到宽泛的 API Key 或原始凭证。

权限继承和 OAuth 一样吗?

不一样。OAuth 可以是实现的一部分,但权限继承是更广泛的产品和运行时模式。它包括任务范围、资源限制、工具策略、审批门、撤销、预算和审计收据。

AI Agent 可以用服务账号吗?

有时候可以,但服务账号仍然应该被租户、工具、任务和策略约束。一个能做所有事的宽泛服务账号是有风险的。偏好用户发起的工使用用户作用域的委托。

Prompt 能强制执行用户权限吗?

Prompt 可以描述规则,但不应该作为执行层。权限必须在工具调用执行前由后端服务检查。

委托令牌应该持续多久?

保持短。很多交互任务只需要几分钟。长时间运行的工作流应该使用租约,在发放新委托前重新检查策略。

小团队最容易犯什么错?

最大的错误是因为 Demo 更容易就给了 Agent 一个强力密钥。这个捷径通常会产生薄弱的审计日志、糟糕的撤销、大的爆炸半径和跨租户风险。