Agent 写正则来实现规则 ≈ 踩坑

作者:hpoenixf日期:2026/9/23

最近在升级我的个人投资研究 Agent 时,我碰到了一个很容易被忽略的问题:

确定性实现,不等于客观判断。

代码当然可以稳定地执行一个正则、关键词表或布尔条件。

但“执行稳定”并不会自动赋予 Runtime 理解开放自然语言的能力。

如果 Runtime 并不知道一句话的真实语义,就不要因为能把它写成 if,假装自己知道。

这篇文章讨论的,就是 Agent 系统里一条很重要的边界:

Runtime 只应该对自己真正知道、能够追溯和复核的事实负责。


前情提要:我们在做什么 Agent

我们做的是一个偏严肃场景的个人投资研究 Agent。

它不是简单把用户问题丢给大模型,也不是让模型自己执行投资操作。

更接近这样的流程:

1用户提出问题
2 Agent 判断需要什么信息
3 按权限读取组合、材料或公开来源
4 根据结果继续调查
5 形成分析
6 系统校验证据、权限和确定性状态
7 发布答案
8

例如:

1我的组合风险是不是太集中?
2这两类 ETF 哪个更适合长期配置?
3结合这份材料,重新评估之前的判断。
4

这种系统里,除了 Model,还会有一层 Runtime。

这里的 Runtime 不是语言运行时,而是围绕 Model 的 Host-owned 执行与状态层。

它负责的事情大致包括:

1工具授权
2调用执行
3状态和回执
4来源与 scope
5确定性数值
6持久化
7恢复
8发布
9终态
10

Model 更适合负责:

1理解用户
2决定下一步查什么
3比较信息
4发现矛盾
5形成判断
6组织回答
7

问题就在于:

Runtime 到底应该管到哪里?


先给结论:谁拥有事实,谁才有资格触发硬规则

Runtime 应该负责它能够客观证明的事实。

例如:

1某个工具是否真的调用
2某个来源是否属于当前用户和当前 run
3某个数据是否已经过期
4某个状态绑定是否仍有效
5某个执行回执是否存在
6某个 publication 是否真的提交
7

这些信息来自 Host、持久化状态或明确协议。

它们有一个共同特点:

可以被审计和复核。

但下面这些问题不是一回事:

1这句话是不是“当前事实”?
2这句话是不是个人持仓断言?
3这句话是不是投资建议?
4这句话是否真的被证据支持?
5这句话是否完整回答了用户?
6

这些属于语义判断。

它们不会因为实现语言是 TypeScript,或者判断逻辑写成了正则,就突然变成客观事实。

这就是标题真正想表达的东西:

Runtime 不知道的,不要因为能写一个规则,就假装它知道。


问题通常不是从“大型自然语言分类器”开始的

实际工程里,这类问题往往从一个非常合理的安全需求开始。

例如:

1模型没有读取用户组合
2却生成了一句“你的组合目前没有某类资产”
3

我们当然不希望系统把这种话当成可信的个人状态。

于是一个很自然的想法是:

1如果答案里出现:
2“你的组合”
3“当前持仓”
4“目前没有”
5……
6就要求 portfolio evidence
7

第一版看起来很合理。

而且 deterministic:

1命中  reject
2不命中  pass
3

问题是:

命中的是字符串模式,不是事实身份。

同一句话可能是:

1真实断言
2假设
3引用
4例子
5否定
6转述
7模型错误
8

Runtime 看到的是字符。

它并不知道这句话在当前上下文里究竟扮演什么语义角色。

于是系统开始出现两种错误:

1误拦:只是举例,却被当成真实个人状态
2漏拦:换一种说法,就绕过了关键词
3

然后工程上很容易继续补:

1更多关键词
2更多正则
3更多 reason code
4更多 repair
5更多测试
6

最后,一个最初只是小 helper 的东西,慢慢变成了“安全基础设施”。

这时候真正应该问的,已经不是:

正则覆盖率够不够?

而是:

这个规则到底有没有资格判断这件事?


一个最小例子:执行状态不能从文案里推出来

假设 Model 写了一句:

“已经替你完成了调整。”

Runtime 可以做两种事情。

错误方式:解释文本

1发现“已经完成”
2 判断这是执行声明
3 检查有没有执行记录
4

这看起来像安全保护。

但问题是:

1“已经完成”可能是引用
2可能是否定句的一部分
3可能是举例
4可能只是文案错误
5

真正的执行状态,其实根本不需要从文字里猜。

Runtime 已经可以知道:

1有没有执行请求
2用户有没有确认
3有没有调用允许的执行工具
4有没有 execution receipt
5账本状态有没有变化
6

所以执行状态应该由这些事实决定:

1 receipt  executed
2没有 receipt  not executed
3

而不是:

1文案像执行成功  猜它执行了
2

如果 Model 文案和真实状态冲突,那是语义质量问题

可以拒绝、降级或交给评审。

但“执行是否真的发生”,不应该由 prose 决定。


自由文本不能创造权威事实

这条边界可以进一步推广。

自然语言里可能出现:

1“你的组合没有黄金”
2“当前净值是……”
3“我已经帮你调仓”
4

这些句子看起来分别像:

1个人状态
2当前事实
3执行声明
4

但 Runtime 不应该仅凭文本,把它们升级成系统事实。

真正能触发确定性验证的,应该是 Host-owned typed facts,例如:

1状态绑定
2来源引用
3数值句柄
4执行回执
5明确 scope
6

也就是说:

自由文本可以表达内容,但不能创建 authority。

Model 可以提出:

1“我认为这里需要引用当前组合”
2

但是否真的存在当前组合、是否有权限、是否仍有效,必须由 Host 决定。

Model 也可以写出一个金额。

但一个自由形式的金额,不应该自动获得“这是可信当前投资金额”的身份。

真正的权威必须来自系统自己拥有的绑定。


哪些文本检查仍然适合 Runtime

这里不是说 Runtime 完全不能检查文本。

有一类检查是合理的:

1. 机器语法

例如:

1ID
2placeholder
3cursor
4protocol marker
5

2. 明确受保护字面量

例如:

1secret
2credential
3token
4

3. 机械约束

例如:

1长度
2JSON/schema 是否合法
3字段是否存在
4格式是否符合协议
5

这些检查共同特点是:

不需要理解语言的意义。

真正危险的是把下面这些概念也交给字符串规则:

1当前事实
2个人状态
3投资建议
4执行
5完整性
6语义支持
7

这些不是“正则写得够不够好”的问题。

而是所有权就错了。


证据链存在,不等于自然语言一定正确

另一个很容易混淆的地方,是 evidence。

Runtime 可以客观证明:

1某个来源确实被读取
2结果确实进入了下一轮
3最终 publication 确实绑定了这个来源
4scope  freshness 检查通过
5

这些都很重要。

但它们并不能单独证明:

1答案正确理解了来源
2答案没有把数字写反
3答案完整回答了问题
4答案没有语义歧义
5

举一个最简单的例子。

来源里写的是:

1A
2

模型回答:

1B
2

即使:

1read 发生了
2citation 也绑定了
3

“B 是否被 A 支持”依然是语义问题。

所以:

provenance 完整,不等于 entailment 成立。

Runtime 可以证明:

“这句话绑定了哪个来源。”

但不能仅凭这一点证明:

“这句话一定正确表达了来源。”

这两个层次最好不要混在一起。


为什么 repair 成功,也不等于规则正确

这是这类 heuristic 最容易制造的错觉。

假设:

1第一轮:
2模型写了一个当前数值
3规则命中  reject
4
5系统反馈:
6不要输出未经验证的当前事实
7
8第二轮:
9模型把数值删掉,改成泛泛描述
10规则不命中  pass
11

从测试角度看:

1repair 成功
2

但 underlying facts 并没有变化。

变化的只是:

1wording
2

这可能说明:

1事实真的被修正了
2

也可能只是:

1模型学会绕过 matcher
2

因此至少要把两个概念分开:

1mechanical repair success
2semantic correctness
3

前者 Runtime 可以测。

后者不能从前者推出。


正确的边界不是“全部交给模型”

看到这里,很容易得出另一个极端结论:

那 Runtime 什么都别管,让 Model 自己判断。

也不对。

Runtime 非常适合负责:

1permission
2scope
3freshness
4receipt
5state binding
6numeric binding
7publication
8terminal state
9

因为这些是真实系统状态。

Model 非常适合负责:

1这句话是什么意思
2当前结果说明什么
3还要不要继续查
4两份资料是否矛盾
5怎样回答用户
6

所以真正的目标不是:

1Model 替代 Runtime
2

也不是:

1Runtime 替代 Model
2

而是:

确定性事实交给 Runtime,开放语义交给 Model。


“Runtime 能知道的都不要让 Model 推理”还缺另一半

我们经常会说:

Runtime 能知道的,就不要让大模型推理。

这句话是对的。

例如:

1某个工具是否调用成功
2某个 publication 是否已经提交
3某个数值是否来自可信计算
4

都没必要让 Model 猜。

但这句话只有一半。

另一半同样重要:

Runtime 不知道的,也不要因为能写一个 if,就假装它知道。

两句话合起来才完整:

1Runtime 已知的
2 不让 Model 重复维护
3
4Runtime 不知道的
5 不让规则冒充理解
6

这也是我们最近越来越认可的分工:

Runtime 维护世界,Model 理解世界。


两个简单案例

案例一:个人持仓

用户的真实组合状态应该来自:

1授权
2scope
3组合数据
4状态绑定
5freshness
6

而不是:

1答案里有没有出现“你的组合”
2

如果没有有效状态绑定,Model 写得再像真实持仓,也不能获得个人状态 authority。

如果状态绑定存在但已经过期,也不能因为文案听起来合理就升级成 current。


案例二:执行结果

执行是否发生应该来自:

1明确请求
2用户确认
3工具调用
4执行回执
5实际状态变化
6

而不是:

1答案里有没有“已完成”“已下单”
2

Model 可以写错。

Runtime 不能因为 Model 写错,就让世界状态跟着变化。

这其实是 Agent 系统最重要的一条原则:

语言描述世界,不等于语言创造世界。


一个实用的 Code Review 清单

以后看到一个新的 deterministic gate,我会优先问下面这些问题:

  1. 这个 gate 判断的到底是什么?
  2. 它的 authoritative input 来自哪里?
  3. 这个输入是 Host-owned fact,还是 Model prose?
  4. 如果把同一句话换个说法,结果会不会变化?
  5. 如果会变化,变化的是语义,还是系统事实?
  6. 自由文本是否能创建个人状态、金额或执行结果?
  7. evidence chain 证明的是来源追溯,还是语义正确?
  8. repair 成功以后,事实真的变了吗,还是 wording 变了?
  9. 没有语义评审时,系统有没有诚实保留“未评估”状态?
  10. 这个规则是在减少风险,还是把自然语言分类偷偷塞进 Runtime?

如果其中有几项答不上来,就值得重新考虑这条 gate 是否应该存在。


最后

Agent 系统很容易在追求可靠性的过程中,把越来越多判断写成确定性规则。

这本身不是问题。

问题在于:

不是所有能写成代码的判断,都是 Runtime 真正知道的事实。

正则可以稳定。

关键词表可以稳定。

布尔逻辑可以稳定。

但:

稳定执行一个判断,不等于这个判断拥有客观依据。

好的 Runtime 应该很严格。

但严格的前提是:

它只对自己真正拥有的事实负责。

Model 可以理解、推理和表达。

Runtime 可以授权、执行、记录和校验。

语义质量可以由 Model、独立评审或 Human 判断。

但不要让任何一层冒充另一层。

所以最后还是这两句话:

Runtime 已经知道的,不要让 Model 再维护。

Runtime 不知道的,也不要因为能写规则,就假装它知道。

好的 Agent 架构不是把所有复杂度搬进代码。

而是:

把确定性复杂度放进 Runtime,把语义复杂度留给 Model。


Agent 写正则来实现规则 ≈ 踩坑》 是转载文章,点击查看原文


相关推荐


15、音频系统
狂人开飞机2026/9/15

第15章 音频系统 15.1 AudioStreamPlayer 基础 # AudioStreamPlayer:非位置音频(BGM、UI音效) # AudioStreamPlayer2D:2D 位置音频(距离衰减) # AudioStreamPlayer3D:3D 位置音频 extends AudioStreamPlayer func _ready() -> void: stream = preload("res://audio/bgm/battle_theme.ogg")


Git-SVN 混合开发,从入门到精通!
重生之我来学Python2026/9/7

Git-SVN 混合开发:命令对照、工作流程与 15+ 实战技巧,一篇搞定! 摘要 本文详细介绍 Git-SVN 混合开发的完整方案,涵盖从安装配置到实战操作的全流程。通过 Git 命令与 SVN 命令的对照表格、15+ 个核心命令详解、以及真实场景下的工作流程,帮助你在 SVN 项目中享受 Git 的便利。无论你是被迫使用 SVN 的 Git 用户,还是想尝试 Git 功能的 SVN 团队,这篇文章都能让你快速上手 Git-SVN 混合开发模式。 在 SVN 项目中使用 Git 本地分支、暂


Highcharts 双 Y 轴分组错位柱状图・代码详解
Highcharts.js2026/8/30

双 Y 轴、非分组错位并列柱状图,同时展示两类指标: 左轴:员工数量(人数,普通数值)右轴:利润(百万美元,金额) 同一分类下 4 根柱子错开摆放,不会互相重叠,用来对比「优化前 / 优化后」两组数据差异。 示例代码 Highcharts.chart('container', { chart: { type: 'column' }, title: { text: 'Efficiency Optimization by Branch


OpenCV实战——透视变换与身份证号码模板识别
clorinda2026/8/22

一、前言》》》》》》》 在现实生活中,发票、身份证和纸张通常不是完全正对着摄像头拍摄的。由于拍摄角度不同,原本的矩形会变成梯形,文字也会发生倾斜。 如果直接对这种图片进行识别,效果往往不理想。因此,通常需要先完成透视变换,把图像矫正成正面视图,再进行二值化、轮廓检测和模板匹配。 本篇主要介绍: 1,透视变换的原理; 2,四个角点的排序; 3,发票图像矫正; 4,形态学闭运算; 5,使用模板匹配识别身份证号码。 二、透视变换的基本原理 透视变换可以把原图中的任意四边形转换成一


Rust Borrow借用详解:不转移所有权访问数据
程序员爱钓鱼2026/8/9

《Rust编程实战》系列第35篇 在上一篇文章中,我们学习了Rust的Copy,了解了哪些轻量数据类型可以在赋值或传参时自动复制。本篇继续进入Rust所有权体系中非常重要的概念: Borrow 中文通常称为“借用”。 前面我们已经知道,String、Vec等非Copy类型传递给另一个变量或函数时,通常会发生所有权移动: fn print_name(name: String) { println!("{}", name); } fn main() { let name = S


Rust图像处理第22节-从RGB到YCbCr: 让亮度和颜色分家
花褪残红青杏小2026/7/31

🦀 Rust + WASM 实战系列 第 22 篇 阅读时间:约 8 分钟 | 实战可运行 📌 写在前面 前面 21 篇,所有图像都是拿 R、G、B 三个数表示的。这一篇换一套坐标系:一个亮度 + 两个色度。 手机里的每一张照片、你看的每一个视频,存进文件之前都会先做这个转换。原因很简单:人眼对亮度极其敏感,对颜色极其迟钝,把两者分开之后,颜色那部分可以随便砍。 数学上,它就是一个 3×3 矩阵(19节的矩阵 × 向量)加它的逆矩阵(21节的 try_inverse) 🚀 TL;DR


🤯 面试被问 AI Workflow 和 Agent 有啥区别?3 张图 + 2 段代码讲清楚!
ReBound2026/7/23

🤯 面试被问 AI Workflow 和 Agent 有啥区别?3 张图 + 2 段代码讲清楚! 摘要:Workflow 和 Agent 到底有啥区别?为什么 Coze 工作流和 ReAct Agent 看起来都在"执行任务",本质却完全不同?本文从面试翻车经历出发,结合 Anthropic 官方定义、ReAct 框架、完整代码示例和实战选型指南,帮你彻底搞懂这对最容易混淆的 AI 概念。 📌 前言 上周面试,面试官笑眯眯地问了一句: "你说说 AI Workflow 和 Agent


大模型入门:从“猜词游戏“到“超级大脑“,一篇读懂 AI 大模型
修己xj2026/7/15

2023 年初,ChatGPT 横空出世,"大模型"三个字一夜之间刷爆了所有人的朋友圈。有人拿它写代码,有人拿它写情书,还有人拿它辅导孩子做数学——而且它居然真的会。 可当你真正想搞懂"大模型到底是什么"时,迎面而来的却是满屏的"Transformer""自注意力""千亿参数",瞬间劝退。 别慌。这篇文章,我们用打比方的方式,把大模型从里到外讲清楚。 一、什么是大模型?先搞懂"大"在哪 今天大家口中的大模型,通常特指大语言模型(LLM,Large Language Model)。ChatGPT


【Java实习面试算法冲刺】双指针
ZenithSourceQuest2026/7/6

第2类题型:双指针 为什么双指针题看起来不难,你一到面试就容易写乱 很多同学第一次刷双指针时,会觉得这类题比哈希表还“直观”。因为代码通常不长,变量也常常只有 left、right、slow、fast 四个名字。但真正到了面试现场,双指针反而很容易暴露出两类问题: 你会套模板,但说不清两个指针各自代表什么。你知道要移动某一边,却解释不出“为什么这样移动不会漏解”。你能把 三数之和 写个大概,却总在去重和边界上翻车。你把“会写代码”当成“理解题型”,结果一换题面就不稳。 如果你


论虚拟线程与 Kotlin IO 协程:资源开销、时长、高并发表现及适用场景与技术选型思考
zimoyin2026/6/28

在现代并发编程中,虚拟线程(由 Java 20+ 引入)和 Kotlin IO 协程(基于 Dispatchers.IO)是两种高效处理异步任务的技术框架。在资源开销、时长(特别是长时间 IO)、高并发场景表现、以及何时选择合适方案等方面各有特点。本文将逐一展开对比分析。 1. 资源开销对比 虚拟线程和协程的核心开销差异源于其底层设计原理: 维度虚拟线程Kotlin IO 协程关键差异内存开销固定栈机制:默认约 1MB1\text{MB}1MB 占⽤[注1]动态内存分配:2KB∼512KB2

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读