erdl-landing

ERDL 规范 v2.1

(Entity-Rule Definition Language · 实体规则定义语言)

状态:v2.1 · 定稿 日期:2026-09-03 版本语义:本文档(ERDL 语言规范)版本为 v2.1;规则文件顶层 protocol: "erdl/v2"(协议标识,固定值)与 version: "2.1.0"(规则格式版本)为独立版本标识,与本文档版本互不混同。 作者:唐启鑫 商标:ERDL™ 是深圳市秒镜科技有限公司的商标。 定位:ERDL(Entity-Rule Definition Language,实体规则定义语言)是一种以 YAML/JSON 承载的声明式规则定义格式,用于精确表达实体结构与行为规则。本规范独立且中立——仅定义格式本身,不依赖任何特定实现或上层框架;其确定性求值与规范化形式支持跨实现逐字节验证。在 ERDL 中,规则决定一切:规则既是语义的载体,也是执行的边界、审计的证据与治理的事实。 规范语言:本文档中 MUST / MUST NOT / SHOULD / SHOULD NOT / MAY 按 [RFC 2119] 解释。


1. Introduction

1.1 ERDL 是什么

ERDL(Entity-Rule Definition Language,实体规则定义语言)是一种以 YAML/JSON 承载的声明式规则定义格式,用于精确表达实体结构与行为规则。它包含两类声明Entity(实体)定义数据结构;Rule(规则)定义 when → then 决策。Entity 界定对象的结构,Rule 规定条件的后果;二者共同构成可执行、可审查、可验证的规则表达。

1.2 设计哲学

ERDL 是多方语义层:它不仅是规则格式,更是人、LLM、系统与审计四方共享的语义约定层。

参与方 ERDL 的角色
人(业务/领域专家) 自然语言规则的精确翻译结果,可读、可审
LLM(通用大模型) 结构化输入,消除歧义,支持确定性求值
系统(规则引擎) 标准化规则描述,并以 fn 委派控制调用边界
审计(监管/合规) 比代码与自然语言更清晰的可追溯规则记录

在这一语义层中,规则决定一切:人表达意图,LLM 翻译语义,系统执行决策,审计复核证据。ERDL 的确定性语义层为 LLM 提供明确方向:使用者以自然语言描述规则,经 ERDL 精确翻译后,由 LLM 基于结构化语义确定性执行——对话界面即为统一入口。

1.3 ERDL 在 AI 治理层面的价值

AI 治理的核心难题,不是模型能否给出答案,而是概率性输出如何满足监管、审计与追责所要求的确定性边界。ERDL 以 YAML/JSON 承载声明式规则,将实体结构、行为约束和处置动作固化为可验证的确定性规则层,使 AI 的「应当如何行动」从训练假设转变为可检查对象。

从信任到验证:传统治理依赖对齐评估或事后解释,难以证明某次具体决策遵循了哪些约束。ERDL 将约束表达为 when → then 规则,每次求值绑定 canonical_tree 快照与结果哈希,可独立重算、逐字节跨实现复核。治理方不再只是相信模型「被正确训练」,而是可以验证某次行为是否命中规则、命中哪条规则、为何得到该结果。

可追责的证据链:ERDL 求值结果可哈希、可重算,可将规则版本、输入快照、决策输出与哈希锚定形成审计记录。审计不是复述日志,而是可重现的证明过程——为何放行、为何拦截、由谁批准,均可回溯查验,避免事后解释成为唯一依据。

机制化的人机权责边界:ERDL 可通过 REQUEST_HUMAN、ESCALATE 等决策类型,将高风险操作、敏感实体变更、不可逆动作等强制交由人工裁决。人的最终决策权不再依赖流程口号,而是被编码为可执行、可测试、可审计的规则路径。

合规即代码与跨组织互认:法规、平台政策和内部红线可转写为 ERDL 规则,并通过测试向量持续验证。不同组织、不同实现或第三方审计机构可基于同一规则与规范化树独立复算,形成「信任但验证」的治理范式,使合规从声明文档变为可运行、可检查、可互认的治理事实。

1.4 设计目标

  1. 确定性:同一规则、同一输入,任何兼容实现 MUST 产生逐字节一致的求值结果与哈希;
  2. 可读性:任何规则可回读为自然语言(gloss),人可秒懂、可审;
  3. 可审计性:规则的求值过程可独立重算、可追溯;
  4. 跨实现可验证:语义收敛到唯一内核,通过测试向量逐字节比对证明实现合规。

1.5 核心承诺

语义载体是内核,不是语法。 语义 = 树 = 哈希。 三者在规范化形式下合一。

任何以「运算符语法」为语义载体的方案,都会因新需求而被迫线性扩张运算符,成本永不收敛。因此本规范把语义收敛到唯一的内核(表达式树),而把多种书写形态作为内核的确定性投影——它们不是各自独立的语言,而是同一语义的不同视图。规则决定一切:规则的有效性不取决于书写入口或实现形态,而取决于唯一、可重算、可哈希、可逐字节验证的规范化语义。


2. 文档结构

2.1 顶层格式

一个 ERDL 文档(*.erdl.yaml)由四个顶层字段构成,字段顺序 MUST 固定:

protocol: "erdl/v2"       # 协议标识,固定值
version: "2.1.0"          # 规则格式版本
metadata: { ... }         # 文档级元数据(见 §2.2)
rules: [ ... ]            # 规则列表(见 §4)
顶层字段 类型 必填 说明
protocol string MUST 协议标识,固定值 "erdl/v2"
version string MUST 规则格式版本(语义化版本)
metadata object MUST 文档级元数据
rules array MUST 规则列表,元素见 §4

2.2 metadata

metadata:
  name: "my-first-rule-set"
  description: "允许读文件操作"
  category: coding
  decision: ALLOW            # 所有规则不匹配时的 fallback 决策
  tags: [example]
字段 类型 说明
name string 规则集名称
description string 规则集描述
category string 规则集分类(coding/security/compliance…)
decision string fallback 决策(所有规则不匹配时的默认裁决,见 §6)
tags array 标签

2.3 格式约定

2.4 解析与求值概览

一个 ERDL 文档从文件到决策结果,走固定的五步管线。理解这条管线,即可理解 ERDL 如何被「解析」与「求值」:

步骤 动作 输入 → 输出 依据
① 加载 读入规则文档 *.erdl.yaml → 结构化对象 §2.1–§2.3
② 校验 加载时类型检查 结构化对象 → 合法文档(拒绝非法) E5
③ 编译 三种书写形态归一化 合法文档 → 表达式树(canonical_tree) E7、§8.2
④ 求值 树对输入事实逐节点判定 表达式树 + fact → 决策 §7
⑤ 输出 生成求值证据 决策 → 可哈希、可重算的求值结果 E6、§8

输入事实(fact)与求值结果(output)的完整契约见 §7.0。


3. Entity 定义

Entity 是规则作用的主体(经 context 传递)。ERDL 预置以下 Entity 类型:

Entity 类型 说明
agent 单个 Agent 实例
tool Agent 调用的工具
task Agent 执行的任务
workflow 多 Agent 编排流程
human 人类审批者
guardian 监管者(supervisor)

规则中的字段引用(如 tool.namecontext.amount)以 Entity 为语义命名空间。字段路径承重:字段名一旦发布即冻结 [FREEZE-1],别名 MUST 先行归一化为规范名。


4. Rule 定义

Rule 是 ERDL 的核心单元:Rule = Metadata + When(条件)+ Then(动作)+ Audit(审计)。When 编译为表达式树(§5),Then 为决策类型(§6),Audit 记录规则求值的审计信息。

4.1 字段定义

rules[] 子字段顺序 MUST 固定为:namedescriptioncategorypriorityoverrideringenabledwhenthenmessageinstructioncorrectionunlessexplanationalternativelegal_basissource_text

字段 类型 必填 说明
name string MUST 规则唯一标识,格式 [CAT]-[NNN]-描述
description string MUST 人读描述
category string MAY 规则级分类;缺省继承 metadata.category(见 §2.2),允许同一文档内混合分类
priority integer MUST 数字越小越优先(见 §7.1)
override string SHOULD 覆盖级别:critical > high > normal > low(默认 normal)
ring integer SHOULD 执行环:0 内核 / 1 恢复 / 2 审批 / 3 建议
enabled boolean MAY 规则启用标志(默认 true);false 时求值跳过该规则
when object MUST 触发条件(见 §5)
then string MUST 决策类型(见 §6)
message string SHOULD 决策消息(拦截性 then MUST 非空)
instruction string MAY 建议指令(ALLOW + instruction 场景)
correction string MAY 纠正文本(CORRECT 决策;求值输出的 primary_correction 来源,见 §7.0.3)
unless object/null MAY 豁免条件块(可选)
explanation string / object MAY 双语解释(规则为何存在、防止何种危害)
alternative string / object MAY 被拦截时建议的替代动作
legal_basis string MAY 法规依据(条款引用)
source_text string MAY 所依据法规的原文摘录

4.2 完整示例

protocol: "erdl/v2"
version: "2.1.0"
metadata:
  name: "my-first-rule-set"
  description: "允许读文件操作"
  category: coding
  decision: ALLOW
  tags: [example]
rules:
  - name: "COD-001-allow-read"
    description: "放行 read_file 工具的所有调用"
    priority: 10
    override: high
    ring: 3
    when:
      logic: AND
      conditions:
        - field: "tool.name"
          operator: eq
          value: "read_file"
    then: ALLOW
    message: "read_file 调用已放行"
    unless: null

5. when 条件表达式

when 是规则的内嵌条件表达式。ERDL 提供三种书写形态(Simple / Expression / 决策表),任一形态编译归一化到同一语义内核(表达式树),再经渲染还原为任一形态;另有一个可读投影 gloss(§5.5)从树确定性生成自然语言。

5.1 书写形态(投影面)

投影面 承载 适用 tier 说明
A · Simple 30 运算符 0–2(MUST) 安全底线,最常用的书写形态
B · Expression 完整 34 节点树 ≥3 业务全景:逻辑组合/量词/算术/时间/聚合
C · 决策表 矩阵 业务/财务人员首选,编译到同一内核

tier 是规则层级(0–5),由低到高表示规则的约束强度与适用范围——本规范中 tier 0–2 为安全底线(MUST 用 Simple),tier ≥3 为业务全景(可用 Expression)。whenexpr 不得共存(E5)。

5.2 投影面 A:Simple(30 运算符)

Simple 是保留的既有语义单元集合,30 运算符 = 28 条件 + 2 修饰符,一字不改。它对应系统安全规则(tier 0–2)。

集合定义

数量 运算符
比较 6 eq · ne · gt · gte · lt · lte
列表 2 in · not_in
字符串 5 contains · not_contains · match · starts_with · ends_with
边界否定 2 not_starts_with · not_ends_with
存在性 2 exists · not_exists
长度 5 length_gt · length_gte · length_lt · length_lte · length_eq
范围 2 between · not_between
计数 4 count_gt · count_gte · count_lt · count_lte
修饰符 2 within(时间窗口)· rate(速率限制)

语义约定(全运算符生效):

权威编译映射:30 运算符全部有确定编译归宿,无悬空——13 直接节点(eq/ne/gt/gte/lt/lte·in·contains/starts_with/ends_with/match·exists·between)、6 not 派生(not_in/not_contains/not_starts_with/not_ends_with/not_exists/not_between)、9 length/count 组合(length_* 5 + count_* 4)、2 时间修饰符(within/rate)。

# Simple 运算符 编译归宿 表达式树表达
1-6 eq ne gt gte lt lte 直接节点 比较节点
7 in 直接节点 集合节点 in
8 not_in not + exists 守卫 exists(field) AND not(in(...))
9-12 contains starts_with ends_with match 直接节点 字符串节点
13 not_contains not + exists 守卫 exists(field) AND not(contains(...))
14-15 not_starts_with not_ends_with not + exists 守卫 exists(field) AND not(...)
16 exists 直接节点 存在节点(值非 null 且非 undefined;空字符串 ""0false 均视为「存在」——「存在」≠「非空字符串」)
17 not_exists not 组合 not(exists(...))
18-22 length_gt/gte/lt/lte/eq 组合 + exists 守卫 exists(field) AND length(field) 比较 n
23 between 直接节点 范围节点(仅数值)
24 not_between not + exists 守卫 exists(field) AND not(between(...))
25-28 count_gt/gte/lt/lte 组合 + exists 守卫 exists(field) AND aggregate(count(...)) 比较 n
29 within 时间修饰 时间窗口(as_of 由引擎注入)
30 rate 时间修饰 + 聚合 速率限制(temporal_state)

exists 守卫(E11 空值传播的编译层保障)not_*(除 not_exists)与 length_*/count_* 组合派生 MUST 编译为 exists(field) AND <派生表达式>,而非裸 not(正向算子) 或裸 length/count(...) 比较。原因:正向算子对缺失字段返回 false、length(缺失) 返回 0,若直接 not 翻转或数值比较,空值传播被破坏(fail-open)。not_exists 是唯一例外——语义即「感知字段缺失」,保持裸 not(exists(...))

有状态算子(within/rate)withinrate 是仅有的两个有状态算子,其求值依赖跨决策的滑动窗口内计数。这一状态不存储在表达式树节点中,而由独立的 Guard 状态管理器维护,以 temporal_state 字段进入审计记录——表达式树本身仍是纯函数(E1 成立),状态源可审计、可重算。

有状态算子真值语义(MUST):计数达阈值 → 条件成立(触发);未达阈值 → 记录本次事件并返回 false(放行)。

算子 阈值 首次/未超限 达阈值后
rate: "N/窗口" N 前 N 次:record + false 第 N+1 次起:true
within: "窗口" 1 首次:record + false 窗口内第 2 次起:true(去重)

配套约束(均 MUST):① 计数后置(仅当正向条件成立才计数);② 计数隔离键(withinfield+operator+value 为键,ratefield+operator+value+rate 为键);③ record 时机在「未超限」分支写入。

5.3 投影面 B:Expression(34 节点树)

Expression 开放完整内核表达力,面向复杂业务规则(tier ≥3)。语义内核是一棵类型化表达式树,由 34 个节点构成(归为 10 组),节点集冻结于 [FREEZE-2]

节点 语义能力
取值 field · var · 字面量 引用字段、上下文变量、常量(var$/$.path,禁读时钟与随机)
逻辑 and · or · not 组合关系
比较 eq · ne · gt · gte · lt · lte 操作数可为字段、变量、字面量或算术子树
集合 in 标量属于集合
字符串 contains · match · starts_with · ends_with 模式匹配;match 走安全正则
存在/量纲 exists · length · between 存在性、长度(Unicode 码点)、闭区间
量词 all · any · none 数组逐元素判定;空数组一律 false
算术 add · sub · mul · div · round 定点小数确定性运算
时间 days_between · epoch_ms · date_add · date_part · month_last_day 日期差、时间戳、日期推演、分量提取、月末取日
聚合 aggregate(count/sum/avg/min/max) 数组聚合

节点总数:取值 3 + 逻辑 3 + 比较 6 + 集合 1 + 字符串 4 + 存在/量纲 3 + 量词 3 + 算术 5 + 时间 5 + 聚合 1 = 34。「比较」6 运算符、「字符串」4 运算符、「算术」5 运算符、「量词」3 种类、「聚合」5 函数在实现中分别以参数化节点类型承载,故「34 个语义节点」在代码中映射为更少的类型字面量——二者是语义节点与类型投影的关系,非数量矛盾。

表达式书写示例

when:
  expr:
    lt:
      - div:
          - sub: [{ field: "tool.args.price" }, { field: "context.cost" }]
          - field: "tool.args.price"
      - 0.15

5.4 投影面 C:决策表(矩阵形态)

决策表面向业务与财务人员,以行列结构表达多条件组合,编译到同一内核:

kind: decision_table
columns:
  - field: "context.amount"
    label: "申请金额"
rows:
  - when: [["gte", 10000]]
    then: "REQUEST_HUMAN"
    priority: 100
  - when: [["gte", 5000]]
    then: "ESCALATE"
    priority: 90
  - when: []                       # 默认行(无条件命中,兜底)
    then: "ALLOW"
    priority: 1

编译规则(E7):① 每行 when 条件组按字段列序编译为逻辑与(and),条件单元编译为比较节点;② 行序即优先级(自上而下首个命中,与 priority 一致,二者 MUST 不冲突);③ 默认行 when: [] 编译为字面量 true;④ then 值 MUST 属于 §6 决策类型枚举;⑤ 编译后产生与手写 Simple/Expression 相同的表达式树。

5.5 投影面 D:gloss(自然语言可读投影)

gloss 是从树确定性生成的自然语言表述:

gloss: "当(售价  成本)除以 售价 小于 15% 时,需人工审批"   # 引擎生成,lint 强制一致

五条不变量(全部 MUST)

# 不变量
G1 gloss = render(树):由冻结渲染模板确定性生成
G2 每条规则 MUST 携带 gloss,lint 校验 gloss == render(树),禁手写
G3 gloss 禁原始字段路径,MUST 用 Entity 的 display_name(中英双语)
G4 gloss 为渲染产物(不进哈希),展示时实时 render(树) 呈现
G5 Simple 规则同样生成 gloss(编译为树后渲染)——阅读层不分层

gloss 渲染模板(逐节点,中英双语;{A}/{B}/{C} 为子表达式递归渲染结果):

节点 中文模板 English template
field {field} {field}
var {变量} {variable}
literal {value} {value}
and {A} 且 {B} {A} and {B}
or {A} 或 {B} {A} or {B}
not 非({A}) not ({A})
eq {A} 等于 {B} {A} equals {B}
ne {A} 不等于 {B} {A} does not equal {B}
gt {A} 大于 {B} {A} is greater than {B}
gte {A} 大于等于 {B} {A} is greater than or equal to {B}
lt {A} 小于 {B} {A} is less than {B}
lte {A} 小于等于 {B} {A} is less than or equal to {B}
in {A} 属于 {B} {A} is in {B}
contains {A} 包含 {B} {A} contains {B}
match {A} 匹配正则 {B} {A} matches regex {B}
starts_with {A} 以 {B} 开头 {A} starts with {B}
ends_with {A} 以 {B} 结尾 {A} ends with {B}
exists {A} 已发生 {A} exists
length {A} 的长度 the length of {A}
between {A} 介于 {B} 与 {C} 之间 {A} is between {B} and {C}
all {A} 中每一项均满足:{B} every item in {A} satisfies: {B}
any {A} 中存在一项满足:{B} some item in {A} satisfies: {B}
none {A} 中无一项满足:{B} no item in {A} satisfies: {B}
add {A} 加 {B} {A} plus {B}
sub {A} 减 {B} {A} minus {B}
mul {A} 乘 {B} {A} times {B}
div {A} 除以 {B} {A} divided by {B}
round {A} 四舍五入 {A} rounded
days_between {A} 与 {B} 之间的天数 days between {A} and {B}
epoch_ms {A} 的时间戳 the epoch milliseconds of {A}
date_add {A} 加 {B} 时长 {A} plus {B} duration
date_part {A} 的 {part} the {part} of {A}
month_last_day {A} 所在月的最后一日 the last day of the month of {A}
aggregate(count) {A} 的元素个数 the count of {A}
aggregate(sum) {A} 之和 the sum of {A}
aggregate(avg) {A} 的平均值 the average of {A}
aggregate(min) {A} 的最小值 the minimum of {A}
aggregate(max) {A} 的最大值 the maximum of {A}

exists 布尔字段特例:当字段名匹配 is_*/has_*(布尔字段约定)时,exists 渲染为 {A} 为"是"(中文)/ {A} is true(英文),而非 {A} 已发生/{A} exists——布尔字段存在即真,避免「是否已告知 已发生」这类别扭表达。


6. then 决策类型

then 的值 MUST 属于以下 13 种决策类型:

# 决策类型 语义
1 ALLOW 放行
2 DENY 拦截
3 CORRECT 纠正偏差
4 NOTIFY 通知
5 REQUEST_HUMAN 请求人工裁决
6 ESCALATE 升级
7 DELEGATE 委派
8 DEFER 延期
9 EMERGENCY_HALT 紧急停止
10 ROLLBACK 回滚
11 QUARANTINE 隔离
12 WORKFLOW 工作流(状态机;子态 WORKFLOW_WAITING / WORKFLOW_PROGRESS)
13 GUIDE 引导

7. 求值语义

7.0 求值概览

求值 = 表达式树(规则编译产物)对输入事实(fact)逐节点判定的纯函数过程(E1)。本节定义求值的输入契约、算法步骤与输出契约,供实现者与使用者对齐。

7.0.1 输入契约(事实对象)

求值输入是一个事实对象(fact),承载规则作用主体的当前状态,以 Entity(§3)为命名空间:

fact:
  tool:                 # Entity: tool
    name: "issue_refund"
    args: { amount: 8000, order_id: "O1024" }
  context:              # 自由上下文字段(规则以 context.* 引用)
    country: "CN"
    role: "operator"
  # 其他 Entity:agent / task / workflow / human / guardian(按需提供)

7.0.2 求值算法

输入:规则集 rules[] + 事实对象 fact
输出:决策结果(见 7.0.3)

1. 排序:按 priority 从小到大(值越小越优先)
2. 分组:按 ring 从 0 到 3 顺序执行(0 内核 → 1 恢复 → 2 审批 → 3 建议)
3. 每个 ring 内,按序求值每条规则:
   a. unless 豁免先于 when 判定——命中豁免则记录后跳过该规则
   b. 编译后的 when 表达式树对 fact 逐节点求值(true / false / 错误)
   c. 首命中:每个 ring 内 first-match-wins(命中即短路该 ring)
   d. override:仅 DENY → ALLOW 方向覆盖,不得覆盖到更不安全状态(§7.1)
4. 兜底:无规则命中 → metadata.decision(fallback 决策,§2.2)
5. 汇总:产出 decision + matched_rules + 证据(canonical_tree / hash / eval_trace)

7.0.3 输出契约(求值结果)

求值结果 MUST 包含以下字段:

字段 说明
decision 最终决策(§6 枚举之一,或 fallback 决策)
matched_rules 命中的规则(按求值顺序)
unless_exemptions 被 unless 豁免的规则(单独记录,不计入 matched_rules)
primary_instruction 首要指令(ALLOW + instruction 场景)
primary_reason 首要理由(DENY 等拦截场景)
primary_explanation 首要解释(可中英双语)
primary_correction 纠正文本(CORRECT 决策;来源为规则字段 correction,见 §4.1)
total_evaluated 求值的规则总数
total_matched 命中的规则总数
temporal_state within/rate 滑动窗口状态快照(无命中时省略)

求值证据(canonical_tree 快照、结果哈希、eval_trace)为可独立重算的派生产物(§8.2、E6)——canonical_tree 进哈希,eval_trace 不进哈希(§8.3)。

7.1 优先级与冲突解决

  1. priority 从小到大排序(值越小越先);
  2. 同 priority 有 override 标记的排前;
  3. override 枚举:critical > high > normal > low(默认 normal);
  4. 同 priority 同 override 按定义顺序;
  5. override 仅允许 DENY → ALLOW 方向覆盖(不得覆盖到更不安全状态)。

7.2 求值约束(E1–E12,全部 MUST)

编号 约束
E1 求值是纯函数:无副作用、无隐式外部状态、无时钟读取;within/rate 的状态注入(temporal_state)与 as_of 同级,属受控外部输入
E2 定点小数 scale=14 + half-even + 字符串序列化;中间计算用高精度有界有理数,仅输出节点舍入
E3 求值错误记 eval_warnings,折叠方向按 E12 分 tier
E4 资源上限(分级):Grade A 算术深度≤2 / 树深≤6 / 节点≤64 / 数组≤10000 / 单规则≤50ms / 量词不嵌套 / 正则步数≤10000;Grade B 树深≤10 / 节点≤256 / 算术深度≤4,量词嵌套≤2 层;Grade C 不适用
E5 加载时类型检查;whenexpr 不得共存
E6 树即证据:canonical_tree(树快照)作为求值证据参与哈希;eval_trace 为可重算派生产物,不进哈希
E7 Simple 与 Expression 编译到同一求值核心,禁止两个求值器
E8 量词安全折叠:空数组 → all/any/none 一律 false(反空洞真)
E9 禁读墙钟;as_of 由引擎注入并记入审计记录
E10 字符串 NFC 规范化
E11 undefined 哨兵语义(空值传播,见 §7.3)
E12 求值错误处理:tier≤2 及 Guard 上下文缺省 fail-close,tier 3–5 折叠为 false

内核显式排除:字符串拼接、正则替换、位运算、日期格式化、递归引用、用户自定义节点——以维持求值的封闭性与可验证性。

7.3 确定性语义(跨实现分叉防护)

以下语义 MUST 在文档与向量中显式标注,避免与标准实现产生语义误解:

(a) 空值传播(E11):Agent 上下文高度动态,字段缺失是常态。求值 MUST 三值逻辑安全失败:

场景 行为
字段不存在时的相等/数值比较 返回 false(非 NPE)
== null / != null 检查 正常返回 true / false
类型不匹配的比较 返回 false(禁止隐式转换)
字段不存在时的算术运算 返回 false(条件)或 EvaluationError(算术表达式)

(b) 量词空数组的安全折叠(E8):标准量词语义下 all(空)=true(空洞真)。本规范刻意偏离:all/any/none(空) 一律折叠为 false——防「无元素可校验却被判为放行」,并在审计记录中记录安全折叠。第三方实现 MUST 采用本折叠语义。

(c) 定点小数的中间精度(E2):中间计算采用高精度有界有理数(如 128 位整数分子/分母),仅输出节点按 scale=14 + half-even 舍入为字符串序列化(IEEE 754-2019 ROUND_HALF_EVEN)。

(d) 正则的 ReDoS 防护match 节点 MUST 同时满足:① 单次匹配步数 ≤10000;② 输入长度上限;③ 优先确定性引擎(RE2 类)或安全语法子集。

(e) aggregate 空数组的安全折叠

函数 空数组结果 依据
count(空) 0 标准计数语义
sum(空) 0 空和恒等元
avg(空) false 安全失败折叠(避免除零)
min(空) false 安全失败折叠(标准 +Infinity,禁用)
max(空) false 安全失败折叠(标准 −Infinity,禁用)

aggregateover MUST 为数组;非数组(缺失/标量/对象)返回 null + type_mismatch warning(折叠为 false)。count(缺失)count(空数组) 语义不同:前者 type_mismatch,后者 0。

(f) 时间节点的 UTC 语义(E9):所有时间节点统一以 UTC 求值,保证跨实现、跨时区逐字节一致:

业务本地时区由引擎注入 as_of 时转换为 UTC 时刻,求值器以 UTC 纯函数运算。

7.4 when 最小完整度约束

when: "true" 的语义是「对所有操作生效」,仅适用于建议性规则:

规则 级别
when: "true" MUST NOT 与 then: DENY 搭配 MUST NOT
when: "true" MUST NOT 与 then: EMERGENCY_HALT 搭配 MUST NOT
when: "true" MUST NOT 与 then: CORRECT 搭配 MUST NOT
when: "true" MUST NOT 与 then: REQUEST_HUMAN 搭配 MUST NOT
when: "true" MAY 与 then: ALLOW + instruction 搭配 MAY
when: "true" MAY 与 then: NOTIFY 搭配 MAY
安全类规则(category=security)MUST 至少含 1 个 condition MUST
工具拦截类规则 SHOULD 含 tool.name 条件 SHOULD
文件操作规则 SHOULD 含 tool.args.path SHOULD
命令操作规则 SHOULD 含 tool.args.command SHOULD

8. 序列化与规范化

8.1 序列化

ERDL 文档以 YAML 承载,可无损转换为 JSON。规范化树(canonical_tree)以 JSON 对象形态序列化。

8.2 规范化树(Canonical Form)

表达式树是唯一求值、唯一哈希、唯一重算的基准对象。要使其哈希可跨实现逐字节一致,树 MUST 具有唯一规范化形式:

规范化规则 说明
节点序固定 子节点按规范顺序排列(左→右严格定序),与源书写顺序无关
字段名承重 字段引用路径承重——字段名发布即冻结 [FREEZE-1],别名 MUST 先行归一化
字面量规范 数字以定点小数字符串表示(scale=14 + half-even);字符串 NFC 规范化
var 规范 仅支持 $ / $.path,路径段为确定字节序列
元数据剥离 注释、来源行号、格式、作者等非语义元数据一律不进规范化树

树哈希的对象是规范化树,而非任何特定实现的内存表示或序列化文本。 两个结构等价的树(仅字段书写顺序、空格、变量命名不同)规范化后产生完全相同的字节序列与哈希。

8.3 规范化树与 gloss 的关系

这一「哈希树、校验 gloss 与树一致」的机制,使 gloss 在哈希模式下无需逐字节一致、也无需进哈希,即可获得树的密码学锚定。


9. 如何集成 ERDL

ERDL 的集成目标,是把关键判断从模型推理、框架代码或口头约定中抽离出来,变成可加载、可执行、可验证的规则资产。它通常以 YAML/JSON 规则文档承载,通过 when → then 完成决策,并输出可哈希、可逐字节复算的求值证据。以下三种集成路径,对应三类典型工程落点。

9.1 场景一:AI Agent(行为约束层 / Action Guard)

角色:在 AI Agent 链路中,ERDL 是 LLM 意图与系统执行之间的「确定性闸门」——Agent 可以生成动作,但动作是否允许执行,必须由规则求值决定。

模拟:客服 Agent 收到用户「退款 8000 元」的请求。LLM 将意图转换为工具调用:issue_refund(amount=8000, order_id=O1024)。在真正触达支付系统前,Action Guard 把工具名、参数、会话上下文打包成事实对象,交给 ERDL 求值。规则集中,R1 写作:when tool.name == "issue_refund" 且 tool.args.amount > 5000 → REQUEST_HUMAN;R2 写作:when tool.name == "issue_refund" → ALLOW。由于 R1 先命中,系统返回 REQUEST_HUMAN。Agent 停止调用支付工具,转为生成人工审批任务,并向用户返回「需人工复核」的话术。

集成要点:第一,规则在模型之外独立求值,Prompt 不再承担安全边界;第二,命中记录、输入摘要、canonical_tree 与结果哈希一并写入审计日志,任何一次拦截都可回放;第三,规则变更只需更新 ERDL 文档,不必重写 Agent 框架、工具实现或模型提示词。

9.2 场景二:MCP(协议分发 / 跨实现互操作)

角色:在 MCP 生态中,ERDL 规则通过 ERDL MCP Server 暴露为标准工具,任何 MCP 兼容 Agent 都能调用同一套规则,实现跨实现的合规分发与互认。

模拟:某企业将资金合规规则部署为 ERDL MCP Server,并暴露 guard_check 工具。第三方 Agent 准备执行一笔高额退款,但自身不掌握企业规则。执行前,它通过 MCP 调用 guard_check,传入动作描述:action="issue_refund"amount=8000channel="payment"。ERDL MCP Server 加载规则集,完成求值,返回:decision=REQUEST_HUMANmatched_rule=R1hash=0x9f...。第三方 Agent 根据返回值停止直接执行,转入人工审批流程,并将该决策凭据写入自己的执行日志。

集成要点:这里的关键是「规则即服务」。规则不再硬编码在某个 Agent 框架里,而是通过标准协议分发;不同厂商、不同语言、不同运行时的客户端,都可以消费同一份判断逻辑。由于返回结果携带规则命中与哈希信息,调用方即使不保存规则原文,也能把决策凭据归档,供后续审计或独立复算。规则升级时,只需更新 MCP Server 端,客户端无需重构执行链。

9.3 场景三:规则引擎(规则定义语言 / 确定性求值)

角色:在规则引擎内部,ERDL 是规则定义语言本身,负责以声明式方式表达业务策略,并提供确定性求值语义。

模拟:反洗钱引擎需要表达「大额交易且高风险国家 → 拦截」。业务团队编写 ERDL 规则:when context.amount > 10000 且 context.country in ["高风险国家列表"] → DENY。引擎加载 YAML 后,不会把它当成普通配置,而是编译为表达式树:比较节点处理金额阈值,集合节点判断国家归属,逻辑节点完成与运算。随后,引擎按照 E1–E12 求值语义执行,输出 DENY。该规则还可生成 canonical_tree 与哈希值;另一实现只要加载同一规则、同一输入,就能重算出相同结果。

集成要点:这里的核心价值是「可验证的确定性」。ERDL 不只让规则可读,还让引擎实现可以被测试向量约束。V-ENGINE 类测试向量可以证明:不同引擎、不同平台、不同版本,对同一规则应产生逐字节一致的结果。由此,规则引擎不再只是业务系统内部黑盒,而是可以接受第三方独立验证的执行器。监管方、审计方或平台方都能依据输入、规则哈希与求值证据,判断「引擎算得对不对」。


10. 示例与一致性验证

10.1 Quick Start(快速上手)

一个最小 ERDL 文档 + 一次求值,走完「写 → 加载 → 求值 → 得结果」全链路(管线见 §2.4)。

第一步 · 写规则refund.erdl.yaml):

protocol: "erdl/v2"
version: "2.1.0"
metadata:
  name: "refund-guard"
  description: "退款金额管控"
  category: coding
  decision: ALLOW
rules:
  - name: "SEC-001-refund-limit"
    description: "退款超过 5000 需人工审批"
    priority: 10
    when:
      logic: AND
      conditions:
        - field: "tool.name"
          operator: eq
          value: "issue_refund"
        - field: "tool.args.amount"
          operator: gt
          value: 5000
    then: REQUEST_HUMAN
    message: "退款金额超过 5000,需人工审批"

第二步 · 加载 + 校验 + 编译:解析 YAML,校验通过后把 when 编译为表达式树(§2.4 步骤①②③)。

第三步 · 求值:给定事实对象:

fact:
  tool:
    name: "issue_refund"
    args: { amount: 8000 }

规则 SEC-001 命中(tool.name == "issue_refund"amount > 5000)。

第四步 · 结果

decision: REQUEST_HUMAN
matched_rules: ["SEC-001-refund-limit"]
primary_reason: "退款金额超过 5000,需人工审批"
total_evaluated: 1
total_matched: 1

若输入改为 amount: 100,规则不命中,走 metadata.decision fallback → decision: ALLOW

10.2 完整示例

见 §4.2(Simple 规则)与 §5.3(Expression 规则)、§5.4(决策表)。

10.3 一致性验证

本规范的语义 MUST 由可独立重算的测试向量证明。表达层向量(V-ENGINE / V-GLOSS / V-PROJ)覆盖:34 节点 × 4 场景(正常/边界/异常/空值)、E1-E12 语义、Simple 30 运算符编译映射、gloss 渲染模板。

五步验证法:加载向量输入 → 生成表达式树 → 重算求值结果 → 与答案对比 → 判定一致。

第三方 Runner 验证流程(从零到合规)

  1. 读本规范;
  2. 用自己选择的技术栈实现独立验证器(不引用任何既有实现代码);
  3. 加载测试向量,逐字节比对;
  4. 对照 Runner 契约确认自建实现满足契约;
  5. 提交结果至实现注册表,供第三方审计复验。

附录 A · 34 节点参考表

节点 数量
取值 field · var · 字面量 3
逻辑 and · or · not 3
比较 eq · ne · gt · gte · lt · lte 6
集合 in 1
字符串 contains · match · starts_with · ends_with 4
存在/量纲 exists · length · between 3
量词 all · any · none 3
算术 add · sub · mul · div · round 5
时间 days_between · epoch_ms · date_add · date_part · month_last_day 5
聚合 aggregate(count/sum/avg/min/max) 1

合计 34 节点

附录 B · Simple 30 运算符参考表

运算符 数量
比较 eq · ne · gt · gte · lt · lte 6
列表 in · not_in 2
字符串 contains · not_contains · match · starts_with · ends_with 5
边界否定 not_starts_with · not_ends_with 2
存在性 exists · not_exists 2
长度 length_gt · length_gte · length_lt · length_lte · length_eq 5
范围 between · not_between 2
计数 count_gt · count_gte · count_lt · count_lte 4
修饰符 within · rate 2

合计 30 运算符(28 条件运算符 + 2 条件修饰符)。

附录 C · 决策类型枚举(13 种)

见 §6。

附录 D · 函数委派与规则分级

对于内核显式排除、确有需求的场景,提供函数委派(FnRegistry)作为受控兜底:

约束 说明
注册制 函数 MUST 注册方可引用,未注册不可调用
沙箱执行 受限环境,受资源配额与超时约束
确定性豁免声明 用于 Guard 求值路径的函数 MUST 声明并保证确定性
审计可溯 每次调用记入审计记录,可离线核验

规则分级(Grade)

Grade 表达方式 审计 SLA
A 纯 Simple(30 运算符) 最高,纯文本可重算
B Expression 树 高,eval_trace MUST
C 含函数委派 分层,C 级不得冒充纯文本可重算

含函数委派的规则(Grade C)MUST 在 gloss 中显式标记「含不可重算的函数委派」;函数委派的调用输入 + 输出哈希 MUST 纳入结果哈希的原像。


附录 E · 术语表

术语 一句话定义
Entity(实体) 规则作用的主体类型(agent/tool/task/workflow/human/guardian),字段引用的命名空间(§3)
Rule(规则) when → then 决策单元
when 规则触发条件(编译为表达式树)
then 规则命中后的决策类型(§6)
tier 规则层级 0–5,由低到高表示约束强度;tier 0–2 用 Simple,≥3 可用 Expression
ring 执行环 0–3(内核/恢复/审批/建议),求值按环序执行
override 覆盖级别 critical > high > normal > low,仅允许 DENY → ALLOW 方向
表达式树 求值语义内核(34 节点,10 组),三种书写形态编译归一化到它
canonical_tree 规范化树,唯一哈希、唯一重算的基准对象(§8.2)
gloss 从树确定性生成的自然语言可读投影(§5.5)
eval_trace 逐节点求值轨迹(可重算派生产物,不进哈希,E6)
eval_warnings 求值过程中的非致命警告(E3)
temporal_state within/rate 滑动窗口状态(有状态算子)
as_of 引擎注入的求值时刻(UTC,E9)
事实对象(fact) 求值输入,承载 Entity 当前状态(§7.0.1)
fallback 决策 无规则命中时 metadata.decision 的兜底裁决(§2.2)
NFC Unicode 规范化形式 C(字符串归一,E10)
ReDoS 正则拒绝服务攻击;match 节点 MUST 步数上限防护(§7.3(d))
half-even 银行家舍入(ROUND_HALF_EVEN),E2 定点小数输出舍入
空值传播 字段缺失统一返回 false 的安全失败语义(E11)

修订历史

版本 日期 变更
v2.1 2026-09-03 §4.1 新增 category(规则级覆盖)、enabled(启用标志)、correction(CORRECT 纠偏文本)三个可选字段,补全字段表与固定顺序;§7.0.3 补 primary_correction 来源交叉引用。协议 erdl/v2 不变;规则格式版本 2.0.0 → 2.1.0(新增可选字段,Non-breaking)
v2.0 2026-08-30 定稿

规范性引用


© 2026 深圳市秒镜科技有限公司 · MIT License