Agent 条件审批应该写到什么程度,才不会变成另一套规则引擎?

简介: 本文探讨Agent接入业务系统后的审批治理难题,强调需严格区分“审批意图”与“业务授权”。ACC v1采用有界条件模型(仅支持ANY语义与基础操作符),确保跨运行时判断一致,拒绝将复杂策略、组织流程或实时状态校验塞入通用契约,坚守可移植治理契约的最小可信边界。

Agent 能调用业务接口之后,下一个问题往往是“什么情况下必须停下来等人”。真正困难的不是加一个审批按钮,而是划清边界:治理契约应该声明哪些可移植条件,运行时应该控制什么,业务系统又必须保留什么。

当团队用 Dify、MCP、函数调用或自研 Agent 接通一套业务系统后,审批需求通常很快出现。

最初的规则也许很简单:

退款金额超过 1000 元时,需要人工审批。

接着,规则会逐渐变成:

退款金额超过 1000 元,并且客户不是 VIP 时,需要经理审批;
如果订单来自高风险地区,还要经过风控;
如果是全额退款,则由财务复核;
黑名单客户直接拒绝;
夜间发起的退款只能等到次日处理。

于是一个很自然的想法出现了:

既然已经有一份 Agent 能力声明,为什么不把这些规则全部写进去?

如果沿着这条路继续走,能力声明很快就会长出嵌套的 AND、OR、NOT,再加入变量引用、数据库查询、身份属性、时间窗口、审批人匹配、工作流跳转和自定义函数。

最后,它不再是一份不同运行时可以共同理解的能力契约,而会变成另一门尚未被完整定义的业务规则语言。

问题因此不是“条件越多越好”,而是:

条件审批应该表达多少,才能既让不同运行时得到一致的治理意图,又不假装自己能够取代企业的策略引擎、审批系统和最终业务授权?

1. 先把四个经常混在一起的问题拆开

一次 Agent 工具调用进入审批链路时,至少存在四个不同问题。

1.1 这次调用是否需要外部决策

例如:

amount > 1000

这是调用发生之前,可以根据已声明参数判断的治理意图。

1.2 外部决策由谁作出

可能是当前用户、门店店长、财务人员、OA 流程、风控系统或另一个组织。

这是审批所有权和组织流程问题。

1.3 审批过程怎样暂停和恢复执行

有界面的 Agent 可以弹出确认页;无界面的 API Gateway 可以返回待处理状态;异步运行时可以创建审批任务并挂起调用;确定性工作流可以暂停节点。

这是运行时控制问题。

1.4 当前主体最终有没有权执行

审批通过之后,业务系统仍要检查:

  • 当前员工是否有退款权限;
  • 订单是否属于当前租户;
  • 订单状态是否仍允许退款;
  • 可退款余额是否充足;
  • 同一笔退款是否已经执行。

这是最终业务授权,也就是 Authority。

这四件事相关,却不能被压缩成一个 approved: true。

一份可移植的治理契约,最多只能稳定声明第一件事:这次调用是否产生了外部决策意图。

2. 条件审批不是业务授权

假设接口声明了:

approval:
  when:
    - param: amount
      op: ">"
      value: 1000

它表达的是:

当本次调用参数 amount 大于 1000 时,运行时应在执行前创建审批意图。

它不表达:

  • 金额小于等于 1000 时业务系统必须放行;
  • 审批通过后退款一定合法;
  • 调用者具有处理该订单的权限;
  • 当前订单还有足够的可退款余额;
  • 这笔退款没有违反黑名单或监管规则。

条件未触发,只代表这条声明没有要求外部审批。

它不代表业务授权已经完成。

这一区分非常重要。否则,团队很容易把一个轻量的调用前治理判断,错误升级成业务系统必须信任的权限结论。

3. 什么样的条件才适合进入通用契约

一个条件要成为跨运行时可移植的声明语义,至少应该同时满足几项要求。

3.1 输入来自当前调用,而不是私有业务数据库

运行时可以直接得到:

{
   
  "order_id": "SO-1001",
  "amount": 1500
}

因此,它可以一致判断 amount > 1000。

但“退款金额是否超过当前可退款余额”需要查询订单、历史退款和实时状态。不同运行时并不知道:

  • 去哪里获取余额;
  • 用谁的身份查询;
  • 数据多久算新鲜;
  • 查询失败时如何处理;
  • 审批等待期间数据变化后是否重新计算。

这类规则属于业务操作或专门的预检 API,不应被伪装成静态契约条件。

3.2 比较值是明确字面量,而不是未定义的上下文变量

下面的声明容易理解:

- param: amount
  op: ">"
  value: 1000

而下面的写法看似更强,实际上引入了新的协议问题:

- param: amount
  op: "=="
  value: "$order.refundable_balance"

$order.refundable_balance 从哪里来、谁能读取、何时失效、拿不到时怎么办,都没有答案。

一个没有数据来源、授权、时效和失败语义的“变量”,不会增强契约,只会制造可执行的假象。

3.3 条件必须具有确定的类型语义

如果调用参数是字符串:

{
   
  "amount": "1500"
}

运行时不能擅自把它转换成数字 1500 再进行比较。

否则,不同语言和框架可能采用不同的隐式转换规则:

  • 某个 JavaScript 实现认为条件成立;
  • 某个严格类型实现直接报错;
  • 某个实现把非法值当成条件未命中,于是绕过审批。

对治理条件而言,“类型不兼容”不能被安静地解释为“不需要审批”。正确行为是:在调用到达业务操作之前拒绝这次无效调用。

3.4 独立实现必须得到同一个判断结果

如果一条声明在两个兼容运行时中可以分别被解释成“需要审批”和“不需要审批”,那就不是实现自由,而是规范歧义。

审批界面的样式可以不同,审批任务存在哪里也可以不同;但相同参数是否产生审批意图必须一致。

4. ACC v1 为什么使用有界的条件模型

ACC v1 的 approval 可以表达无条件审批意图:

x-agent-capability:
  version: 1
  enabled: true
  scope: refund.create
  approval:
    required: true
    prompt: "Approve refund for order {order_id}?"

approval.required: true 表示每一次调用都需要创建审批意图。

条件规则不能降低这项要求。即使所有条件都未命中,无条件审批仍然成立。

它也可以表达参数级条件审批:

x-agent-capability:
  version: 1
  enabled: true
  scope: refund.create
  approval:
    when:
      - param: amount
        op: ">"
        value: 1000
        label: "退款金额超过 1000 元"
      - param: batch_count
        op: ">"
        value: 20
        label: "批量退款超过 20 笔"

当 approval.required 为 false 或省略时,approval.when 使用 ANY 语义:任意一条条件命中,就创建审批意图。

也就是说,上面的规则表达:

amount > 1000
或者
batch_count > 20

任一成立,都需要外部决策。

如果 approval.when 不存在或为空,则不会产生条件审批意图。

ACC v1 把操作符限制为 >、>=、<、<=、==、!=、in、contains 和 exists。其中:

  • 大小比较只接受数值参数和有限数值字面量;
  • ==、!= 与 in 使用 JSON 类型感知的严格相等;
  • contains 只适用于字符串或数组,数组元素仍按严格 JSON 相等判断;
  • exists 只判断参数路径是否存在,不要求 value;
  • param 必须解析到绑定操作已经声明的输入,不能凭空访问其他上下文。

这套模型不复杂,但它有一个重要性质:审批要求是单调增加的。

  • 增加一条条件,只会增加可能触发审批的情况;
  • 某条条件未命中,不能取消另一条已经命中的条件;
  • 条件规则不能取消 approval.required: true;
  • 模型输出不能把治理元数据改成更宽松的值。

在安全边界中,这种可预测性往往比表达式的丰富程度更有价值。

5. 为什么 v1 不急着加入任意 AND / OR 嵌套

开发者很容易提出这样的需求:

金额超过 1000,并且商品属于电子产品时才审批。

如果只看这一条规则,加入 all 和 any 好像很简单。

但一旦允许通用布尔组合,下一步通常会出现:

(A AND B) OR (C AND NOT D)

再下一步会出现:

  • 嵌套条件的优先级;
  • 缺失字段在 NOT 中的含义;
  • 数组中“任意元素”和“全部元素”的区别;
  • 条件求值错误时是拒绝、审批还是跳过;
  • 新旧运行时忽略未知操作符时是否会降低安全性;
  • 不同语言对数字、空值和集合比较的差异。

这时,规范已经站在通用策略语言的门口。

通用策略语言当然有价值,但它需要完整定义:

  • 表达式语法;
  • 类型系统;
  • 数据来源;
  • 求值顺序;
  • 错误和失败语义;
  • 沙箱与资源限制;
  • 版本与兼容策略。

如果这些内容没有被完整定义,只增加几个看起来灵活的字段,反而会让实现者产生“规则已经被可靠执行”的错觉。

因此,ACC v1 选择有界的 ANY 条件,不是在否认复杂策略的存在,而是在拒绝用半套表达式语言冒充可移植标准。

需要复杂布尔策略的部署,可以在明确的运行时策略命名空间中使用 OPA、Cedar、自有规则引擎或其他成熟方案;但它们的结果不能被伪装成所有 ACC 运行时都必须理解的核心语义。

6. 为什么这些规则不应该写进条件审批

下面几类常见要求都很重要,但不属于通用条件审批声明。

6.1 黑名单客户直接拒绝

这是业务拒绝规则,不是审批意图。

黑名单数据的来源、更新频率、申诉机制和最终效力都由业务系统掌握。即使 Agent 运行时提前发现风险,业务系统仍必须在所有调用路径上执行同一规则。

6.2 退款金额不能超过当前可退款余额

这是依赖实时业务状态的跨字段不变量。

它应由退款操作或业务预检 API 验证,而不能依赖运行时持有一份可能过期的订单快照。

6.3 超过 5 万元由总监审批

“超过 5 万元需要外部决策”可以是可移植声明;“由哪位总监审批”则依赖组织目录、岗位代理、休假委托和企业流程。

前者可以属于能力契约,后者属于审批所有者。

6.4 审批 30 分钟后过期

有效期涉及时钟来源、等待队列、重试、跨时区和失效后的恢复方式。它应由审批协议或部署策略完整定义。

简单增加一个时间字符串,却让旧运行时忽略它继续执行,会造成安全意图降级。

6.5 只有工作日 9:00 到 18:00 才允许执行

时间窗口需要时区、节假日日历、可靠时钟和失败语义。它是有价值的运行时策略,却不因此自动成为通用核心字段。

关键不是这些需求“高级”或“不重要”,而是它们分别依赖不同的权威数据和执行责任。

7. 审批意图为什么不等于审批工作流

同一份审批声明,可以被不同类型的运行时一致理解,却以不同方式兑现:

运行时形态 可能的实现
带 UI 的 Agent 应用 展示结构化确认页并等待决定
无 UI 的 API Gateway 返回待审批状态和后续查询入口
异步任务系统 创建审批任务并挂起执行
确定性工作流 暂停当前节点,收到外部决定后恢复
企业控制面 接入现有 OA、工单或业务审批系统

这些实现不必拥有相同界面、数据库和任务状态机。

它们需要一致的是:

在相同声明和相同调用参数下,是否必须先取得外部决策,再进入业务执行。

ACC 因此声明 approval intent,而不定义:

  • 谁来审批;
  • 审批人如何匹配;
  • 是否需要多人会签;
  • 审批 UI 长什么样;
  • 任务如何持久化;
  • 超时后怎样升级;
  • 批准后由哪个队列恢复执行。

这些是运行时和企业流程真正应该拥有的自由度。

8. 审批通过,也只能批准被看见的那一次调用

条件判断解决的是“是否需要外部决策”,还没有解决“批准的究竟是什么”。

如果审批页面展示的是:

{
   
  "order_id": "SO-1001",
  "amount": 1500
}

审批通过后,Agent 重新推理成:

{
   
  "order_id": "SO-1001",
  "amount": 15000
}

原审批不能授权这组新参数。

一个可靠运行时通常需要:

  1. 在创建审批意图前校验并冻结能力标识和调用参数;
  2. 将审批决定绑定到被审阅的精确调用;
  3. 防止批准被另一组参数复用;
  4. 默认把批准作为一次性消费;
  5. 区分拒绝、过期、执行失败和业务系统拒绝;
  6. 恢复执行时再次核对调用快照。

这些属于实现安全属性和配套审批协议,不是 approval.when 本身能够证明的事情。

同样,一条由运行时自己写入的“已审批”日志,也不自动构成第三方可验证证据。高保证场景还需要定义规范化序列化、签名者、密钥发现、时效、重放保护和失败关闭行为。

通用契约应该明确自己的非保证,而不是用一个字段暗示整条证据链已经成立。

9. 一条完整的条件审批链路应该怎样工作

把各层重新组合,一次调用可以经历下面的顺序:

Agent 选择能力并提出参数
  -> 按绑定协议的输入 Schema 校验参数
  -> 解析可信行动主体
  -> 评估能力范围与运行时策略
  -> 评估 risk 与 approval 意图
  -> 条件命中时冻结本次调用并创建审批意图
  -> 由外部审批所有者作出决定
  -> 核对决定绑定的能力、主体和参数
  -> 恢复被批准的精确调用
  -> 业务系统按实时权限和业务状态作最终授权
  -> 记录结果、拒绝或失败

在这条链路中:

  • 模型可以提出工具和参数,但不能批准自己;
  • 契约可以声明审批意图,但不能任命企业审批人;
  • 运行时可以暂停和恢复,但不能替代业务最终授权;
  • 业务系统可以拒绝已经审批的调用;
  • 审批系统可以作出决定,但不能悄悄改变被批准的参数。

责任边界越清楚,系统越不需要依赖某一个“万能组件”。

10. 六个常见误区

误区一:把审批要求写进系统提示词就够了

提示词可以改善模型行为,不能成为执行层的信任边界。

误区二:条件未命中就代表调用已获授权

条件只决定是否产生审批意图,最终 Authority 仍属于业务系统。

误区三:字符串 "1500" 可以自动当成数字比较

治理条件必须使用严格、类型感知的比较。类型不兼容应在执行前被拒绝。

误区四:条件越复杂,契约越专业

没有完整语法、数据协议和失败语义的复杂表达式,只会增加跨实现歧义。

误区五:批准“退款”就等于批准之后任意退款参数

审批必须绑定被审阅的精确能力和调用参数。

误区六:审批通过后业务系统必须执行

订单状态、租户隔离、余额和当前主体权限仍由业务系统实时判断。

11. 一份最小设计检查表

在为 Agent 工具增加条件审批时,可以先回答下面的问题:

  • [ ] 条件是否只读取当前调用中已经声明、已经校验的参数?
  • [ ] 比较值是否是明确字面量,而不是来源不明的上下文变量?
  • [ ] 每个操作符是否具有严格、跨语言一致的类型语义?
  • [ ] 类型不兼容时是否在业务执行前拒绝,而不是按“未命中”放行?
  • [ ] 无条件审批是否不会被条件规则取消?
  • [ ] 模型输出是否无法修改风险、主体和审批治理元数据?
  • [ ] 审批意图是否与审批人、UI 和工作流实现保持分离?
  • [ ] 审批决定是否绑定精确能力、主体和参数快照?
  • [ ] 审批通过后,业务系统是否仍执行最终授权?
  • [ ] 需要复杂业务规则时,是否交给有权威数据的策略或业务层?

如果这些问题没有被回答,“加了审批”往往只意味着系统多了一个页面,还没有建立可靠的行动边界。

12. 结语:好的条件审批不是表达一切,而是只承诺能够一致兑现的部分

Agent 进入真实业务系统后,条件审批确实是不可回避的治理需求。

但标准化的价值不在于把企业所有规则搬进同一份 YAML,而在于找到一组不同运行时都能一致理解、验证和执行的最小公共语义。

对于条件审批,这个最小语义可以非常克制:

  • 条件只读取已声明的调用参数;
  • 只与明确字面量进行类型严格的比较;
  • 任一独立条件命中就产生审批意图;
  • 无条件审批不能被条件取消;
  • 审批意图不冒充审批流程;
  • 审批通过不冒充最终业务授权。

复杂策略、组织流程和动态业务状态都是真问题。但尊重这些问题所属的层次,比把它们全部塞进契约更专业。

一份行业契约最难的地方,从来不是还能增加多少字段。

而是它是否有足够的纪律,只声明那些自己真的能够跨系统兑现的承诺。


延伸阅读

  • ACC 规范:SPEC.md 中的 approval 语义
  • ACC 设计边界:DESIGN_RATIONALE.md
  • ACC 实现者指南:审批意图、调用冻结与恢复参考流程
  • 前序拆解:风险分级应该描述操作,还是直接规定审批流程?
  • 前序拆解:Agent 代表谁行动,可信主体为什么不能来自模型输出?
相关文章
|
3月前
|
存储 数据采集 人工智能
企业AI知识库不是套个ChatGPT
企业AI知识库绝非简单对接ChatGPT!它需私有化部署、六层架构(采集→存储→处理→索引→检索→应用),支持混合检索、RAG增强、物理级数据隔离与知识图谱推理,确保安全、精准、实时——这才是真正可用的企业级AI知识中枢。(239字)
263 0
|
15天前
|
人工智能 安全 API
AI断线以后,这笔退款还要不要再做一次?
客服处理退款时遇断网,“正在处理”状态难辨成败。AI需凭原操作标识续办,而非盲目重试;须区分“查结果”与“再执行”,依赖业务接口幂等保障,确保资金安全、过程可溯。
|
19天前
|
人工智能 自然语言处理 安全
AI 把任务做完了,为什么企业还不能放心?
AI代班项目跟进,表面“完成”易,组织认可难。企业真正需要的“完成”,是结果可信、权限合规、状态可验、接手无忧——让假期归来者无需重做,即可直接开会推进。
|
1月前
|
人工智能 自然语言处理 安全
企业想让 AI 操作业务后台,RAG、MCP、工作流和 Agent 控制面怎么选?
企业为CRM/ERP等系统加AI助手时,常混淆RAG、OpenAPI、MCP、工作流与Agent控制面——它们并非互斥选项,而是分层协作:RAG解决“知道什么”,OpenAPI定义“接口如何调用”,MCP实现“工具如何发现”,工作流编排“步骤如何执行”,控制面保障“操作为何可信”。关键不在选技术,而在判后果:仅问答?用RAG;需查数据?加API;要改业务?必配控制面。
|
1月前
|
存储 人工智能 安全
一个本地 AI Agent 要操作多个门店或 SaaS 账号,应该怎样安全切换身份?
本文深入剖析多账号智能体的身份管理本质:非简单下拉切换,而是涵盖授权、凭据、会话、工具与权限的全生命周期治理。强调浏览器真实登录态、PKCE安全授权、连接独立存续、会话身份绑定及操作系统级凭据保护,确保多门店共存、显式切换、零上下文串用。
|
1月前
|
存储 文字识别 算法
RAG全链路设计:文档解析、Chunk策略、向量+BM25混合检索、高效召回、重排序22.1
本文系统剖析RAG全链路核心环节:文档解析、Chunk分块、双路检索、结果融合与重排序。指出效果不佳主因常在检索设计而非模型能力,并提供各环节原理、误区、调优策略及可运行代码,助力构建高精度生产级RAG系统。
366 2
|
2月前
|
存储 运维 安全
MCP 选中工具之后,到安全执行之间还缺什么?
本文厘清AI Agent安全执行的五大责任边界:MCP管工具协议、Runtime管任务编排、共享控制管执行协调、企业系统管身份审批、业务系统保留最终授权。强调“调用成功≠业务完成”,高风险操作需端到端治理。
|
3月前
|
消息中间件 人工智能 自然语言处理
风险分级应该描述操作,还是直接规定审批流程?
聚焦AI Agent风险分级本质:`high`描述操作后果(如资金、批量通知),非强制审批流程;审批策略须由组织按制度、权限、审计能力自主决定,不可与风险等级硬绑定,确保治理可移植、可落地。
|
3月前
|
人工智能 自然语言处理 安全
我们缺少一个词,来描述 Agent 开始替人操作业务系统这件事
“A2B(Agent-to-Business)”概念,刻画AI从“生成答案”迈向“执行业务”的范式跃迁:人只需提出目标,Agent即可理解意图、穿越系统边界、调用真实能力、完成订单/退款/工单等具备制度性后果的业务操作。它不是技术协议,而是描述人机新型委托关系的认知坐标,助力行业统一语言、沉淀知识、共建责任可溯的智能业务基础设施。
|
3月前
|
人工智能 自然语言处理 安全
scope不是最终权限:Agent 能触达什么,和用户最终能不能做,为什么必须分开?
本文厘清Agent工具权限核心概念:`scope`定义能力“可达性”(Reach),即Agent能否触达某业务功能;而真实操作权(Authority)须由业务系统基于主体、租户、订单状态等实时事实动态判定。二者分层治理,缺一不可。

热门文章

最新文章