GitHub周趋势2026W25 | Headroom 压缩 95% Token、NVIDIA 开源 AI Agent 安全扫描器、…
2026-07-28
2026-08-03 0
一个 Agent 已经通过 MCP 发现了工具,生成了符合 inputSchema 的参数,并成功发出一次 tools/call。

这时,这项业务操作算完成了吗?
如果工具只是查询天气、读取本地文件,答案可能接近“是”。但只要工具开始创建退款、修改库存、停用员工账号、批量发送通知或触发生产部署,一次协议调用成功就只代表:请求已经沿着一条技术通道到达某个工具服务。
它还不能单独证明:
这次行动代表的是正确的人; 这个人此刻有权操作这条业务数据; 高风险参数已经得到有效审批; 网络重试不会造成重复扣款或重复退款; 超时之后到底执行了还是没有执行; 部分失败时应该重试、补偿还是人工介入; 事后留下的记录足以回答“谁以什么身份做了什么”; 最终业务状态仍然满足系统自己的约束。因此,企业真正面对的不是“MCP 能不能调用接口”,而是另一个更完整的问题:
这篇文章不把所有问题都塞给 MCP,也不试图再创造一个万能中间层。它只做一件事:把这条执行链上容易混在一起的责任拆开。
MCP 已经解决了工具发现、结构化参数、调用协议、结果返回等重要问题。对于 HTTP 传输,它还有独立的授权规范,用来说明受保护的 MCP Server 如何作为 OAuth 资源服务器工作,客户端如何获取访问令牌,以及令牌为什么必须绑定正确的资源受众。官方安全实践也覆盖了最小权限、会话绑定、凭证保护、沙箱和逐次授权等问题。
所以这里讨论的缺口,并不是因为“MCP 没有安全设计”。
真正的区别在于,协议成功和业务完成回答的是两组不同的问题:
协议成功:一个格式正确的请求,是否被送达给了一个允许当前客户端访问的 MCP Server?业务完成:正确的主体,是否在正确的业务状态下,对正确的对象执行了一次正确的行动,并且审批、幂等、失败恢复和责任证据都与这次行动保持一致?协议可以承载行动,但协议本身不知道:
订单ORD-9001 现在是否还允许退款; 员工 E-1024 是否属于门店 S-18; 这笔订单此前是否已经在另一个入口完成过退款; 退款金额是否超过当前剩余可退金额; 这个审批是否批准的正是即将执行的那组参数。 这些事实更靠近业务领域,而且会随时间变化。它们不能只靠工具描述、模型推理或一次 OAuth 鉴权来推断。
生产链路最容易犯的错误,是把所有组件统称为“Agent 平台”“MCP 网关”或“工具服务”,然后默认这个盒子会自然承担全部安全责任。
更可验证的做法,是先区分五种语义责任:
| 层次 | 主要责任 | 不能被误认为 |
|---|---|---|
| 工具协议与 MCP Server | 工具发现、Schema、协议调用、协议授权和工具执行接口 | 每一条业务对象的最终授权者 |
| Agent Runtime / 编排器 | 理解任务、选择工具、生成参数、维护工作流状态、呈现人机交互 | 可信业务身份的来源,或最终权限系统 |
| 共享执行控制 | 限定可触达能力、装配可信上下文、解释可移植治理意图、绑定审批快照、协调派发、请求去重、记录统一执行状态 | 企业身份提供者、审批权威、事务协调器或全部业务规则的拥有者 |
| 企业身份、策略与审批系统 | 解析可信身份、执行组织策略、判断谁有资格批准某类行动 | 真实业务操作本身 |
| 业务系统 | 强制租户隔离、对象级授权、当前状态校验、业务不变量、事务提交和最终执行决定 | 只要上游说“已审批”就盲目信任的被动后端 |
这五种责任不等于必须部署五个产品。同一个服务可以承担其中多项责任,一个组织也可以把它们拆到多个系统。
关键在于:安全边界应该按照责任来判断,而不是按照进程数量来判断。
把两个责任放进同一个进程,不会让它们自动变成同一件事;把它们拆成多个服务,也不会自动带来安全性。
很多 Agent 权限管理的讨论之所以混乱,是因为大家都在说“有没有权限”,但实际说的是三种完全不同的决定。
这是协议授权问题。OAuth Scope、Token Audience、过期时间、受保护资源元数据等属于这一层。
一个售后 Agent 可能需要 order.read 和 refund.request.create,却永远不应该看见 employee.delete 或 tenant.config.update。
这是 Reach,能力触达范围。它在模型选工具、生成参数之前,就缩小了最大可达攻击面。
这是最终业务 Authority:
操作人属于哪个租户、门店或组织; 订单当前是否可退款; 金额是否在剩余可退范围内; 是否已经存在另一笔成功退款; 当前组织策略是否允许这项操作。只有业务系统,或者拥有同等新鲜业务上下文的权威系统,才能可靠回答这些问题。
三者是互补关系:
MCP 协议授权-> 当前客户端能否访问这个 Server?能力 Reach-> 当前 Agent 场景能否触达这个操作?业务 Authority-> 当前主体此刻能否执行这一次具体行动?一个有效的 MCP Token 不是订单退款授权;一份工具白名单不能替代租户隔离;业务系统保留最终授权,也不意味着可以把所有危险工具都无差别暴露给模型。
这些问题都不是加一个字段或挂一个中间件就能完整解决的。它们是端到端属性:有自然的主要责任方,但必须穿过整条执行链才成立。
Agent Runtime 往往最适合展示确认或审批界面;共享执行层可以暂停派发,并把审批决定绑定到一份规范化请求;企业审批系统决定谁有资格批准;业务系统在真正写入前仍然要再次执行最终授权。
一份有意义的审批绑定,至少应覆盖:
可信主体 能力标识 规范化参数 任务身份如果审批之后参数发生变化,原审批不能静默授权新请求。
因此,“弹过确认框”不等于已经建立审批边界。审批证据必须和将要执行的内容绑定,验证方还必须知道:这份证据究竟由谁签发、谁有资格签发。
Runtime 应在重试过程中保持稳定的请求身份;共享执行层可以对重复提交去重并保存任务状态;业务系统则必须在业务域内执行最终唯一性约束。
以退款为例,共享执行层可以阻止同一个执行请求被派发两次。但只有订单或支付系统才能保证:同一笔业务退款不会从网页后台、定时任务和 Agent 三条不同路径被重复创建。
所以“中间层做了幂等”不能替代数据库唯一约束、业务幂等键或领域状态检查。
写操作不能看到 HTTP 超时就盲目重试,因为“没有收到响应”不代表“对方没有执行”。
一个有状态任务至少应该区分:
accepted -> awaiting_approval -> queued -> running -> succeeded-> rejected-> failed调用方在超时后应该查询或恢复同一个任务身份,而不是重新创造一笔新的业务请求。重试策略可以由执行协调层负责,但重试是否安全,最终仍依赖业务边界上的幂等约束。
普通应用日志主要回答运维问题;审计证据要回答责任问题:
谁发起了行动; Agent 代表的是哪个可信主体; 哪项能力和哪些参数被评估; 哪条策略或哪次审批影响了执行; 谁在什么时间派发了什么; 业务系统最终接受还是拒绝了什么。如果同一个可能被攻陷的 Runtime,既能声称“审批已经发生”,又能书写唯一的审计记录,那么这份记录本质上仍是自述。
更高保证等级下,可能还需要独立签名的审批证据、只追加存储、外部时间基准,或者由业务边界重新验证证据链。
共享执行层可以统一记录格式和任务关联,但不能因为把一条记录命名为“审计日志”,就让自己的声明自动获得独立可信性。
回滚不是任意工具都天然具备的通用能力。
有些动作可逆,有些动作需要显式补偿,有些动作根本无法撤销。真正的恢复语义属于业务操作本身,或者属于理解业务流程的 Workflow / Saga 层。
共享执行层可以保存执行状态、暴露失败,并触发业务系统已经明确定义的补偿路径;但它不能给几个互不相关的 API 标一个 atomic: true,就凭空制造事务原子性。
以“Agent 帮用户发起订单退款”为例,一条可以被审查的路径大致如下:
1. 用户提出退款要求。2. Agent Runtime 选择 refund.create,并提出参数。3. MCP Client 使用协议授权调用可信 Server。4. 执行控制检查当前路由能否触达 refund.create。5. 可信主体从模型参数之外的可信上下文中解析。6. 请求 Schema 与治理条件被评估。7. 如需审批,任务暂停在精确参数快照上。8. 同一任务携带可验证审批证据恢复执行。9. 派发使用稳定的幂等身份。10. 业务系统重新校验主体、租户、订单状态、金额和业务不变量。11. 业务系统提交或拒绝这次操作。12. 结果和证据链都关联到同一个任务身份。这里不存在一个“做完所有安全”的万能节点。模型提出行动,协议承载行动,Runtime 协调行动,企业系统建立身份和策略信任,业务系统授权并提交最终后果。
不需要。
单用户本地工具、只读能力,或者只有一个 Runtime 和少量低后果操作的应用,完全可以把这些控制放在 MCP Server 或宿主应用内部。为了概念完整而额外部署新服务,只会增加运维成本,并不必然提高安全性。
当以下情况逐渐出现时,共享执行控制才更有价值:
多个 Agent 框架或 MCP Client 在调用同一批业务系统; 多个 MCP Server 正在重复实现审批、幂等和审计; 企业希望不同入口共享同一份能力白名单; 任务需要跨人工审批、本地执行器或进程重启暂停与恢复; 执行状态必须在 Runtime 退出后继续存在; 不同工具的治理证据需要统一比较; 业务凭证不应该散落到每一个 Agent 应用中。真正的判断标准不是“我们有没有使用 Agent”,而是:
即便答案是“需要共享控制层”,它也应该保持克制:协调和执行公共控制,不把自己扩张为全部身份、全部策略、全部事务和全部业务真相的来源。
与其笼统地说“支持 Agent 治理”,不如明确这些失败会发生什么:
| 失败情况 | 保守处理 |
|---|---|
| 可信主体缺失或无法验证 | 不派发要求主体的操作 |
| 工具元数据或治理声明不可信 | 不根据它提升权限或放宽限制 |
| 审批证据和精确请求不匹配 | 拒绝执行或重新审批 |
| 超时后执行状态未知 | 查询同一任务,不盲目创建新写请求 |
| 可重试写操作没有幂等身份 | 拒绝自动重试 |
| 业务授权失败 | 返回最终拒绝;上游审批不能覆盖业务权限 |
| 审计存储不可用 | 按操作等级执行明确的 fail-open / fail-closed 策略,不能假装证据已经落盘 |
| 没有定义补偿动作 | 报告不可逆或需要人工恢复,不能宣称支持回滚 |
这些语义才使不同实现之间可以被比较、被测试,也使责任边界在事故发生时不至于消失。
披露:我维护两个探索这一问题的开源项目。
Agent Capability Contract(ACC) 尝试用可移植、操作级声明表达能力 Reach 与治理意图。它不执行工具,不定义企业身份,也不替代业务系统的最终授权。
BailingHub(百灵中枢) 尝试实现一个可自托管的共享执行控制面,在业务工具调用周围处理能力触达、可信主体、审批绑定、任务状态、派发和追踪。它是一个具体实现,不是唯一答案;业务系统仍然拥有最终 Authority。
这张职责地图并不依赖任何一个项目。组织可以把同样的边界实现在 MCP Server、Agent 平台、API 网关、工作流引擎、共享控制面,或者它们的组合中。
真正重要的是,系统能够不含糊地回答:
哪个组件控制工具 Reach? 可信主体来自哪里? 谁判断需要人工审批,谁有资格批准? 审批授权的究竟是哪一份精确请求? 重试如何绑定稳定幂等身份? 谁记录证据,谁能独立验证? 哪个系统执行最终对象级和业务状态授权? 执行部分完成、状态未知、被拒绝或不可逆时会发生什么?MCP 让工具互操作变得现实。从“工具被选中”到“业务后果被安全形成”,仍然是一项必须沿整条链路共同构造的端到端属性。