All posts
Muhtalip Dede profile photoMuhtalip Dede · Founder of kprompt

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 → cluster

Reads 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:

LayerOwnerJob
Prompt → IntentLLM + schema validationParse what the operator meant
Intent → ActionsGo planner / routersTurn intent into concrete cluster or tool steps
SafetyGo policyRisk score, hard deny, force approval
ApprovalHuman or CIy/N, --approve, or jq gate on JSON
ExecuteGo + kubeconfig / tool CLIsApply 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 approval

Fail 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 y

Score 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.