别让 AI Agent 先画靶再射箭:一套「结论忠于数据」的证据链工作流

你让 AI 写一份"接口性能月报",它 3 秒输出,结构漂亮、金句频出------但数据哪来的?口径对齐了吗?追两个问题就崩。这不是模型不够聪明,而是我们把"汇报顺序"这个人类职场的老问题,原封不动地交给了 Agent,还以为它会自己解决。

TL;DR

  • 分析/汇报类任务有两种典型翻车姿势:先想结论再找数据 (先画靶后射箭)和 先倒数据再组织内容(数据陈列馆)。
  • 正确顺序是三段式:问题先于数据,数据先于结论,结论只忠于数据。
  • 落地抓手是三件套:Task Contract (定问题)、Claim--Evidence 绑定 (结论挂证据)、Confidence Gate(缺口披露 + 对抗验证)。
  • 文末附可直接抄进 System Prompt 的模板,以及完整的最小可用实现。

一、从一个真实场景说起

周一早上,你对你的 AI Agent 说:

text 复制代码
线上 /orders 接口 P99 从 200ms 涨到了 800ms。
帮我分析一下原因,下午要向老板汇报。

30 秒后,Agent 交给你一份排版精美的报告,核心结论加粗显示:

根因:数据库慢查询导致接口性能劣化,建议为 orders 表增加复合索引。

逻辑通顺、行文流畅、结论明确。你追问一句:"慢查询日志在哪?你看了吗?"

它开始改口。再追问数据来源和统计口径,整份报告开始松动。最后你发现:它根本没看过任何日志,"慢查询"只是从"P99 上涨"和"涉及数据库"这两个信号推理出来的最合理叙事。

这不是模型能力问题。让任何一个聪明的实习生"不查任何资料、先写根因分析",他也能交出一份同样漂亮的稿子。问题出在我们把任务的执行顺序搞错了。

二、两种失败模式:画靶射箭 vs 数据陈列馆

做分析、写汇报,本质上是在回答一个问题:先想输出什么,再找数据?还是先看数据,再决定输出什么?

答案是:两个都不选。这是假二选一,两种纯做法都会翻车,只是翻车姿势不同。

做法 学名 翻车姿势
先想输出什么内容 → 再找数据 先射箭后画靶(确认偏误) 结论先于证据。稿子漂亮,数据是的。被追问"数据哪来的?口径对齐了吗?边界 case 呢?"当场崩盘
先看有什么数据 → 再输出内容 数据陈列馆(无观点流水账) 没有目标牵引,把数据仓库倒出来完事。读者看完还得自己做分析、自己下结论------你把决策成本转嫁给了读的人

失败模式 A:先画靶,后射箭

这是最危险的一种,而且 LLM 是它的放大器,不是矫正器

经过指令对齐的语言模型,有一种被严重低估的倾向:它太擅长顺着既定结论讲故事了。一旦"根因是慢查询"这个假设先入为主,后续所有"检索"和"分析"都会变成给这个结论找论据------它会下意识地挑选、重新解释,甚至虚构支持性证据。

这就是幻觉最肥沃的土壤。不是模型"不知道",而是它太知道你想要什么。你用一句"帮我分析原因"隐式地预设了"存在一个可分析的原因",它就顺坡下驴,给你一个 causally-correct-looking 的故事。

失败模式 B:数据陈列馆

反过来,如果没有任何问题牵引,直接"把你知道的都吐出来",你会得到一份没有结论、没有优先级、没有建议的流水账。读者需要自己在几十条信息里挖出那个决策点。

汇报的目的不是展示劳动量,是推动决策。 没有问题的数据堆砌,等于把最贵的认知工作(下结论)原封不动地推给了读者。

三、正确顺序:三段式工作流

text 复制代码
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ ① 定问题    │ ──> │ ② 拉数据    │ ──> │ ③ 出结论    │
│ 不是定结论  │     │ 缺口要披露  │     │ 绑定证据链  │
└─────────────┘     └─────────────┘     └─────────────┘

① 先定问题,不定结论

任何分析任务开工前,先把三个东西写下来(对 Agent 来说,就是先产出一个结构化的 Task Contract):

  • Intent:这次分析要回答什么问题?读者是谁?读完要做什么决策?
  • Acceptance:结论要满足什么条件才算成立?(例如:"每个结论必须引用至少一条可复核的数据来源")
  • Forbidden:明确禁止的行为。(例如:"禁止输出没有证据来源的因果论断")

注意:这里定的是问题,不是答案。 "为什么 P99 上涨"是问题,"因为慢查询"是答案------前者是开工的前提,后者必须是数据的产物。

② 按问题反向拉数据

有了问题,才知道拉什么数据。这里有两个对 Agent 尤其重要的纪律:

  1. Agent 没有"库存数据"。它面对的世界是可查询的,数据是按需拉取的。所以"先看有什么数据再写"这个选项在物理上不存在------必须先有问题,才知道调用什么工具、查什么源。
  2. 数据缺口必须显式披露,禁止脑补。 查不到 JVM GC 日志,就写"GC 数据未采集,无法排除 GC 停顿因素",而不是默默用推测补上这块拼图。

③ 让数据决定结论

叙事结构是第 ① 步定的,但结论内容由证据链决定。当数据打脸预设故事时:改故事,不改数据。

这是整个工作流里最难的一条------对人类难(沉没成本、面子),对 LLM 更难(它天生倾向于输出"你期待的叙事")。所以这条纪律不能靠"提醒模型注意",必须结构化地强制执行:结论必须绑定证据,绑不上证据的声明不允许进入最终报告。下一节看怎么落地。

一句话总结:question before data, data before conclusion, conclusion loyal to data.

四、落地实现:一个最小可用的证据链 Agent

思路不复杂,代码也不复杂。核心是三个组件:Task Contract、Claim--Evidence 绑定、验证门。

4.1 Task Contract:把"要回答什么"写成合同

python 复制代码
from dataclasses import dataclass, field

@dataclass
class TaskContract:
    intent: str                      # 要回答什么问题(不是答案!)
    audience: str                    # 读者是谁,读完做什么决策
    acceptance: list[str] = field(default_factory=list)   # 结论的验收标准
    forbidden: list[str] = field(default_factory=list)    # 明确禁止的行为
    verify_commands: list[str] = field(default_factory=list)  # 可执行的验证命令

比如那个 P99 案例,contract 长这样:

python 复制代码
contract = TaskContract(
    intent="定位 /orders 接口 P99 从 200ms 涨到 800ms 的主要贡献因素",
    audience="技术负责人,需基于结论决定是否今晚发布热修复",
    acceptance=[
        "每个结论至少绑定 1 条可复核的数据来源",
        "区分 verified(已验证)/ inferred(推断)/ gap(数据缺口)",
        "数据不足时显式披露,不得用推测填补关键结论",
    ],
    forbidden=[
        "禁止输出无证据来源的因果论断",
        "禁止为了叙事完整性而虚构数据",
    ],
    verify_commands=[
        "查询 APM 系统最近 7 天 /orders 分位数曲线",
        "导出慢查询日志 Top 50",
    ],
)

4.2 Claim--Evidence 绑定:每条结论挂着证据出厂

python 复制代码
from dataclasses import dataclass
from typing import Literal

Confidence = Literal["verified", "inferred", "gap"]

@dataclass
class Claim:
    statement: str          # 结论本身
    evidence: list[str]     # 证据来源:命令输出 / 日志行号 / API 响应摘录
    confidence: Confidence  # 置信级别

关键规则:报告中每一句话要么是某条 Claim 的展开,要么删掉。 gap 级别的 Claim 不是错误------"数据缺口"本身是诚实的交付物,但关键路径上的 gap 必须触发补数据动作,而不是被静默忽略。

4.3 主循环:定问题 → 拉数据 → 草拟 → 验证门

python 复制代码
def report_agent(user_request: str) -> "Report":
    # ① 先定问题,不定结论
    contract = extract_contract(user_request)

    # ② 按问题反向拉数据(工具调用在此发生)
    raw_evidence = gather_evidence(contract)

    # ③ 草拟报告:每条结论必须尝试绑定证据
    draft = draft_report(contract, raw_evidence)

    # 验证门:claim ↔ evidence 逐一核对
    report = verify_claims(draft)

    # 关键路径上的 gap:先补数据,补不到就显式披露
    for claim in report.critical_claims_with_gaps():
        patched = try_gather_more_evidence(claim, contract)
        if not patched:
            claim.disclose_gap(reason="证据不可得,需人工补充数据源")

    return report

注意 verify_claims 这一步------它不该由同一个上下文"自证清白"。更稳的做法是对抗验证:另起 N 个独立实例,System Prompt 只有一个任务------"尝试推翻这条结论",多数推翻即毙掉该结论。这就是用流程消灭"自我评价权滥用"。

4.4 可直接抄走的 System Prompt 模板

把这段放进你的 Agent System Prompt,汇报类任务的幻觉率会立竿见影地下降:

text 复制代码
你是一个证据链驱动的分析 Agent。遵守以下规则:

1. 开工先输出 Task Contract(intent / acceptance / forbidden),
   定的是问题,不是结论。Contract 获得确认后再拉数据。
2. 数据按需拉取:先有问题,再定查什么。查得到就去查。
3. 每条结论必须绑定证据来源。没有来源的声明,禁止写入报告。
4. 数据与任何预设叙事冲突时:修改叙事,禁止修改数据。
5. 数据缺口必须显式披露(标注 gap),禁止用推测填补关键结论。
6. 交付格式固定为三段:候选结论 + 证据链 + 剩余风险。
   你只能产出 candidate 状态,最终状态由验证方或用户确认。

第 6 条值得单独强调:让 Agent 只拥有"提出候选结论"的权力,而把"宣布完成"的权力留给验证环节。 行动权、自评权、评分权、环境修改权四权分离------这是防止 Agent "自己写题、自己答题、自己打满分"的架构级防线。

五、案例分析:同一个问题,两种交付

还是开头那个 P99 案例。对比一下两种 Agent 的实际输出形态。

反例(先想结论,再找数据)

text 复制代码
【根因分析报告】

经过深入分析,/orders 接口性能劣化的根因是数据库慢查询。
建议为 orders 表的 user_id 字段增加索引,预计可将 P99
降低 60% 以上。此外,建议开启查询缓存以进一步优化。

特征:结论因果完整、建议具体到字段、通篇没有一条证据来源。"预计降低 60%" 这种数字是从哪来的?从模型对"加索引很有效"的先验里编的。老板要是真拿这句话去做发布决策,这就是事故报告的第一行。

正例(证据链驱动)

json 复制代码
{
  "claims": [
    {
      "statement": "P99 劣化与 orders 表慢查询高度相关",
      "confidence": "verified",
      "evidence": [
        "慢查询日志 Top 50 中,orders 表 SELECT 占 37 条(近 24h)",
        "APM 数据库 span 耗时占比从 41% 升至 76%"
      ]
    },
    {
      "statement": "劣化起点与 v2.3.1 发布时间吻合,疑似与新增统计查询有关",
      "confidence": "inferred",
      "evidence": [
        "劣化起始时间 09-03 14:20,v2.3.1 发布于 09-03 14:05",
        "新代码引入了 SELECT COUNT(*) 全表统计(commit a1b2c3d)"
      ]
    },
    {
      "statement": "GC 停顿是否为次要贡献因素",
      "confidence": "gap",
      "evidence": ["GC 日志未采集,需运维开启后复核"]
    }
  ],
  "remaining_risks": ["索引变更需评估写放大,建议先在影子库验证"]
}

同样的问题,第二种交付的每个数字都能被复核,每个推断都标了置信级别,每个缺口都摆在了明面上。下午的汇报,你敢拿哪份上会?

六、进阶:把"验证"做成流程,而不是口号

三段式工作流跑通之后,还有三个升级方向:

  1. 置信门控(Confidence Gate):交付前强制执行"漏洞 → 修复 → 验证"循环。逐条自问"这条结论最可能是假的,假在哪?"------关键结论未验证、关键缺口未披露,就不允许输出"已完成"。
  2. 对抗验证(Adversarial Verify):为每条关键结论 spawn 一个"专职反驳者",提示词只有一句话------"尝试推翻它"。多数被推翻的结论直接毙掉。这一招专治 LLM 的叙事惯性。
  3. 权责分离:不要让同一个 Agent 既写报告、又给自己验收、还能改验收标准。行动、自评、评分、环境修改四种权力分给不同角色,最终状态由外部验证方(另一个实例或人类)确认。

七、总结

回到最初的问题:做汇报,是先想输出再找数据,还是先看数据再输出?

  • 两个都不对。前者是先画靶后射箭,LLM 会把它放大成系统性幻觉;后者是无观点的流水账。
  • 正确的顺序是三段式:定问题(不是定结论)→ 反向拉数据(缺口显式披露)→ 让数据决定结论(绑定证据链)。
  • 落地三件套:Task Contract 写清楚要回答什么、Claim--Evidence 绑定让结论挂着证据出厂、Confidence Gate 把"验证"变成流程而非口号。

最后送一份自查清单,发报告前过一遍:

  • 开工时定的是问题,还是不知不觉写成了结论?
  • 每条关键结论,都能指出具体的数据来源吗?
  • 数据打脸预设故事时,改的是故事,还是数据?
  • 所有数据缺口,都明说了吗?有没有被推测悄悄填上的?
  • "已完成"这三个字,是验证过之后说的,还是感觉上该说了?

问题先于数据,数据先于结论,结论只忠于数据。 把这十五个字刻进你的 Agent(或者你自己)的工作流里,汇报这种事,就再也不怕追问了。


如果这篇文章对你有帮助,欢迎点赞收藏,评论区聊聊你的 Agent 都画过什么靶、射过什么箭。

相关推荐
静开1 小时前
模型没换、提示词没动,成功率从不到 70% 干到 95% —— 改的到底是什么
agent
掰头战士1 小时前
从LLM到Agent、Agent的6大核心。这些基础知识你还记得吗
node.js·llm·agent
甜辣uu1 小时前
智能体Agent性能优化从原理到实战
人工智能·性能优化·大模型·llm·agent·rag·智能体
一 铭1 小时前
软件诞生于 Commit 之间:聊聊 Zed 的 DeltaDB
人工智能·ai·agent
云烟成雨TD4 小时前
LlamaIndex 系列【21】语义检索(Semantic Search)
ai·agent·rag·llamaindex
云烟成雨TD6 小时前
LlamaIndex 系列【20】关键词检索(Keyword Search):BM 25 算法
ai·agent·rag·llamaindex
然我7 小时前
从 Service 到生命周期:Agent Runtime 的插件内核
前端·javascript·agent
AIGC大时代7 小时前
评科研 LLM/Agent:从读论文抽检到 ERA 树搜索写可计分实证软件
llm·agent·评测·科学发现·google research
机械改造鹅7 小时前
从零开始拆解Pi系列——(10)slash 命令系统
agent