14.02概念更新于 2026年9月17日

各类动作的验证方式

发邮件看 message_id、写库后读回、改代码跑测试、发布后做 HTTP 检查。

14.02 · 课时讲解

各类动作的验证方式

换一条独立的路径,去读世界的真实状态。

1 / 12

一句话理解:验证就是换一条独立的路径去读世界的真实状态:发出去的查回执,写进去的读回来,改过的代码跑测试,上线的页面去访问。

上一课说明了“已完成”不等于真的完成。但落到需求评审时,大家常常卡在一个很具体的问题上:**这个动作,到底怎么验证?**说一句“要验证结果”没有用,研发需要知道读哪个接口、比对哪些字段、比对不上怎么办。

这一课给出一个通用公式,一张覆盖常见动作的速查表,再细看 Coding、发票审核和发布上线三个场景。

验证的通用公式

不管什么动作,验证都可以拆成五个要素:

验证的通用公式:动作、预期状态、观测通道、比对、判定,以创建工单为例 动作 预期状态 观测通道 比对 判定 创建工单 存在一张工单 标题=X 负责人=Y 按 ID 查询 工单接口 标题、类型 负责人 通过 / 失败 无法判断 通道要独立 比对关键字段 三态判定 三条原则 →
图 1 · 验证的五个要素,以“创建工单”为例;下方是三条原则

有三条原则:

  1. 观测通道要独立。 不要拿写接口自己的返回值证明写入成功,而是用另一个读接口去查。独立程度越高,证据越可信。
  2. 比对具体字段,而不只是“有没有”。 工单存在但负责人写错了,仍然是失败。事先定义哪些字段是关键字段。
  3. 判定有三种结果,不是两种。 除了“通过”和“失败”,还有“无法判断”:例如消息已受理但投递状态要几分钟后才能查到。把第三种状态显式记录下来,才能安排延迟复查,而不是被当成成功。

动作与验证方式速查表

动作类型 例子 验证方式 保留的证据 注意事项
读取数据 查询订单、操作日志 结构校验、关键字段非空、取值范围检查 原始返回 空结果不等于“没有问题”,可能是数据缺失
计算分析 计算超时时长、金额差额 用代码计算,不让模型心算;结果回填给模型 计算输入与输出 注意时区与单位
发送消息 发邮件、发 IM 通知 检查返回的消息 ID;高风险场景再查投递状态 消息 ID、投递回执 “已受理”不等于“已送达”
写入记录 修改工单状态、写入审核结论 写后读回,比对关键字段 读回的记录 主从延迟可能导致刚写完读不到,需要短暂等待后再读
创建对象 创建工单、创建任务 按返回 ID 查询详情;检查是否重复创建 对象 ID 与详情 重试前先查是否已创建,避免建两张工单
修改代码 修复 Bug、加功能 构建、类型检查、运行相关测试与全量测试 测试输出、diff 警惕“为了通过而改测试”
发布上线 部署页面、更新配置 访问线上地址,检查状态码与关键内容 响应码、页面片段 CDN 缓存可能返回旧版本
生成文档 诊断报告、分析结论 结构检查、数字回溯到数据源、引用可追溯、按标准评审 引用列表 语义质量可以用 LLM 评审辅助
界面操作 在后台页面提交表单 截图,并检查成功提示或列表中出现新记录 截图、页面状态 页面改版会让选择器失效
文件操作 导出 CSV 报表 检查文件存在、行数、表头与抽样内容 文件元信息 空文件也是“导出成功”

Anthropic 在 Claude Agent SDK 的工程文章里把验证手段分成三类:基于规则的反馈(例如代码 lint,明确指出哪条规则失败、为什么失败)、视觉反馈(例如对生成的 HTML 邮件截图检查排版),以及用另一个模型按模糊标准评审(它也提醒这种方式稳健性较弱、会增加延迟)。上表中大部分行属于第一类,这也是应该优先使用的一类。

把速查表里的动作按这三类手段重新归组:

按三类验证手段归组的动作:基于规则的反馈、视觉反馈、LLM 评审 基于规则的反馈 优先使用 读取数据 结构与非空校验 计算分析 代码重算 发送消息 查消息 ID 写入记录 写后读回 创建对象 按 ID 查询并查重 修改代码 类型检查与测试 发布上线 访问线上地址 文件操作 检查行数与表头 视觉反馈 界面操作 截图查成功提示 HTML 邮件 截图检查排版 LLM 评审 生成文档 语义质量按标准评审 稳健性较弱、会增加延迟,只用于语义质量
图 2 · 大部分动作都能用规则反馈验证;视觉反馈与 LLM 评审只补规则覆盖不到的部分

三个场景细看

Coding Agent:测试是天然的验证器

Coding Agent 之所以进步快,一个重要原因是代码领域自带反馈闭环:编译器、类型检查、测试都能给出客观的通过或失败(参见办公 Agent 与 Coding Agent)。一个好的修复流程应该是:

# 示例:Coding Agent 修复金额计算 Bug 之后的验证序列
npm run typecheck                               # 1. 类型检查
npm test -- tests/pricing.test.ts               # 2. 先跑能复现 Bug 的用例,确认由红变绿
npm test                                        # 3. 再跑全量测试,防止改好一个坏掉一片
git diff --stat                                 # 4. 检查改动范围,是否碰了不该碰的文件

第 4 步经常被忽略。如果 Agent 修改了测试断言让测试“通过”,前三步全是绿的,问题却没有解决。可以用规则强制检查:diff 里出现测试文件的断言变更时,标记为需要人工复核。

把这四步和失败时的去向画出来:

Coding Agent 修复后的验证序列:类型检查、复现用例、全量测试、检查 diff,失败与断言变更的去向 ① 类型检查 typecheck ② 复现用例 由红变绿 ③ 全量测试 防止改坏别处 ④ 检查 diff 改动范围是否越界 汇报 附测试输出 任一步失败:带着报错重新修改 测试断言有变更 断言被修改 → 人工复核
图 3 · 四步验证全部通过才汇报;任一步失败带着报错重改,测试断言被改则交人复核

发票审核 Agent:规则与数据交叉核对

发票审核 Agent 从发票图片中抽取字段,再给出“通过 / 退回”的结论。抽取结果不能只靠模型“看起来对”,很多检查可以写成确定性规则:

from decimal import Decimal

def check_invoice(inv: dict, po: dict) -> list[str]:
    """返回未通过的检查项;空列表表示全部通过。"""
    issues = []
    net = Decimal(inv["net_amount"])
    tax = Decimal(inv["tax_amount"])
    total = Decimal(inv["total_amount"])

    if net + tax != total:
        issues.append("价税合计不等于金额加税额")
    if inv["buyer_tax_id"] != po["company_tax_id"]:
        issues.append("购买方税号与采购主体不一致")
    if total > Decimal(po["approved_amount"]):
        issues.append("发票金额超过采购单批准金额")
    return issues

审核结论写入财务系统之后,再按单据号读回,确认状态和备注已经更新。模型负责看懂发票、解释退回原因,算术与一致性交给程序。

发布上线:部署完去访问一次

假设 SEO 诊断 Agent 修改了一个页面的 title 并触发部署。“部署任务成功”只能说明流水线跑完了,真正的验证是访问线上页面:

# 示例:发布后检查(URL 为示意)
curl -s -o /tmp/page.html -w "%{http_code}\n" https://example.com/pricing   # 期望输出 200
grep -o "<title>[^<]*</title>" /tmp/page.html                               # 期望包含新标题
grep -c 'rel="canonical"' /tmp/page.html                                    # 期望为 1

如果状态码正确但标题还是旧的,多半是缓存问题。此时判定应为“无法判断”,并安排几分钟后复查,而不是直接报告成功或失败。

把验证结果记录下来

每次验证都应该留下结构化记录,供汇报、Tracing 与任务状态使用(示例):

{
  "action_id": "act_07",
  "action": "update_ticket_status",
  "expected": { "ticket_id": "T-20260917-0042", "status": "fix_confirmed" },
  "method": "read_back",
  "observed": { "status": "fix_confirmed", "updated_by": "agent-support" },
  "verdict": "passed",
  "checked_at": "2026-09-17T10:21:04+08:00"
}

有了这条记录,最终汇报可以附证据,出了问题可以回查,评测时也能直接统计“写操作验证通过率”。

常见误区

  • 用写接口的返回值证明写入成功。 返回值和实际写入可能不一致,应当独立读回。
  • 只验证“有没有”,不验证“对不对”。 工单建了但类型和负责人写错,下游照样出事。事先列出关键字段。
  • 把验证写进 Prompt,指望模型“记得检查”。 模型可能跳过。关键验证应当由 Harness 强制执行,例如在工具调用后的钩子里自动读回,参见 Hooks 与生命周期。
  • 忽略异步与延迟生效。 消息投递、搜索引擎收录、缓存刷新都需要时间。立即检查失败,不代表动作失败。

设计要点

  • 为每一类动作写下“预期状态、观测通道、关键字段、判定规则”四项。
  • 优先使用确定性验证(读回、测试、规则、HTTP 检查),LLM 评审只用于语义质量。
  • 验证结果使用“通过 / 失败 / 无法判断”三态,并为“无法判断”设计延迟复查。
  • 创建类动作的重试前先查重,保证幂等。
  • 验证逻辑放在 Harness 或工具层强制执行,不依赖模型自觉。

练习

以实战项目「可执行的售后处理 Agent」为对象(它能创建工单、发送通知、修改状态),为下面 5 个动作填写验证表:

动作 预期状态 观测通道 关键字段 失败或无法判断时怎么办
查询订单与操作日志
计算超时时长
创建处理工单
邮件通知负责人
修改工单处理状态

做完后再检查一遍:有没有哪一行的“观测通道”其实就是动作本身的返回值?

延伸阅读

下一步

速查表里反复出现“换一条独立通道”。下一课「自我检查与外部验证」会解释为什么让模型自己检查不够,以及模型互评和程序验证各自可靠到什么程度。

试试:上下文、MCP、沙箱、Prompt 注入、外链