Building AI SRE in Public #2: Intent Compiler
Kubernetes deserves a compiler, not a chatbot. How kprompt turns natural language into Intent → Actions → PlanResult, why Go owns planning and safety, and why the IR must stay reviewable for AI SRE.
This is episode 2 of Building AI SRE in Public. Episode 1 argued for the category. This episode is the technical heart of the wedge: an intent compiler — not a chat REPL that happens to call kubectl.
Compilers emit artifacts; chatbots emit turns
A chatbot optimizes for conversation continuity. A compiler optimizes for an intermediate representation (IR) you can refuse. In kprompt the IR is not “whatever the model said last.” It is a pipeline of typed stages ending in PlanResult — something a human, a jq filter, or a CI job can gate before the apiserver sees a mutate.
Conceptual pipeline (shipped shape)
prompt
→ Intent (structured: kind, target, params)
→ Actions[] (ordered ops + optional manifests/diffs)
→ Safety (risk + hard denies)
→ PlanResult (printable + JSON)
→ Approve? → Executor → clusterReads can short-circuit (list, get, logs, explain) without a mutate approval. Mutations always materialize the plan first. That split is deliberate: investigation should be fast; change should be conscious.
What the LLM is allowed to own
The model is good at messy language → structured intent. It is a bad place to put irrevocable policy. So the boundary is sharp:
| Layer | Owner | Job |
|---|---|---|
| Prompt → Intent | LLM + schema validation | Parse what the operator meant |
| Intent → Actions | Go planner / routers | Turn intent into concrete cluster or tool steps |
| Safety | Go policy | Risk score, hard deny, force approval |
| Approval | Human or CI | y/N, --approve, or jq gate on JSON |
| Execute | Go + kubeconfig / tool CLIs | Apply only what was approved |
If the model hallucinates a wipe, the safety layer should still deny. If the model proposes a scale, the plan should still show namespace, resource, and risk before apply. Trust the typed stages; distrust free prose as a control plane.
IR sketch: Intent, Action, PlanResult
Exact Go structs evolve in the product repo. The conceptual types stay stable enough to teach:
IR shapes (conceptual)
Intent
Kind, Target, Params, Confidence
Action
Op, Object (GVK/name/ns), Manifest?, Diff?
PlanResult
Intent, Actions[], Risk, Summary,
RequiresApproval, Denied?, Applied?PlanResult is the public artifact: terminal summary for humans, JSON for pipelines. Secrets and raw kubeconfig never belong in history or CI logs. Episode 3 will go deeper on the schema; today the point is that AI SRE features (investigate, why, blast radius) must eventually land as richer fields on the same artifact — not as a second chat product.
One compiler, many backends
A compiler that only scales Deployments is a toy. The payoff is one approval contract across day-2 surfaces: Kubernetes API, Helm, Prometheus explains, OTel walks, Tekton/KEDA plans, GitOps sync prompts, Crossplane claims (high risk). The LLM proposes; routers and planners emit Actions against tools you already run. Multi-tool chains still collapse to one aggregate plan and one approve for mutating steps.
Different backends, same gate
kprompt "scale api to 3" -n staging
kprompt "install redis" -n cache
kprompt "why is my api slow?" -n production
kprompt "optimize my cluster"
# Mutating follow-ups still require approvalFail closed by default
- Unknown or wipe-class intents → deny before a useful apply path
- High-risk mutations → approval required even with automation flags later
- Missing kubeauth / LLM key → clear doctor-style errors, not silent guess
- Multi-context: no “one --approve mutates the fleet”
Fail closed is how a compiler earns the right to grow into AI SRE. Auto-remediation without an IR you can refuse is how AIOps burned trust.
What this episode ships vs explores
- Shipped: Intent → plan → safety → approve → apply; JSON PlanResult; multi-tool routes
- Building: richer investigate/why trees and blast-radius fields on the same IR
- Exploring: knowledge/ADR context feeding the compiler — still not unsupervised mutate
How to pressure-test the compiler
Thirty-minute drill
brew install kprompt/tap/kprompt
export KPROMPT_GEMINI_API_KEY="..."
kprompt "delete all pods" -n staging # expect deny / hard stop
kprompt "scale api to 0" -n staging -o json | jq .risk
kprompt "scale api to 2" -n staging # read plan → n or yScore the artifact, not the banter. If a competing tool cannot show a refuse-able plan, it is a different product — even if both accept English.
Next
Episode 3 is PlanResult — the IR as a CI citizen: why one typed document serves humans and pipelines, how blastRadius and verify attach, and what never belongs in the artifact. Read it next.
Related posts
Building AI SRE in Public #4: Safety Engine
Policy is code, not LLM vibes. How kprompt’s safety engine hard-denies wipe-class intents, scores risk, forces approval, and why fail-closed is the load-bearing wall of AI SRE.
Read articleBuilding AI SRE in Public #3: PlanResult
PlanResult is the IR of AI SRE: one typed document for humans and CI. Why JSON, what applied means vs verify, how blastRadius attaches, what never gets stored, and how investigate/why must extend the same artifact.
Read articleBuilding AI SRE in Public #1: Why AI SRE
AI kubectl is not enough. Production needs investigate, why, blast radius, and verify — still behind an approval boundary. Why the AI SRE category exists, what failed in classic AIOps, and what we ship first.
Read article