AI FaultLab:故障演练 Agent 的设计思路 一个诊断型 Agent 的工程化实践从故障证据到大模型诊断报告最近在做一个后端故障演练和诊断平台里面有一个比较核心的模块把一次故障实验中的指标、Trace、规则诊断结果整理出来再交给大模型生成一份结构化诊断报告。一开始我没有把它做成一个“聊天机器人”因为这类系统真正需要的不是自由问答而是稳定、可控、能解释的诊断流程。后端故障排查本身是有证据链的不能让模型凭感觉猜。所以这个 Agent 的设计重点不是“让模型多聪明”而是先把证据准备好再让模型在证据范围内生成结论。为什么不能直接让大模型诊断最开始如果直接把一句话丢给大模型比如“MQ 堆积了帮我分析一下”它当然也能说出一些看起来合理的答案比如消费者太慢、队列积压、需要扩容消费者、检查死信队列等。但问题是这些回答不一定来自当前系统的真实数据。后端诊断最怕这种情况模型说得很像对的但实际上没有任何指标支撑。比如系统里明明没有消费失败大模型却开始分析死信队列Trace 里没有慢 SQL它却建议先优化数据库。这种回答在面试展示里可能还能糊弄一下但放到工程系统里就不可靠。所以我把诊断链路拆成了几层故障演练 - 指标采集 - Trace 追踪 - 规则诊断 - Evidence Package - LLM 诊断报告 - JSON 校验 - fallback大模型不是第一判断者而是最后的报告生成者。Evidence Package先把证据整理清楚Java 后端会负责收集一次实验的完整上下文包括实验信息、指标列表、Trace 树和规则诊断结果。这些数据会被组装成一个 Evidence Package再发给 Python AI Service。大概结构是这样的{ experiment: {}, metrics: [], traceTree: {}, ruleResult: {} }这里面比较关键的是ruleResult。规则诊断是确定性的比如 MQ 堆积场景会看publishCount、consumeCount、avgConsumeMs、consumerDelayMs这些指标。只要生产数量明显大于消费数量并且消费耗时较高就可以判断存在消息积压风险。规则诊断的好处是稳定、可测试、可解释。它给大模型提供了一个基础结论大模型后续只是在这个基础上把报告组织得更完整而不是重新猜一遍。Python AI Service固定流程不做自由发挥AI Service 没有一上来就引入复杂框架而是先用 FastAPI 做了一个固定工作流build_trace_summary - build_prompt - select_model - call_llm - parse_json - fallback_if_needed这样做的好处是链路很清楚。每一步职责单一出了问题也容易定位。比如模型超时那就是call_llm的问题模型返回的不是合法 JSON那就是parse_json处理如果 API Key 没配置那直接进入 fallback不会影响接口可用性。我不希望这个模块一开始就变成一坨很大的generate_report()方法。因为后续还要接 Runbook RAG、工具调用、模型路由如果现在没有把流程拆干净后面改起来会很痛苦。Prompt 约束只基于证据生成Prompt 里有几个强约束只能基于 Evidence Package 生成诊断 不能编造不存在的指标 不能编造不存在的 Trace 节点 不能输出 Markdown 必须输出严格 JSON 证据不足时要说明证据不足输出结构也固定{ experimentId: , faultType: , faultName: , confidence: 0.0, summary: , phenomenon: [], evidence: [], rootCauses: [], suggestions: [], runbookReferences: [], fallback: false }固定 JSON 很重要。因为 Java 后端要把结果保存到diagnosis_report.ai_report_json前端也要把这些字段展示出来。如果模型返回一段 Markdown页面就没法稳定渲染后续也没法做结构化分析。JSON 解析和 fallback不能让模型拖垮主链路实际接大模型的时候有几个问题很常见模型可能返回 Markdown 代码块json {...}也可能缺字段或者 confidence 给出超过 1 的值。更极端一点模型可能直接输出一段自然语言。 所以 AI Service 里做了一层 JSON Parser。它会先清理代码块再尝试解析 JSON。字段缺失时补默认值confidence 会限制在 0 到 1 之间。数组字段如果不是数组也会被兜底成空数组。 如果解析失败或者模型调用超时就不让接口直接 500而是走 fallback。 fallback 的报告来自规则诊断结果 text AI 诊断服务暂时不可用当前返回基于规则诊断的降级报告。这块看起来不起眼但工程上很关键。AI 服务不能成为主链路的单点故障。哪怕大模型不可用系统至少还能返回一份规则诊断报告。配置设计只把 API Key 放到环境变量一开始配置项都走环境变量比如模型名、base_url、timeout、retry 次数。后来我做了一次简化只有DASHSCOPE_API_KEY从环境变量读取其他配置都放到config.py里作为默认值。原因很简单真正敏感的只有 API Key。模型名、base_url、超时时间这些都是普通运行参数不需要每次都让开发者手动配置。现在配置更清晰dashscope_base_url https://dashscope.aliyuncs.com/compatible-mode/v1 llm_enabled True llm_timeout_seconds 90 llm_max_retries 0 llm_default_model qwen-plus llm_fast_model qwen-turbo llm_reasoning_model qwen-plus llm_long_context_model qwen-plus本地只需要长期配置DASHSCOPE_API_KEY这样既安全也减少了启动成本。ModelRouter不是所有请求都打同一个模型后面我又加了一个简单的 ModelRouter。它不会做复杂调度只根据当前诊断任务的复杂度选择模型。规则大概是ruleResult 缺失或未命中 - fast model Trace 节点较多 - reasoning model evidence 数量较多 - reasoning model metrics 数量较多 - long context model 其他情况 - default model这个设计的目的不是炫技而是给后续扩展留口子。实际系统里不同任务对模型的要求不一样。证据不足的时候用强模型也没有意义因为模型没有足够上下文Trace 很大、指标很多的时候才值得使用能力更强或上下文更长的模型。当前路由结果只打日志不返回给前端。这样对外接口不用变Java 后端和前端也不需要跟着改。为什么暂时没有直接上 LangGraph这个阶段我没有直接引入 LangGraph。不是因为它不好而是当前链路还比较固定证据整理 - prompt 构造 - 模型调用 - JSON 校验 - fallback用普通 Python 函数已经能表达清楚。如果现在直接上复杂框架项目成本会变高调试也更麻烦。不过我在拆分的时候保留了类似工作流节点的结构。后续如果要做多轮工具调用、人工审核、状态恢复、多分支诊断再迁移到 LangGraph 会比较顺。目前还缺什么现在这套链路已经能完成Java 后端组装证据 - Python AI Service 调用百炼大模型 - 生成结构化 JSON 报告 - Java 落库 - 前端展示但它还不是完整的 RAG 诊断系统。目前模型只基于实验证据和规则结果生成报告还没有引入 Runbook。后续应该补一层 Runbook RAG把故障排查手册、处理经验、常见原因和修复步骤检索出来再注入 Prompt。到那个阶段链路会变成Evidence Package - Runbook 检索 - ModelRouter - Prompt Builder - LLM - JSON 校验 - fallback这样模型生成的报告就不只是“根据指标分析”还可以结合项目里的排查手册给出更接近真实运维经验的建议。总结这个 Agent 的核心不是让大模型自由发挥而是把它放在一个受控的诊断流程里。前面用规则诊断保证确定性中间用 Evidence Package 统一证据输入后面用 Prompt 和 JSON Schema 限制输出格式再用 fallback 保证服务可用。模型路由则是在成本、延迟和效果之间做一个简单平衡。这套设计不复杂但比较符合工程落地的思路先保证链路稳定再逐步增强智能能力。现在它已经可以算是一个基础的诊断型 Agent后续接入 Runbook RAG 后才会更接近一个完整的故障诊断助手。