高风险场景下的契约型 AI Agent 设计
Stack Overflow 讨论如何为高风险执行场景设计受限制的 AI agent。涉及 agent 安全治理和权限控制的深度思考。
Stack Overflow 讨论如何为高风险执行场景设计受限制的 AI agent。涉及 agent 安全治理和权限控制的深度思考。
[编者注:本文最初发表于 O’Reilly Media 的 Radar 博客。]
在上一篇文章《智能体 AI 中缺失的一层》中,我提出,AI 智能体需要一个确定性的执行内核——一个具有特权的“内核空间(Kernel Space)”,在每项拟议操作接触现实世界之前对其进行验证。那篇文章重点讨论了执行边界上发生的事情:幂等性、JIT 状态验证,以及与 DFID 关联的遥测。但建立这条边界之后,一个自然的问题随即出现:究竟是谁在跨越它,又是依据什么权限?
本文聚焦于一类范围更窄、要求更高的系统。我们讨论的不是 RAG 聊天机器人、研究副驾驶,也不是仅用于检索和总结信息的轻量级助手。我们的目标是高风险智能体系统:获准通过转移资金、变更基础设施或修改关键记录来改变外部状态的系统。本文介绍的方法并非通用型智能体框架,而是一种面向具有副作用系统的强制执行模式。
高风险 AI 系统必须围绕责任而非能力来设计。
业界目前给出的答案并不令人满意:人在回路(Human-in-the-Loop,HITL)。在开发环境和低频流水线中,将不确定的决策交由人工处理尚且合理。但在规模化运行的生产系统中——数十个智能体每小时做出数百项决策——它就会成为“可扩展性陷阱”。
从运营角度看,其失败过程很简单。一个智能体将某项决策标记为需要审核。人工批准了它。紧接着又来一项,然后是几十项。队列不断增长。审核人员开始一路点击处理。他们不再阅读 JSON 载荷。因为积压越来越多,会议十分钟后就要开始,而且到目前为止还没有发生灾难性事故,所以他们直接点击“批准”。这就是告警疲劳:治理退化成了人工吞吐量管理。问题不在于人性弱点,而在于治理层的技术债——太多二元决策被塞进了人工队列。
Tyler Akidau 在《Posthuman: We All Built Agents. Nobody Built HR.》中概括了这一更广泛的问题,也呼应了 Tim O’Reilly 对 AI 时代所缺失协议的呼吁:业界在智能体能力上投入了大量资源,却远未同等重视用于治理权限、约束和问责的基础设施。
可扩展的 AI 并不意味着招聘更多审核人员来监督更多机器人,而是要彻底改变治理模式。具有可扩展性的替代方案是“例外治理(Governance by Exception)”:由人类设计策略,运行时负责执行,只有真正的例外情况才会被升级处理。
企业 AI 的主流思路只关注一个问题:这个智能体能做什么?它拥有哪些工具?它可以调用哪些 API?这就是能力视角。它很自然,也很直观,但对于生产系统而言,这种视角完全错了。
在组织设计中,角色是稳定且经过分配的。与传统软件中的基于角色的访问控制(Role-based access control,RBAC)非常相似,它定义了某人获准做什么,而不取决于此人碰巧正在执行哪些任务。我们无法规定一个人如何思考,但可以严格限制其获准从事的行为。责任声明明确表达了这条边界。可是不知为何,我们在软件领域忘记了这一区别,寄希望于原始智能——更好的模型、更严密的提示词、更完善的对齐——能够成为一道足够可靠的护栏。
在一些企业领域中,二者的区别会更加清晰:
金融:能力是“能够执行股票交易”。责任是“获准执行单笔不超过 50,000 美元的交易,仅限高流动性股票,且每日最大回撤不得超过 2%”。
医疗运营:能力是“能够重新安排患者预约”。责任是“获准在 14 天的时间窗口内重新预约非紧急门诊,并严格避免专科医生的时间重复预订”。
供应链:能力是“能够重新规划货运路线”。责任是“获准对非危险品货物进行改道,产生的 SLA 违约成本最高不得超过 5,000 美元”。
在智能体会接触资金、医疗记录或实体物流的系统中,这两种表述之间的差距,就是演示原型与生产部署之间的差距。
当前范式通常使用提示词来弥合这一差距。给 LLM 一个 API 密钥,告诉它“谨慎控制仓位规模”,然后期待模型在面对对抗性输入、异常市场状况以及边缘案例诱人的逻辑时仍能保持对齐。在低风险场景中,这或许可以接受。但在会对现实世界产生副作用的高风险系统中,这并不是一个充分的控制面。
这种区别并非新问题。分布式系统在几十年前就解决过类似的问题。
Carl Hewitt 于 1973 年提出的 Actor 模型为我们提供了一个很有用的基础。Actor 是独立的计算实体,拥有自己的状态、行为和消息接口。Actor 之间不共享状态,仅通过传递消息进行通信。关键在于,Actor 的行为是有边界的——由它所接受的消息来定义,而非由一组开放式的能力来定义。
面向责任的智能体(Responsibility-Oriented Agent,ROA)并没有发明一种新的分布式系统原语。相反,它围绕不可预测的 LLM 核心,组合了多种经过验证的模式——有界 Actor、RBAC 风格的权限包络、审计轨迹以及执行边界验证。实际上,与完整的计算 Actor 相比,ROA 更接近决策 Actor:它维护自己的内部状态,但不会直接改变外部世界。在稳定的角色、固定的任务以及可由机器强制执行的契约之内,它接收业务事件,结合相关上下文进行推理,并生成一个 PolicyProposal,交由运行时验证。
它的职责是认知性的,而非执行性的。它负责解释情况并结构化地表达意图。但与传统 Actor 不同,ROA 智能体由严格的关注点分离来定义。在其参考形态中,凭据位于智能体无法触及的范围之外。它不会打开任何通往外部系统的直接执行通道,也不会自行写入任何状态。ROA 智能体可以使用工具来收集上下文,例如在其沙箱内执行只读操作、查询知识库;但改变状态的操作权限仍位于下游,必须经过确定性的验证与执行门控。唯一可归因于智能体的状态变更步骤是 emit_policy_proposal()——一种结构化、具有明确类型的声明,表示它希望系统执行某项操作。ROA 负责塑造意图的形式;运行时决定该意图是否获准转化为行动。
这种分离是该架构最重要的特性。五大工程支柱定义了它在实践中的具体含义——每个支柱分别应对推理与执行边界上的一种不同故障模式——它们共同将 LLM 从概率性工具转变为可治理、可问责的系统组件。
举个具体例子:假设伦敦商业保险市场中的一个承保智能体收到了一份房产投保材料。它阅读文件并生成一段 Explain 说明,然后针对报价生成一个 PolicyProposal。但该房产价值为 1,500 万英镑,而其契约规定的权限上限为 1,000 万英镑。提案到达内核后,运行时以确定性方式评估 YAML 契约,拒绝执行,并将流程转换为 ESCALATED 状态。此时,高级核保人员不必再审核每一份价值 200 万英镑的材料,只有遇到这笔特定的 1,500 万英镑例外时才会收到通知。这就是通过一次决策实现的“人在回路之上(Human-Over-The-Loop)”。
如果说角色定义了智能体可以处理的决策类别,那么责任契约(Responsibility Contract)则定义了其权限的硬性边界。智能体的权限包络不是提示词,而是一份经过版本控制、可由机器读取的契约,它注册在智能体注册表(Agent Registry)中——后者是内核关于智能体身份的唯一事实来源。这里有一条关键原则:提示词只是建议,代码才是强制执行。提示词中的“每笔交易不得超过 10,000 美元”可能会被一个动机足够强烈的模型创造性地重新解读,也可能被精心构造的提示词注入覆盖。相比自然语言指令,由确定性运行时代码验证的契约字段 max_order_size_usd: 10000.0 在实质上更难绕过。在参考架构中,契约通过带外方式部署——智能体不能自行注册,也不能读取或修改自己的契约。
这一设计还有一个容易被忽视的二阶影响:角色定义会自动限定智能体所需的数据上下文范围。如果某个核保智能体依据合约,只能处理 LOW 和 MEDIUM 风险等级的 HOME_STD 与 HOME_PLUS 保单类型,那么在每次推理调用前组装智能体工作快照的 Context Compiler,只需提供与这些维度相关的信号。商业地产的市场数据、被排除风险等级的洪水区统计数据,以及其他产品线的监管数据,根本不在其范围之内。上下文由合约以确定性的方式缩小。
这背后有一个具体的 LLM 工程原因。在实践中,随着工作上下文不断扩大,模型往往会变得不那么可靠,其中就包括从业者所说的 Lost in the Middle 这类效应。严格限定范围的角色不仅仅能为治理带来便利,它还是一种架构机制,可以把智能体的工作上下文控制在足够小的范围内,使其能够可靠地进行推理。与在明确领域内运行、受到合约约束的智能体相比,一个拿到不受限制的上下文窗口、其中塞入所有可能相关信息的通用智能体,更容易出现性能退化。
在保险核保示例中,可以像这样配置 Responsibility Contract:
agents:
- agent_id: "underwriter_agent"
version: "1.0.0"
created_by: "compliance@example.com"
created_at: "2025-02-17T10:00:00Z"
mission: |
You are an insurance underwriter. Analyze the client application and propose
a policy. Base premium on Total Insured Value (TiV) at ~2% of TiV, capped at max_tiv.
NEVER propose for Fireworks or CryptoMining industries - these are prohibited.
contract:
role: EXECUTOR
max_tiv: 3000000
prohibited_industries: ["Fireworks", "CryptoMining"]
escalate_on_uncertainty: 0.65
Mission 在运行时不可变。如果说 Responsibility Contract 定义了智能体可以做什么,那么 Mission 则定义了它试图在这些边界内优化什么。这一区别在运营层面非常重要:Contract 定义了允许的行动空间,而 Mission 定义了该空间内的排序逻辑。Contract 回答的是“可以做什么”;Mission 回答的是“应该做什么”。两个智能体可以拥有相同的权限边界,但仍然针对不同的业务结果进行优化,前提是两者都始终处于同一个硬性边界之内。
在 ROA 架构中,Mission 是一种包含两个表面的部署产物:一个是供智能体用作推理指引、便于人类阅读的 mission_statement,另一个是供 Runtime 强制执行完整性检查、可由机器验证的 mission_context_hash。
mission_statement: "Minimize SLA penalties in logistics rerouting. Prioritize low-cost carriers."
mission_context_hash: "sha256:a3f9b2c1..." # Kernel-computed at deployment time, strictly immutable
确定性的 Kernel 不会解释 mission_statement 文本。智能体在内部使用该文本作为推理指引,而 Runtime 则通过比较提案中的 mission_context_hash 与 Agent Registry 中注册的不可变值来强制保证 Mission 的完整性。如果提示词注入或运行时漂移改变了智能体的目标,哈希值将不再匹配,提案便会在不进行语义解释的情况下被拒绝。哈希只是其中一种实现方式;真正的要求是在边界处以确定性的方式保证完整性。
Mission 在部署时定义,只能通过有意进行、受版本控制的合约更新来演进,而不能通过调整提示词、用户反馈或运行时协商来改变。实际上,Mission 将优化策略置于变更控制之下。一个 Mission 会随着每次对话发生漂移的智能体,并不是持久的生产行为主体;它只是一个会话。
如果 Contract 定义边界,Mission 定义目标,那么 Epistemic Isolation 定义的就是唯一可接受的输出形式。ROA 智能体只能通过结构化、带类型的 PolicyProposal 产物与外部世界交互。智能体的输出是一项不受信任的主张——它声称希望系统执行某个操作——而 Runtime 会严格将其视为这种性质的内容。
正是这一特性,使 ROA + Runtime 模式在抵御提示词注入方面具有实质性优势。如果某次注入绕过了 LLM 的推理护栏,被破坏的输出仍然会以带有 agent_id 的类型化提案形式抵达。如果提案要求转移资金,但智能体的合约并未授予这项权限,Runtime 就会以 RBAC_DENIED 拒绝它。安全性来自执行边界处的确定性强制约束,而不是对 LLM 对齐能力的信任。
为了在概率性思考与确定性主张之间建立清晰的桥梁,ROA 智能体通过一种结构化的内部工作流生成决策,并严格区分 Explain 与 Policy:
Explain:智能体解释上下文,并用自然语言阐明当前情况(例如,“Flood risk score 3/10...”)。这会为人工审计人员生成一份叙事性产物。系统绝不会解析它来生成执行逻辑。
Policy:智能体生成结构化的 PolicyProposal,其中包含 Runtime 能够以确定性方式验证、与执行相关的字段。在核保示例中,它看起来如下:
proposal = PolicyProposal(
total_insured_value=2_750_000,
premium=55_000,
industry="Commercial Property",
justification="TiV remains below delegated max_tiv and no prohibited industry indicators were found.",
confidence=0.81,
)
约束字段(total_insured_value、premium、industry)用于驱动确定性验证,而 justification 和 confidence 则保留为用于审计与升级处理的可观测性元数据。
这种分离使证据模型变得清晰:叙述内容保持人类可读,策略保持机器可执行,并且二者都可以绑定到同一个决策谱系,同时避免自由文本渗透到执行逻辑中。
当智能体拥有稳定的角色、固定的 Mission 和严格规范的输出接口后,跨决策周期的连续性才真正具备意义。这是实际实现中最缺失的支柱,也是造成某类生产故障的首要原因:无限拒绝循环。
ROA 智能体并不是无状态的推理调用。它们是长期存在的实体,会在多个周期中维持一条决策轨迹——一份由 Kernel 管理的记录,其中包含先前的提案、提案的验证结果,以及这些决策造成的业务后果。
约束权限的同一套范围限定逻辑,也决定了记忆是否有意义。在稳定角色范围内运行的长期智能体,会积累来自相同决策类别、相似约束条件的历史记录,因此过去的行为及其结果之间确实存在因果关联。一个接收互不相关任务的通用助手或许仍能发现某些模式,但这些相关性在运营层面通常并不可靠。聚焦的职责才是区分智能体记忆中信号与巧合的关键。
这种机制所防止的故障模式有一个名称:决策失忆。缺乏长期连续性时,智能体会反复表达同一个已被拒绝的意图,因为上一次拒绝并未成为下一个决策周期的一部分。
每个 PolicyProposal 都携带一个 Decision Flow ID(dfid),用于将其绑定到完整的决策上下文。它并非简单地倾倒非结构化日志,而是构建了一种用于重建的基础结构——一条连接以下内容的关系型轨迹:
输入:智能体进行推理时所依据的精确 Context Snapshot(T0)。
验证:根据 Responsibility Contract 评估得出的结果。
结果:最终的执行回执。
借助这条相互关联的记录,只需对整个决策生命周期执行标准 SQL join,就能回答:“这个智能体为什么会在这个特定时刻、基于当时世界的何种状态做出这个决定?”在保障要求更高的部署环境中,还可以将同一套结构化遥测数据封装成带有加密签名的携带证明的意图,从而独立验证决策产物,无需要求任何人信任可能被修改的文本日志——这正是 EU AI Act 等高风险合规制度正在推动的方向。
不过,结构化决策遥测的作用并不止于支持日常事后分析。每项决策都会成为一条由 DFID 绑定的结构化关系记录,而这套基础同样能在 Agent Drift 等宏观故障于整个智能体集群中悄然累积之前,将其检测出来。
Human-Over-The-Loop——规模化自治
Human-in-the-Loop 的替代方案并不是移除人类,而是将人类从执行循环转移到设计循环。
这就是 Human-Over-The-Loop(HOTL)模型。人类作为 Policy Designer,负责定义并演进治理决策的合约,而系统则在这些边界内自主运行。没有审批队列,也没有审核疲劳。Governance by Exception 才是可扩展的模型。
升级触发器。只有当智能体遇到其合约未授权它自行解决的情况时,系统才会升级处理:
提议的操作超过合约权限限制
智能体置信度低于升级_不确定性阈值
外部 API 错误超过重试预算
在配置的不活跃窗口内没有发出决策
当触发器触发时,DecisionFlow 进入 ESCALATED 状态。操作员看到 WorkingContext、PolicyProposal 和升级原因,可以选择 OVERRIDE、MODIFY 或 ABORT。这不是"批准/拒绝"队列;这是有针对性的干预。
升级不应被理解为证明智能体可靠地知道自己不知道什么。LLM 在判断自身不确定性时表现不佳,因此架构不信任内省。escalate_on_uncertainty 阈值是有用的启发式方法,而非绝对真理:系统在声称的置信度低于阈值或提议违反 Kernel 可确定性评估的合约参数时强制升级。如果模型以高置信度生成了一个糟糕的提议,Runtime 仍然会阻止它。智能体可以表示不确定性;Runtime 决定这种不确定性是否重要。
冻结上下文 + 即时验证。操作员根据智能体在 T0 时刻看到的完整世界快照来审核提议,避免 TOCTOU(检查时间和使用时间的竞态条件)问题:人工使用机器看到的完全相同的数据来审核机器的决策。
但世界在不断变化。在 T1 时刻点击"OVERRIDE"不会盲目执行操作;它强制提议通过 Runtime 的即时验证门。如果现实在 T0 和 T1 之间已经超出合约的漂移范围,Runtime 会拒绝覆盖而不是根据陈旧状态执行曾经有效的意图。
合约演进。对正当边界情况的长期正确回应通常不是重复覆盖,而是合约变更。如果业务现实发生变化,操作员会更新 Responsibility Contract 并部署新版本。系统通过版本控制治理边界而非提示编辑或微调来适应。
升级预算。升级通过每个智能体的令牌桶进行速率限制(例如,每小时 3 次升级)。如果智能体用完预算,Runtime 会将其转换为 SUSPENDED 状态,记录状态变化,并阻止新的 DecisionFlow,直到操作员干预。这防止升级 DDoS 并遏制失控的推理成本。
置信度 ≠ 权限。智能体可能发出 confidence=0.99 的提议,但如果该提议超过合约权限,Runtime 仍会拒绝它。自我评估的确定性不是许可证。
采用 ROA 模式并不意味着放弃工程团队在过去一年掌握的工具。LangChain、AutoGen 和 CrewAI 等框架擅长编排复杂的推理循环、RAG 管道和工具使用。ROA 不是为了与它们竞争,而是为了对它们进行治理。
在实践中,你可以将一个成熟的 LangChain 智能体包装在 ROA 边界内。底层框架仍然处理概率推理(用户空间编排)。架构转变很简单但影响深远:你过滤框架的工具空间。你从 LangChain 智能体的工具箱中物理删除 exchange.execute_trade() 或 db.drop_table()。取而代之的是,你提供一个单一的沙盒化工具:emit_policy_proposal()。智能体进行推理、迭代,最终调用该工具来发出其最终意图。ROA 包装器捕获此声明,可能执行本地自检作为噪声削减启发式,并将 PolicyProposal 转发到 Kernel Space 进行实际强制执行。你保留框架的强大功能,但在重要的地方获得了确定性执行治理。
ROA 不是免费的。它引入工程开销,正因为它用显式治理替代了非正式信任。
验证门和即时验证检查为每个产生副作用的决策增加延迟。
Responsibility Contract 增加设计开销:编写、版本管理、所有权和审查现在必须明确。
DFID 关联的可审计性增加存储、追踪和操作整合工作。
升级阈值和预算需要领域调优;不良的默认设置要么淹没操作员,要么隐藏合法的例外。
这些成本仅在不正确的副作用的代价高于控制成本时才合理。对于 RAG 聊天机器人和低风险助手,这种架构通常是过度的。对于高风险系统,这是构建真正边界的成本。
五根支柱。一个架构承诺:无法被信任来自我治理的智能体必须在治理它的系统内运行。Responsibility Contract 限定权限。Mission 锁定目标。Epistemic Isolation 确保输出是声明而非命令。Longevity 防止系统忘记已学到的内容。Audit 使每项决策都可重构。ROA 模式——使用 Responsibility Contract 而非能力列表、声明而非命令、确定性内核而非非正式提示——将这些组合成单一的可执行边界。意图由智能体结构化。边界由合约强制。遥测由 DFID 积累。人在循环之上模型为真正的例外而非批准队列保留人类判断。它们一起将概率模型转变为可治理的生产主体。
一旦确定性执行边界和 DFID 关联的遥测就位,不同类别的第三天问题就成为可能:哪些智能体保持在限制范围内但悄悄地摧毁利润?哪些决策模式在人类注意到漂移前正当自动暂停?我们如何将任何操作重构到监管标准,治理承载不同风险概况和决策权重的智能体舰队?
责任是缺失的执行治理层——它属于架构中,而非系统提示。
AI 演示的时代已经结束。AI 生产系统的时代正在开始。这些系统不仅将通过其模型的智能而区别开来。它们还将通过其治理的严谨性而区别开来。
本文对 Responsibility-Oriented Agents 和 Decision Intelligence Runtime 及其生产弹性和操作挑战的方法进行了高级介绍。完整的 DIR 规范、ROA 合约架构和参考实现