定位:专业复盘体 + 分点 + 图。原稿:《运维诊断 Agent 防幻觉实践》
在 AI Agent 落地过程中,幻觉是最难处理的问题之一。尤其在运维诊断场景,Agent 会编造并不存在的日志内容、凭空捏造错误码,输出结果基本不可用。
我最初的反应是:Agent 太散了,应该把它拆开,多建几个节点来约束它。于是引入了 Verifier(校验结论能否推导)和 Gatekeeper(校验输出结构是否合法),让它们去卡 Executor 的输出。这个思路看似合理,实际只是用架构的复杂度掩盖了上下文工程的不足,没有触及根源。
本文结合一个真实的运维诊断场景,梳理幻觉的来源,以及最后沉淀下来的一套「单 Agent + 四层防线」方案。
幻觉从哪来
在设计防幻觉方案之前,先把病因找准。有一个观点说得很准确:幻觉源于上下文缺失。
Executor 之所以会过度输出和产生幻觉,根本原因归结为以下三点:
- 脏数据淹没:工具返回的数据太脏、太多,淹没了关键信息,模型为了「消化」这些冗余数据,开始编造关联性。
- 缺乏契约约束:Prompt 没有强约束输出格式,模型开始「自由发挥」,生成散文式分析。
- 闭环缺失:模型只基于单方面的工具结果「自圆其说」,缺乏真实世界的负反馈机制。
为什么多 Agent 审查行不通
最初的设计里,我们专门加了 Gatekeeper 和 Verifier 节点去拦截、校验 Executor 的输出,结果问题反而更大。原因有三点:
- 事后纠偏,成本太高:让 Executor 先跑完,生成一堆幻觉文本、消耗大量 token 和算力,再让另一个 LLM 去审查。审查节点本身也是 LLM,同样可能幻觉,事后审查的方式并不划算。
- 污染源没切断:Executor 过度输出的根源是上下文太长、数据太脏。不去清洗数据、压缩上下文,反而在外面增加编排节点,该膨胀还是膨胀,该编造还是编造。
- 节点间通信引入新幻觉:多个节点之间用自然语言传递状态,容易产生理解偏差,主控可能误解子节点的摘要,造成「传话传错」的二次幻觉。
结论是:用多 Agent 互相监督来防幻觉,管理成本翻倍,根源问题却没有解决。
四层防线:把幻觉扼杀在源头
防幻觉的正确思路是源头拦截。我们最终采用单 Agent + Harness 架构,建立了四道防线:
flowchart TD Start[工具原始返回] --> L1[第一道防线<br>工具层RTK清洗] L1 --> L2[第二道防线<br>JSON Schema契约约束] L2 --> L3[第三道防线<br>物理门禁验真] L3 --> L4[第四道防线<br>多维度交叉验证] L4 --> End[输出诊断报告]
第一道防线:工具层清洗(RTK 机制)
解决的问题:查日志返回上千行,模型为了消化数据开始编造。
做法:工具返回给 Agent 之前,Harness 代码先做强制清洗。查日志只保留 ERROR 级别及前后几行,INFO 直接过滤;查数据库把几百行记录聚合成几个关键指标(如「连接池占用率 98%」);查监控只返回异常时间段的数据点。
效果:进入 Agent 上下文的数据越干净、越精炼,模型自由发挥的空间就越小。
第二道防线:契约式输出约束
解决的问题:Agent 输出大段散文式分析,甚至脑补并不存在的错误码。
做法:在 System Prompt 里强制要求每次思考和行动符合 JSON Schema,并在代码层校验:
{
"thought": "思考过程,不超过50字",
"action": "queryLogs",
"params": {"service": "order", "time": "last_10m"},
"evidence_id": null
}
代码拦截:thought 超过 50 字或格式不符,代码层直接打回重试,不消耗额外的 LLM 调用。Gatekeeper 真正的形态,应该是一行 Linter 代码,用一个大模型节点来做这件事反而是浪费。
第三道防线:物理门禁验真
解决的问题:Agent 在报告里写「根据日志显示发生了 504 超时」,但它根本没有查询那个时间段的日志。
做法:Agent 输出最终报告时,Harness 代码执行后置断言:报告里的每个证据 ID 是否在本次会话的历史工具调用中真实存在;报告引用的日志路径在文件系统里是否真实存在。不合法就直接拒绝输出,返回错误让 Agent 重试。验真靠代码查真实系统,不靠 LLM 判断。
第四道防线:多维度交叉验证
解决的问题:Agent 查了日志就基于日志下结论,但日志可能只是表象。
做法:保留一个轻量的验收 Sub-Agent,不参与主流程,只在最后做证据链交叉验证:
flowchart TD
A[工具调用] --> B[Agent分析]
B --> C[生成报告]
C --> D[验收Sub-Agent]
D --> E{证据链一致?}
E -->|是| F[输出报告]
E -->|否| G[降级为低置信度报告]
日志结论与监控指标结论是否一致,日志时间线与调用链时间线是否对齐。不一致就输出低置信度报告,说明「证据存在矛盾」,不做强行缝合的结论。
引入真实反馈
幻觉的另一大原因是缺少真实世界的负反馈。Agent 输出什么就是什么,没有人纠正它。
这里引入闭环控制的思路:Agent 是控制器,工具是执行器,工具执行结果是反馈信号。为了对抗 LLM 的不确定性,必须引入物理世界的真实反馈。
例如 Agent 决定回滚某个配置,Harness 代码先不直接执行,先做一次 Dry-run。如果 Dry-run 报错,就把这个真实报错作为反馈喂回 Agent。Agent 撞上物理世界的阻力,就无法继续顺着幻觉往下编,只能被迫调整策略。核心是让 Agent 的决策在真实世界中被验证,避免它在自己的想象里自圆其说。
三条工程准则
总结下来,防幻觉方案的设计可以记住三条:
- 上下文干净 > 提示词花哨:防幻觉的第一步是清洗喂给 Agent 的数据,通过清洗和上下文卸载,让模型始终在清晰、聚焦的环境里推理。
- 约束写进代码:参数校验、格式限制、字数控制,能写成 Linter 的就写成 Linter,别只写在 Prompt 里指望模型自觉。
- 用代码查系统:Agent 引用的任何客观事实——文件路径、日志 ID、错误码——都必须通过代码查询真实系统来验真。
总结
防幻觉和抑制过度输出,不能靠增加 Agent 数量互相监督来解决。正确的做法是:把推理交给 ReAct,把校验交给代码,把喂给模型的上下文洗干净。做到这三点,幻觉就基本压住了。