AI DevOps 演示往往遵循类似的套路:Agent 收到一条信息明确的告警,查询相关指标,发现明显异常,并给出一个看似确定的诊断。整个过程看起来堪称完美,但一旦把它放入真实环境中,它却自信地建议重启一个已经弃用两年的服务。
演示与生产环境之间的差距不是源于智能,而是上下文。
大语言模型(LLM)知道 Kubernetes 是什么,但它不知道你的 payments-api 有一个大家都忽视的不稳定存活探针;不知道结算团队负责管理重试策略;也不知道过去三次所谓的“数据库故障”,实际上是缓存配置错误。这些知识存在于你的运行手册、事故复盘报告、架构文档,以及资深工程师的经验里。
下面将介绍如何将运行手册与 RAG 结合起来,以及我在让 Agent 保持知识可靠的过程中总结的一些经验。
两种知识层
一个 SRE Agent 需要两类完全不同的知识,两者应该分别进行架构设计。
- 实时状态层反应系统当前的状态,包括 Prometheus 指标、容器日志、Kubernetes 事件、部署历史以及告警信息。这些数据实时、客观,并由机器生成。Agent 在调查时,通过权限受限的只读工具获取这些数据。
- 组织知识层则包含监控面板无法呈现的各种信息,包括运行手册、标准操作流程、处理手册、事故复盘报告、架构文档、服务归属信息以及升级规则。这些信息更新较慢,由人工编写,并包含大量需要结合具体情况做出的判断。它能够回答实时状态层无法回答的问题:“这个症状对于该服务来说是正常的吗?”、“我应该通知谁?”、“上次,我们是怎么处理的?”等等。
我第一个版本接入了实时状态层,并将组织知识层的摘要直接放入系统提示中。结果带来了两个问题:①提示变得过于冗长,占用了本来应该留给故障调查的信息;②提示总是过时。原因是运行手册更新后,系统提示并不会随之更新。
用检索替代“硬塞”
解决方案虽然简单但是有效:将组织知识层当作一个检索问题处理。
运行手册、事故复盘、架构文档与服务归属信息都以 Markdown 格式存放在 Git 仓库中。一条流水线负责对文档进行分块和向量化,并将结果加载到向量数据库中。每次合并到主分支时,都会重新生成已更改文件的嵌入内容。这样一来,知识库最多只会比实际情况相差一次合并。
发生故障后,Agent 不会接收整个知识库,而只会检索与当前故障相关的内容。对 checkout-api 的延迟告警会检索出checkout运行手册、提及checkout的事后分析报告,以及描述其依赖关系的架构文档。与批处理流水线或移动网关有关的内容则不会被检索。
调查流程如下:
1. 告警到达:Agent 根据路由元数据确定受影响的服务
2. 知识检索:获取与这些服务相关的运行手册、事故复盘和文档
3. 实时调查:通过只读工具获取指标、日志和部署变更
4. 信息关联:结合检索到的知识解读实时信号
5. 如果证据不足,则继续检索,或交由人工处理
真正体现这套方法价值的是第 4 步。原始遥测数据告诉 Agent:“缓存命中率下降了。”而检索到的事故复盘则提供了关键背景:“在 3 月份遇到过完全相同的情况,原因是 TTL 配置错误,修复方案是 PR #1203。”
两者结合起来才能形成可靠的诊断,单独依靠任何一方都只是猜测。
证明这一点的事件
在测试过程中,我注入了一种 Agent 从未遇到过的故障:一个第三方 API 后端服务的连接重置。实时信号比较模糊:错误率上升、延迟表现不稳定,但近期没有部署变更。
检索层找到了一份之前事故的复盘,其中记录了第三方提供商的每月维护窗口及其特征:整点时开始出现连接重置。Agent 随后检查了时间戳,匹配了该模式,于是响应结果从“可能是网络问题。”变为“这与 6 月事故复盘中记录的供应商维护模式一致;建议采取该文档中记录的缓解措施;无需修改代码。”
这个答案并不是因为模型本身更聪明,而是来自几个月前某人撰写的一份两段式事故复盘在恰当的时机被调取了出来。
Agent 要做的,只是识别出这份文档与实时遥测描述的是同一事件。
保持知识的可靠性
RAG 引入了一种新的故障模式:Agent 能发挥多大作用,很大程度上取决于你提供给它的文档质量。因此,为了让 Agent 保持可靠,我坚持了三条原则。
1. 运行手册与它所描述的服务一起存放在 Git 中。
要更新 Agent 的行为,就需要合并一个 PR,也就意味着必须经过代码审查。团队中那些靠经验积累下来的知识也是如此。过时的运行手册应该在代码审查时就被发现,而不是等到凌晨 3 点发生故障时才暴露出来。
2.事故复盘是语料库中价值最高的文档。
它们记录了其他地方都没有的“症状—原因”对应关系。每次故障解决后,我的Agent都会生成一份结构化的事故复盘——供人查看的版本发布到Confluence,同时将Markdown版本提交到 Git 知识库供Agent使用。每一次事故都会让知识库会不断积累,让下一次调查更加精准。
3.检索到的内容是上下文,而不是指令。
运行手册写着“立即重启服务”,并不意味着 Agent 就会执行这个操作。检索到的文档只用于辅助诊断,而实际操作仍然必须通过同样的权限受限工具、验证钩子和人工审批流程执行。这一点对安全至关重要——文档可能存在错误、已经过时,甚至在最坏的情况下遭到恶意篡改。而知识层没有执行权限,只能提供决策依据。
仍然存在的问题
目前还有三个问题没有完全解决:
1. 检索遗漏
如果故障告警的用词与运行手册中的用词不一致,正确的文档可能根本不会被检索出来。例如,一条关于“连接池耗尽”的告警,可能无法检索到标题为“数据库饱和问题”的运行手册,除非向量嵌入能捕捉到出两种表述之间的语义关联。
现在,我会在运行手册开头直接写明故障症状。这样做有所帮助,但仍然无法彻底解决这个问题。
2.文档冲突
两份相隔两年的运行手册,可能针对同一个问题给出完全相反的缓解措施。如果知识库没有提供额外信息,Agent 无法判断哪一份才是当前有效的。我现在会在每份运行手册的开头加入 last_validated 日期,并让检索层优先选择最近验证过的文档。虽然方法比较粗糙,但至少针对的是一个真实存在的问题。
3.置信度伪装
一份被检索出来的文档,通过引用一个看似权威的文档,让一个原本证据不足的诊断听起来很有说服力。即使运行手册与当前问题只有较弱的相关性。例如“根据运行手册中的记录……”等这样的表述很容易让人信服。
现在,Agent 会明确指出哪些文档影响了它的判断,审核诊断的人可以据此检查这些引用是否真的支持这一结论。
结论
如果你的 AI DevOps Agent 在 Demo 中表现良好,却在生产环境中失效,那么问题可能不在于模型不够好,而在于缺少团队已经积累下来的组织知识。这些知识需要在正确的时机被检索出来,并通过与代码相同的评审流程持续维护其可靠性。
实时遥测告诉 Agent 发生了什么;运行手册和事故复盘则结合你们的历史经验,告诉它这意味着什么。
只有前一种信息的 Agent,本质上只能算一个 Demo。同时掌握实时状态和组织知识的 Agent,才真正能成为 SRE 的得力助手。