AI 系统最棘手的问题往往不是抛出异常,而是顺利返回一段看似合理、实际上遗漏约束或缺少证据的结果。这类“静默失败”会绕过传统监控:HTTP 状态码是 200,JSON 可以解析,日志里没有堆栈,但业务结论已经偏离目标。
围绕“上下文、检查清单和无遗漏复核”组织 Agent 工作流,关键不是让模型多思考一次,而是把生产、审查和放行拆成可观察、可验证的步骤。
为什么成功响应不等于任务成功
传统服务通常有清楚的失败信号:超时、异常、非零退出码或违反数据库约束。AI 输出的失败边界则模糊得多,常见情况包括:
- 遗漏约束:回答了主要问题,却忽略日期范围、格式要求或禁止事项。
- 未经证实的断言:语言很确定,但没有引用输入材料中的证据。
- 上下文漂移:多轮执行后,Agent 开始优化局部步骤,忘记最终交付目标。
- 工具调用不完整:搜索或读取操作成功,但没有覆盖全部对象。
- 审查同源偏差:同一个模型用相近提示词复核自己的结果,重复了原有判断。
因此,监控不能只问“调用是否成功”,还要回答三个问题:任务要求是否完整传递,输出是否逐项满足要求,以及复核过程是否真正覆盖了高风险部分。
把上下文变成可执行契约
长提示词不等于可靠上下文。更实用的方式是把上下文拆成结构化字段,让执行器和审查器读取同一份任务契约:
job_id: report-2025-03
objective: 根据给定材料生成季度风险摘要
inputs:
- quarterly_report.txt
constraints:
language: zh-CN
max_words: 500
require_evidence: true
forbidden_claims:
- 不得推测未披露的财务数据
acceptance_checklist:
- 覆盖运营、财务和合规风险
- 每项风险包含输入材料中的证据
- 明确区分事实与建议
- 不包含输入材料之外的数字
review_policy:
minimum_score: 4
block_on_missing_evidence: true
这份契约有两个作用。一方面,它减少自然语言指令在多 Agent 之间传递时的损耗;另一方面,它给自动化验收提供稳定字段。生产 Agent 可以自由组织文字,但不能自由解释什么叫“完成”。
对于长流程,还应记录上下文版本、输入材料摘要和工具结果。否则,即使发现错误,也很难判断是模型推理失误、检索遗漏,还是上游输入发生了变化。
检查清单要产生证据,而不是只打勾
“请检查答案是否正确”通常只能得到宽泛评价。更有效的复核要求审查器逐项返回状态、证据和问题位置。例如:
{
"checks": [
{
"id": "evidence",
"passed": false,
"evidence": [],
"issue": "财务风险段落没有引用输入材料"
}
],
"approved": false
}
这里最重要的字段不是 approved,而是每项检查的证据。没有证据的“通过”只能算模型意见,不能算验收结果。
检查项也不宜无限增长。可以把确定性规则交给代码,例如字段完整性、字数、引用格式和数值范围;把语义判断留给模型,例如结论是否被材料支持、是否遗漏关键风险。代码检查便宜且可重复,模型复核则用于处理无法简单编码的边界。
可以这样实践:构建一个失败即阻断的最小工作流
下面示例只使用 Python 标准库,可以直接运行。为保持示例独立,generate_draft() 模拟生产 Agent,semantic_review() 模拟模型审查器;接入真实系统时,可以将这两个函数替换为模型 API 调用,同时保留任务契约、确定性检查和放行逻辑。
from dataclasses import dataclass, field
from typing import List
@dataclass
class TaskContract:
required_sections: List[str]
max_words: int
require_evidence: bool = True
@dataclass
class Draft:
text: str
evidence: List[str] = field(default_factory=list)
@dataclass
class ReviewResult:
approved: bool
issues: List[str]
def generate_draft(source: str) -> Draft:
# Replace this function with a worker-agent API call.
return Draft(
text=(
"运营风险:关键供应商交付延迟。\n"
"财务风险:成本可能继续上升。\n"
"合规风险:新规要求更新数据保留流程。"
),
evidence=["材料第 2 节:关键供应商平均延迟 12 天"]
)
def deterministic_review(draft: Draft, contract: TaskContract) -> List[str]:
issues = []
for section in contract.required_sections:
if section not in draft.text:
issues.append(f"缺少必要章节:{section}")
if len(draft.text.split()) > contract.max_words:
issues.append("输出超过字数限制")
if contract.require_evidence and not draft.evidence:
issues.append("没有提供证据")
return issues
def semantic_review(source: str, draft: Draft) -> List[str]:
# Replace this function with an independent reviewer-agent API call.
issues = []
if "成本可能继续上升" in draft.text and "成本" not in source:
issues.append("财务风险包含输入材料无法支持的推测")
if len(draft.evidence) < 3:
issues.append("并非每项风险都有对应证据")
return issues
def run_job(source: str, contract: TaskContract) -> ReviewResult:
draft = generate_draft(source)
issues = deterministic_review(draft, contract)
issues.extend(semantic_review(source, draft))
# Fail closed: unresolved findings prevent publication.
result = ReviewResult(approved=not issues, issues=issues)
print("DRAFT:\n", draft.text)
print("\nAPPROVED:", result.approved)
for issue in result.issues:
print("-", issue)
return result
if __name__ == "__main__":
source = (
"材料第 2 节:关键供应商平均延迟 12 天。"
"材料第 5 节:新规要求更新数据保留流程。"
)
contract = TaskContract(
required_sections=["运营风险", "财务风险", "合规风险"],
max_words=500,
)
run_job(source, contract)
运行命令:
python oversight.py
该示例会阻止草稿通过,因为财务结论缺少来源支持,而且三项风险没有分别提供证据。真实工作流还应保存草稿、检查结果、模型版本、提示词版本和输入哈希,以便重放与审计。
独立复核也有边界
增加 Reviewer Agent 并不自动消除错误。如果生产者与审查者使用相同模型、相同上下文和相似提示词,它们可能共享盲点。高风险任务可以采用不同复核层:代码验证硬约束,独立模型检查语义,人工审批处理高影响决策。
同时要防止“无限复核”。Agent 反复修改和审查会增加成本,也可能在修复一个问题时引入另一个问题。更稳妥的策略是限制重试次数,为问题分级,并在连续失败后转交人工处理。
上线前的验收清单
一套可落地的监督机制至少应满足这些条件:
- 任务目标、输入、约束和验收项采用结构化格式保存。
- 每个检查项都返回证据或明确的问题描述,而不只是布尔值。
- 确定性规则由代码执行,语义问题再交给模型判断。
- 未解决的高风险问题默认阻断发布。
- 生产与复核步骤分别记录模型、提示词、输入和输出版本。
- 工作流设置最大重试次数,并提供人工升级路径。
- 使用真实失败案例建立回归测试集,而不是只测试理想输入。
AI 静默失败无法靠一句更强的提示词彻底解决。真正有效的监督来自工程化边界:明确什么算完成,要求每次通过都有证据,并让失败在进入业务系统之前变得可见。