HolmesGPT专业评测:架构原理、Skills机制与SRE智能体
前记
前段时间,团队里在持续跟进故障根因分析智能体的方向,正好有同事推荐了一个开源 SRE Agent——HolmesGPT。起初只是粗略看了几眼,知道它用多轮 ReAct 的思路做根因分析,但具体实现一直没细抠。趁着周末沉下心把源码和文档翻了个遍,就有了这篇梳理。
本文基于 HolmesGPT 源码分析、官方文档(holmesgpt.dev/0.28.0)以及行业调研报告,从架构设计、核心机制到关键工程决策做了系统拆解,希望对正在探索运维智能体方向的同学有所启发。
一、HolmesGPT项目定位与背景
HolmesGPT 是 Robusta 开源的项目,2025 年 10 月进入 CNCF Sandbox,官方定位是 “The CNCF SRE Agent”——专注生产事故调查、根因分析与云原生故障处理的自治智能体,不是那种一问一答的 AI 工具。
在运维智能体的谱系里,SRE Agent 的核心命题是服务可用性,典型的工作流是:收到告警 → 自动调查 → 定位根因 → 给出修复建议。根因分析(RCA)是它的看家本领,但 RCA 不只有 SRE 场景才需要——NetOps、DBOps、SecOps 同样会用到,只不过分析对象不同。市面上同类产品不少:k8sGPT(偏静态扫描)、Datadog Bits AI、Dynatrace Da vis AI、PagerDuty Copilot 等等,独立开源产品灵活度高,平台内置产品数据集成更深。
一句话概括 HolmesGPT 的核心能力:把监控、日志、追踪、Kubernetes 资源状态、云 API、知识库与工单系统串成一条可执行的调查链路。从版本演进来看,0.26.0 引入的 Skills 扩展模型是个分水岭——项目从早期 “runbook + catalog.json” 的旧形态,正式演化为 “技能目录 + 工具调用 + 审批/审计” 的新体系。
二、整体架构:五个清晰层次
通过阅读源码(https://github.com/HolmesGPT/holmesgpt),HolmesGPT 的架构可以划分为五个层次,各层职责边界非常清晰:
┌──────────────────────────────────────────────────────┐
│ 入口层(Entry Points) │
│ server.py (FastAPI HTTP) holmes_cli.py (CLI) │
├──────────────────────────────────────────────────────┤
│ 编排层(Orchestration) │
│ Config → ToolCallingLLM → conversations.py │
├──────────────────────────────────────────────────────┤
│ 核心引擎(Core Engine) │
│ LLM ←→ ToolExecutor ←→ ToolsetManager │
├──────────────────────────────────────────────────────┤
│ 插件系统(Plugin System) │
│ Toolsets(50+) | Sources | Destinations │
│ Skills | MCP | Transformers │
├──────────────────────────────────────────────────────┤
│ 基础设施(Infrastructure) │
│ Context Window 管理 | OAuth | Safeguards │
└──────────────────────────────────────────────────────┘
入口层提供两种接入方式:server.py 基于 FastAPI 暴露 HTTP API(支持 SSE 流式输出),holmes_cli.py 提供命令行交互。两者共用同一套核心引擎,没有独立的逻辑分支。
编排层的核心是 ToolCallingLLM 类,实现 Agentic Loop 主控逻辑。
插件系统是可扩展性核心,涵盖 50+ 数据源的 Toolset、Source/Destination 插件接口、Skills 知识目录和 MCP 协议适配层。
基础设施层解决三个生产级问题:超长调查中的 Context Window 管理、工具调用安全护栏、OAuth 多租户认证。
三、Agentic Loop:核心调查机制
3.1 循环结构
ToolCallingLLM 是整个系统最核心的类,其 call_stream() 方法实现了完整的 Agentic Loop:
def call_stream(self, msgs, max_steps=10, ...):
while num_llm_calls < max_steps:
compact_if_necessary(msgs) # 上下文压缩
response = self.llm.completion(msgs, tools=self._get_tools())
if response.has_tool_calls:
results = execute_tools_concurrently(response.tool_calls)
msgs = append_tool_results(msgs, results)
else:
yield ANSWER_END event
return
num_llm_calls += 1
call() 是 call_stream() 的同步包装器,这个设计让 CLI 终端实时渲染和 HTTP SSE 推流共用同一套引擎。
3.2 关键工程设计
防死循环护栏(safeguards.py):检测到相同工具 + 相同参数被调用时,直接返回错误强制 LLM 换方向——五行代码解决了工程实践中的一个常见痛点。
上下文压缩:单工具结果超大时写入磁盘(spill to disk);整体 Context 超限时调用 LLM 对历史消息做摘要压缩(compact_if_necessary)。两级策略保证长调查不中断。
任务外部记忆(TodoWriteTool):让 LLM 维护一个结构化任务列表作为外部工作记忆,每轮更新状态(pending/in_progress/completed/failed)。这个设计解决了一个经典问题:长调查中 LLM 容易“忘记”未验证的假设,同时提供了可审计的调查轨迹。
人工审批门控:Toolset 中可配置 approval_required_tools,LLM 调用写操作前暂停等待人工确认,实现“读操作自动 → 写操作审批”的安全分级。
四、YAML Toolset:声明式工具扩展体系
YAML Toolset 的核心思想是把 Shell 命令或 API 调用通过 YAML 声明包装成 LLM 可以调用的函数,无需编写任何 Python 代码。以 kubernetes.yaml 为例:
tools:
- name: "kubernetes_jq_query"
description: "Use kubectl to get json and filter with jq."
parameters:
kind: {type: string, required: true}
jq_expr: {type: string, required: true}
script: |
kubectl get {{ kind }} -o json | jq '{{ jq_expr }}'
transformers:
- type: llm_summarize
max_tokens: 2000
两类变量语法区分了 LLM 可见参数与系统配置:{{ variable }} 是 Jinja2 模板变量,由 LLM 填入;${VARIABLE} 是环境变量,LLM 不可见,用于存放 API Key、内网地址等敏感信息。
YAMLTool 类通过 get_openai_format() 将工具元数据转换为标准 OpenAI function calling 格式。LLM 完全不知道背后是 YAML 还是 Python,只看到标准的 function schema——这正是 YAML Toolset 与 MCP Toolset 能无缝共存的根本原因。YAML 还支持 Transformer 链,内置的 LLMSummarize 在工具输出超过阈值时用快速模型摘要,减少主调查 LLM 的 token 消耗。
五、Skills 系统:把 SOP 变成 Agent 能力
5.1 设计哲学
Skills 系统最重要的设计哲学只有一句话,来自源码 skills_fetcher.py 的注释:
Skills 不是自动化脚本,而是给 LLM 读的 SOP。LLM 读完 Skill 后,自行决定调哪些工具来执行每一个步骤。同一个 Skill 在不同环境、不同工具可用性下,会调用不同的工具,但遵循同一套诊断逻辑。
5.2 SKILL.md 文件格式
每个 Skill 是一个 SKILL.md 文件,格式为 YAML frontmatter + Markdown 正文,放入目录后自动扫描加载,零注册、零代码:
---
name: redis-memory-pressure
description: 诊断 Redis 内存压力、OOM 驱逐、maxmemory 配置问题
---
## Workflow
1. 执行 redis-cli INFO memory,采集 used_memory、maxmemory、mem_fragmentation_ratio
2. 执行 redis-cli INFO stats,查看 evicted_keys 累计值
3. 检查 maxmemory-policy 配置
4. 若 evicted_keys > 0,查询最近 1 小时 key 数量趋势
## Synthesize Findings
- used_memory > maxmemory * 0.9 且 evicted_keys 增长 → 确认内存压力
- mem_fragmentation_ratio > 1.5 → 内存碎片,建议执行 MEMORY PURGE
## Recommended Remediation
立即:CONFIG SET maxmemory 调整上限;永久:评估 key 增长趋势制定扩容策略
内置 Skills 覆盖了常见的 Kubernetes 故障类型,例如:
Pod 反复重启、CrashLoopBackOff
5.3 加载机制与 LLM 交互流程
skill_loader.py 实现三级来源合并,优先级从高到低:用户自定义目录 → 内置 Skills → 远程 Skills(URL 动态拉取)。用户自定义的同名 Skill 会覆盖内置版本,允许团队针对自身环境深度定制。
Skills 与 LLM 的交互分为五步:
第一步:目录注入 System Prompt。启动时扫描所有 Skill,只提取 name + description(每条约 20 token)注入 System Prompt,Skill 正文按需获取,节省 90% token:
A vailable Skills:
* redis-memory-pressure | 诊断 Redis 内存压力、OOM 驱逐、maxmemory 配置问题
* pod-crashloop | 诊断 Kubernetes Pod 反复重启的根本原因
* high-memory-usage | 调查容器内存使用率持续升高的问题
* node-not-ready | 调查 K8s Node 进入 NotReady 状态的原因
第二步:LLM 语义匹配,调用 fetch_skill。LLM 将用户问题与目录中每条 description 做语义比对。匹配时发起 fetch_skill("redis-memory-pressure") 工具调用。这是语义理解而非关键词匹配,“Redis 内存不够了”也能命中正确的 Skill。
第三步:SkillsFetcher 返回带指引的 Skill 正文。工具结果以 role: tool 消息形式注入 messages,包裹在 标签中,并附加明确指示:
[Skill 完整内容]
IMPORTANT: the above are DIRECTIONS not ACTUAL RESULTS.
You must follow them by CALLING TOOLS YOURSELF.
第四步:LLM 按 Skill 步骤调用真实工具。Skill 内容约束了搜索空间——LLM 不会漫无目的地尝试工具,而是按照 Workflow 顺序有条不紊地执行。官方案例表明,有 Skill 约束时无效工具调用从 16 次降到 2 次。
第五步:输出带执行状态的标准化报告:
我使用了技能【redis-memory-pressure】进行排查:
1. ✅ INFO memory — used_memory 3.62G / maxmemory 3.81G,使用率 95%
2. ✅ INFO stats — evicted_keys 累计 18,432 个,仍在增加
3. ✅ maxmemory-policy — allkeys-lru
4. ✅ key 数量趋势 — 过去 1 小时增长 18%(210 万 → 248 万)
5. ❌ 无法查询慢查询日志 — Redis Slowlog 工具集未启用
根本原因:key 数量异常增长超出 maxmemory 上限,触发 LRU 驱逐...
❌ 步骤不仅是诊断记录,更是工具链缺失的反馈,驱动持续完善 Agent 覆盖面。
六、实战演示与典型场景
6.1 CLI 交互模式:多轮深度排查
官方交互模式文档展示了一个典型的多轮调查场景——payment-service 不响应请求:
holmes ask "why is the payment-service in production namespace not responding?"
Agent 依次执行:kubectl_find_resource(定位 deployment)→ kubectl_describe(查看状态)→ kubectl_get_by_kind(列出 Pod)→ fetch_pod_logs(拉取日志)→ kubectl_events(查看事件),初步判断是数据库连接失败。用户追问后,Agent 继续调查 PVC Pending 原因,最终定位到 StorageClass 不存在:
Root Cause: The PVC is pending because the requested StorageClass "fast-ssd" not found.
A vailable StorageClasses: gp2 (default), gp3, io1, standard
整个调查过程中,工程师可以随时用 /run 命令注入 Agent 无法直接访问的数据(如 SSH 到宿主机、查询 ALB 健康状态),Agent 将这些数据融入分析上下文继续推理。
6.2 AlertManager 告警自动调查
当 KubePodCrashLooping 告警触发后,通过以下命令一键调查:
holmes investigate alertmanager --alertmanager-url http://localhost:9093 --alertmanager-alertname "KubePodCrashLooping"
也可以不加过滤,让 HolmesGPT 批量调查所有活跃告警,按严重程度输出结构化的 RCA 报告,并支持通过 --alertmanager-label "severity=critical" 精确过滤。
6.3 CI/CD 流水线集成
在 GitHub Actions 中,当 Kubernetes 部署超时失败时,自动触发 HolmesGPT 调查并将结果发送到 Slack:
- name: Deploy & Investigate on Failure
if: failure()
run: |
holmes ask "The deployment failed. Analyze why pods are not becoming ready.
Focus on: image pulls, resource limits, probes, configuration." --no-interactive --destination slack --slack-channel "#deploy-alerts"
6.4 Operator 定时巡检
Operator 模式将 Agent 作为 Kubernetes Controller 持续运行,支持定时巡检配置:
scheduledHealthChecks:
- name: daily-cluster-health
schedule: "0 9 * * *"
prompt: "扫描集群中所有异常 Pod,分析根因并生成日报"
destinations: [slack, jira]
集群中发现异常时,Operator 自动生成结构化报告并推送到指定渠道,无需任何人工干预。
七、SRE Agent 评测体系
7.1 评测的特殊难点
SRE Agent 的评测有几个独特挑战,与一般 LLM 应用不同:
- 没有唯一正确答案:同一故障可以从日志入手,也可以从指标入手,两条路径都能到达正确结论
- 过程比结果更重要:30 次工具调用找到答案 vs 5 次找到,评分应截然不同
- 环境依赖重:离开真实 Kubernetes 集群,评测会严重失真
- 故障难以复现:生产事故往往一次性,无法重放调查环境
7.2 评测维度设计
一套完整的评测体系需要覆盖:
| 维度 | 关键指标 |
|---|---|
| 诊断准确性 | Top-1/Top-3 根因准确率、影响范围判断、修复建议可执行性 |
| 调查过程质量 | 工具调用总次数、无效调用占比、重复调用率、并行执行率 |
| 场景覆盖深度 | L1(单组件故障)→ L5(间歇性隐性故障) |
| 安全性 | 高危操作是否正确拦截,是否因异常数据产生幻觉 |
7.3 HolmesGPT 的 pytest 评测框架
HolmesGPT 的评测体系是上述理论的工程实现,值得直接参考。每个测试场景是一个独立目录,核心是 test_case.yaml:
user_prompt: "What is the issue with payment-processing-worker?"
expected_output:
- The `DEPLOY_ENV` environment variable is undefined or missing
before_test: |
kubectl create namespace app-09
# 部署一个故意缺少 DEPLOY_ENV 的 Pod,等待进入 CrashLoopBackOff
kubectl wait --for=jsonpath=...=CrashLoopBackOff pod ...
after_test: |
kubectl delete namespace app-09
tags: [easy, kubernetes, regression]
执行流程:before_test 向真实 K8s 集群注入已知故障 → HolmesGPT 调用真实工具调查 → 裁判 LLM 检查输出是否符合 expected_output → after_test 清理现场。这正是“故障注入测试环境 + LLM-as-Judge”的工程实现。
评分机制:使用 autoevals 库的 LLMClassifier,用独立的 CLASSIFIER_MODEL 作为裁判。expected_output 是语义要求列表,裁判判断 Agent 的回答是否覆盖了这些语义,而非逐字匹配。expected_output 对 Agent 永远不可见,只有裁判 LLM 能看到——这是防止 LLM 凭领域知识猜答案的反作弊设计。
过程指标采集:评测框架同步追踪 tool_call_count、num_llm_calls、holmes_duration、total_tokens、num_compactions 等指标,全部上传到 Braintrust 平台做跨版本、跨模型横向对比。
分层测试管理:通过 tags 字段管理测试集分层(easy、regression 等),CI 只跑核心回归集,全量测试按需触发。
7.4 评测数据集构建策略
| 方案 | 能评测的对象 | 成本 | 推荐用途 |
|---|---|---|---|
| 历史事故复盘集 | 结论准确性 | 高(人工标注) | 黄金基准,季度对比 |
| 故障注入测试环境 | 过程质量 + 准确性 | 高(专用集群) | 持续回归测试 |
| Mock 工具回放 | 过程质量 + 准确性 | 中(前期积累录制) | 日常自动化评测 |
HolmesGPT 采用的正是故障注入方案。三种方案可以叠加:复盘集作为黄金基准,注入环境做持续回归,Mock 回放支撑日常自动化。建议从 L1-L2 难度的高质量样本起步,20-30 个精标案例的价值远高于 200 个粗糙样本。
八、结语
HolmesGPT 对 SRE 智能体建设的最大参考价值,在于它提供了一套经过生产验证的设计决策集合:Agentic Loop 的工程化实现、Skills 把人类知识变成 Agent 能力的标准化路径、YAML 工具集的声明式扩展体系,以及一整套防止 Agent 失控的工程护栏。
在交互方式上,HolmesGPT 将其抽象为 Source(输入触发)→ 调查引擎 → Destination(输出回写)三层,支持 CLI、告警驱动、ChatOps、Operator 巡检、CI/CD 集成、API 嵌入等多种模式,核心引擎无需改动,只需替换插件。对于从零开始建设的团队,建议按顺序落地:先 CLI 验证能力 → 接告警驱动跑通主流程 → 建 ChatOps 提升协作可见性 → 嵌入运维平台。
HolmesGPT 更适合云原生环境下开箱即用的场景。实际生产环境中,面对复杂异构环境(Kubernetes 只是其中一小部分),直接使用可能受限,但其设计理念仍然值得借鉴。
研究过程中发现一个值得注意的设计思路:很多简单的 API 调用或支持 CLI 方式的工具(kubectl、PromQL 查询等),直接通过智能体进程内的 Bash 方式执行就能解决,不一定需要封装成 MCP Server,开发成本可以大幅降低。这个思路对于快速搭建原型和工具链扩展很有价值。
故障根因分析智能体确实是一块不好啃的骨头——不论是智能体的产品设计、与真实运维环境的适配,还是全链路可观测数据的接入,都存在相当大的挑战。但办法总比困难多,HolmesGPT 的设计思路给出了具体的方向性指引,希望对正在做类似方向的同学有所帮助。
在运维领域,一个值得推动的愿景是:让一线运维同学从繁重的告警处理和故障排查中解放出来,把更多时间投入到有创造性价值的事情上——不是被 AI 替代,而是借助 AI 拓展自身的价值边界。
自勉,共勉。
参考资料:HolmesGPT 源码、官方文档(holmesgpt.dev/0.28.0)、CNCF 博客(2026-04)、ChatGPT 调研报告《HolmesGPT 在运维领域的使用情况与最佳实践调研报告》





