Capstone 06 — DevOps Troubleshooting Agent for Kubernetes
AWS's DevOps Agent went GA, Resolve AI published its K8s playbooks, NeuBird demoed semantic monitoring, and Metoro tied AI SRE to per-service SLOs. They all converged on one shape: an alert webhook fires, an agent reads telemetry, walks a graph of K8s objects, ranks root-cause hypotheses, and posts a Slack brief with approval buttons. Read-only by default, every remediation gated by a human. This capstone builds that agent, scores it on 20 synthetic incidents, and compares it against AWS's Agent on three shared cases.
Learning Objectives
- Design a read-only-by-default tool surface for an SRE agent, with destructive verbs on a separate MCP server behind a Slack approval token.
- Model a Kubernetes cluster as a knowledge graph (ownership, scheduling, observation edges) and walk it outward from an alert to collect telemetry.
- Rank root-cause hypotheses with an evidence score built from recency, specificity, citation count, and graph-path length.
- Log considered versus executed commands, and score the agent on a 20-scenario synthetic incident suite for RCA accuracy and time-to-hypothesis.
Problem
An AI SRE agent is a service that takes an incident alert, investigates the cluster on its own, and hands a human a ranked root-cause hypothesis to approve or reject. Through 2025-2026 that became the standard pitch: agents triage, humans approve remediations. AWS DevOps Agent, Resolve AI, NeuBird, Metoro, and PagerDuty AIOps all ship this shape in production. The agent reads Prometheus metrics, Loki logs, Tempo traces, kube-state-metrics, and a knowledge graph of K8s objects, then produces a hypothesis with telemetry citations in under five minutes. It never runs a destructive command without explicit human approval through Slack.
Most of the hard work here is scoping and safety, not reasoning. The agent needs a read-only-by-default RBAC surface, a hardened MCP tool server, and an audit log of every command it considered next to every command it executed. It has to recognize when it is out of its depth and escalate. And it has to run cheaply enough that an OOM-kill cascade does not turn into a $5k agent bill.
Concept
A K8s knowledge graph is the data structure the agent reasons over. Nodes are K8s objects (Pods, Deployments, Services, Nodes, HPAs, PVCs) plus telemetry sources (Prometheus series, Loki streams, Tempo traces). Edges encode ownership (Pod -> ReplicaSet -> Deployment), scheduling (Pod -> Node), and observation (Pod -> Prometheus series). A kube-state-metrics sync keeps the graph fresh, and it is re-sampled on every alert.
When an alert fires, the agent starts at the affected object and root-causes outward. It walks edges, pulls the relevant telemetry slices (last 15 minutes), and drafts a hypothesis. Hypotheses are ranked by evidence: how many telemetry citations support one, how recent they are, how specific. The top 3 go to Slack with graph-path visualizations and approval buttons for remediation actions.
Remediation is gated. The default actions are all read-only. Destructive ones (scaling down, rolling back, deleting Pods) need Slack approval, and ArgoCD rollback hooks need an auth token the agent never holds. The audit log records every command the agent considered, not only the ones it executed, so a review can catch near-misses.
Architecture
PagerDuty / Alertmanager webhook
|
v
FastAPI receiver
|
v
LangGraph root-cause agent
|
+---- read-only MCP tools ----+
| |
v v
K8s knowledge graph telemetry slices
(Neo4j / kuzu) Prometheus, Loki, Tempo
ownership + scheduling last 15m, scoped
|
v
hypothesis ranking (evidence weight)
|
v
Slack brief + approval buttons
|
v (approved)
ArgoCD rollback hook / PagerDuty escalate
|
v
audit log: considered vs executed, every command
Stack
- Observability sources: Prometheus, Loki, Tempo, kube-state-metrics
- Knowledge graph: Neo4j (managed) or kuzu (embedded) of K8s objects and telemetry edges
- Agent: LangGraph with per-tool allow-list, read-only by default
- Tool transport: FastMCP over StreamableHTTP; separate server for destructive tools behind approval gate
- Models: Claude Sonnet 4.7 for root-cause reasoning, Gemini 2.5 Flash for log summarization
- Remediation: ArgoCD rollback webhook, PagerDuty escalate, Slack approval card
- Audit: append-only structured log (considered, executed, approved, outcome)
- Deployment: K8s deployment with its own narrow RBAC role; separate namespace
Build It
-
Graph ingestion. Sync kube-state-metrics into Neo4j/kuzu every 30s. Nodes: Pod, Deployment, Node, Service, PVC, HPA. Edges: OWNED_BY, SCHEDULED_ON, EXPOSES, MOUNTS, SCALES. Add telemetry overlay edges: OBSERVED_BY (a Pod is observed by a Prometheus series).
-
Alert receiver. A FastAPI endpoint that accepts PagerDuty or Alertmanager webhooks. Extract the affected object(s) and the SLO breach.
-
Read-only tool surface. Wrap kubectl, Prometheus query, Loki logql, and Tempo traceql through FastMCP. Every tool gets a narrow RBAC verb ("get", "list", "describe"). The default server has no "delete", "exec", or "scale".
-
Root-cause agent. LangGraph with three nodes.
samplepulls the last-15-minutes telemetry slice,walkqueries the graph for neighboring objects, andhypothesizedrafts ranked root-cause candidates with telemetry citations. -
Evidence scoring. Each hypothesis gets a weighted score: recency and specificity carry the most weight, then citation count (capped at 5), then the inverse of graph-path length (
main.pyuses 0.35, 0.35, 0.2, 0.1). Return the top 3. -
Slack brief. Post an attachment with the hypothesis, the graph-path visualization (a subgraph image rendered server-side), and approval buttons for at most one remediation action.
-
Remediation gate. Destructive tools (scale down, roll back, delete) live on a second MCP server behind an approval token. The agent can call them only after a human approves the Slack card.
-
Audit log. Append-only JSONL. For every candidate command, record whether it was considered, whether it was executed, and who approved it. Ship it to S3 daily.
-
Synthetic incident suite. Build 20 scenarios: OOMKill cascade, DNS flap, HPA thrash, PVC fill, noisy neighbor, faulty sidecar, bad ConfigMap rollout, certificate rotation, image-pull backoff, and so on. Score the agent on root-cause accuracy and time-to-hypothesis.
Use It
webhook: alert.pagerduty.com -> checkout-api SLO breach, error rate 14%
[graph] affected: Deployment checkout-api (3 Pods, Node ip-10-2-3-4)
[walk] neighbors: ReplicaSet checkout-api-abc, Service checkout-api,
recent rollout 14m ago
[sample] prometheus error_rate 14%, up-trend; loki 500s on /api/v2/pay
[hypo] #1 bad rollout: latest image checkout-api:v2.41 fails /healthz
citations: deploy.yaml (rev 42), prometheus errorRate, loki 500 stack
[slack] [ROLL BACK to v2.40] [ESCALATE] [IGNORE]
(approval required; agent does not roll back unilaterally)
Ship It
outputs/skill-devops-agent.md is the deliverable. Point it at a K8s cluster and an alert source and it produces ranked root-cause hypotheses plus a Slack-gated remediation flow.
| Weight | Criterion | How it is measured |
|---|---|---|
| 25 | RCA accuracy on scenario suite | ≥80% correct root cause across 20 synthetic incidents |
| 20 | Safety | Destructive-action guard never fires without Slack approval in the audit log |
| 20 | Time-to-hypothesis | p50 under 5 minutes from alert to Slack brief |
| 20 | Explainability | Every hypothesis has graph paths and telemetry citations |
| 15 | Integration completeness | PagerDuty, Slack, ArgoCD, Prometheus end-to-end working |
| 100 |
I'd build steps 3, 7, and 8 before the LangGraph agent. A read-only tool server, a second server for destructive tools behind an approval token, and the considered-vs-executed log are what make the agent safe to point at a real cluster. With them in place, a bad hypothesis cannot execute anything on its own, because a human approval sits between it and the cluster. My bet is that the considered-vs-executed log deserves a read before the accuracy number. A high RCA score tells you the hypothesis was right and says nothing about what the agent tried on the way there, and the near-miss audit in Exercise 2 is how you would find out.
Exercises
-
Run your agent on the same three incidents AWS's DevOps Agent is demoed on. Publish the side-by-side and report where your agent diverges.
-
Add a "near-miss" audit that flags any command the agent considered that would have been destructive without approval. Measure the near-miss rate over one week.
-
Swap the hypothesis model from Claude Sonnet 4.7 to a self-hosted Llama 3.3 70B. Measure the RCA accuracy delta and the dollar cost per incident.
-
Build a causal filter that separates correlated telemetry spikes from a true root cause. Train a small classifier on the 20-scenario labels.
-
Add a rollback dry-run: run an ArgoCD rollback against a staging cluster with the same manifest, so the rollback plan is verified on a live cluster before the Slack approval button appears.
Key Terms
| Term | What people say | What it actually means |
|---|---|---|
| K8s knowledge graph | "Cluster graph" | Nodes = K8s objects + telemetry series; edges = ownership, scheduling, observation |
| Read-only-by-default | "Scoped RBAC" | Agent's service account has only get/list/describe verbs; destructive verbs live in a separate server behind approval |
| Audit log | "Considered vs executed" | Append-only record of every candidate command, whether it ran, who approved |
| Hypothesis ranking | "Evidence score" | Weighted sum of recency, specificity, citation count, and inverse graph-path length |
| Slack approval card | "HITL gate" | Interactive Slack message with remediation buttons; agent cannot proceed until a human clicks |
| Telemetry citation | "Evidence pointer" | A Prometheus query, Loki selector, or Tempo trace URL that supports a claim |
| MTTR | "Time to resolution" | Wall-clock from alert fire to SLO recovery |
Further Reading
- AWS DevOps Agent GA (the canonical 2026 reference)
- Resolve AI K8s troubleshooting (the competitor reference)
- NeuBird semantic monitoring (semantic-graph approach)
- Metoro AI SRE (SLO-first production framing)
- kube-state-metrics (the cluster-state source)
- LangGraph (reference agent orchestrator)
- FastMCP (Python MCP server framework)
- ArgoCD rollback (the gated remediation target)
Code
- main.py (python, 230 lines)
- ts/package.json (json, 23 lines)
- ts/README.md (markdown, 50 lines)
- ts/src/agent.ts (typescript, 60 lines)
- ts/src/blocks.ts (typescript, 61 lines)
- ts/src/index.ts (typescript, 176 lines)
- ts/src/server.ts (typescript, 104 lines)
- ts/src/slack_verify.ts (typescript, 43 lines)
- ts/src/types.ts (typescript, 30 lines)
- ts/tests/agent.test.ts (typescript, 40 lines)
- ts/tests/server.test.ts (typescript, 93 lines)
- ts/tests/slack_verify.test.ts (typescript, 82 lines)
- ts/tsconfig.json (json, 22 lines)