Cloud Edition
OttoFlow · Open Source · Kubernetes-native
Deterministic AI workflows for Kubernetes
Collect. Analyze. Publish.
One explicit DAG. One bounded AI step — never the whole loop.
How OttoFlow works
ResourceQuery, CEL expressions, PromQL — deterministic, no LLM involved.
The one Agent step. Sees a computed summary only — never a raw pod spec, never your kubeconfig.
Report, mutation, or API call — gated by matchConditions, back to deterministic.
The Problem
Static runbooks, or a kubeconfig and a prayer
For a decade, automation meant a runbook: anticipate a failure, codify the response, run it on repeat. AI broke that ceiling — and the industry's answer swung to the opposite extreme.
Non-deterministic
Free-form prompts produce inconsistent results — hard to test, debug, or trust at scale.
Unpredictable costs
Stuffing whole tool catalogs into prompts inflates tokens, hallucinations, and bills.
Expanded attack surface
Open-ended agents with broad tool access widen blast radius and break governance.
The industry's response to these walls has swung between two extremes:
The runbook shrugs
Deterministic and reviewable, but it handles only the failure its author anticipated. Twelve restarts, an OOM kill, this morning's rollout — a static pipeline can count them, not weigh them.
The free agent
Hand an LLM a kubeconfig and let it explore. Every run differs — nothing to code-review, nothing to diff when it breaks — and it re-derives facts a single API call already knew.
OttoFlow's answer: judgement is one step in an explicit DAG — not the system itself.
How It Works
A workflow is a DAG. The model sees only what the graph hands it.
Independent steps resolve and run concurrently; the agent step receives a computed summary, never a raw pod spec — what it can see is declared in YAML, in code review, not decided by the model at runtime.
pod-triage sample workflow: two deterministic collectors run in parallel, converge into a single bounded agent step, then publish — gated by matchConditions so a healthy cluster never invokes the LLM at all.Reconciles Workflow/WorkflowRun CRDs, watches cluster events, spawns runner Jobs.
Resolves the DAG, runs independent steps concurrently, retries what fails, enforces expression cost budgets.
Sandboxed service for LLM interpretation only — strict data boundaries, mTLS from the runner.
Highlights
Governed by construction, not by prompt
Declarative
A workflow is a Kubernetes CRD — reviewed, diffed, and versioned like any other YAML.
Deterministic
Explicit dependencies, parallel step batches, configurable retries, per-expression cost budgets.
Scoped data, not a kubeconfig
Agent steps see exactly the fields the workflow declares — never a raw pod spec, never live API access.
Sandboxed & least-privilege
Per-step RBAC, mTLS between controller/runner/agent-executor, scoped MCP tool access per step.
Multi-provider LLM
OpenAI, Anthropic, Gemini, Azure OpenAI, or a local llama.cpp-compatible server — swap with a flag.
Inherits Kyverno's DNA
Same architectural philosophy as the policy engine we created — declarative, reviewable, familiar CEL.
Samples
Five workflows you'll actually run
All under samples/workflows/production/ — 70+ more cover cost, security, and compliance automation.
| Workflow | What it does |
|---|---|
| cluster-overview | Pure-CEL cluster snapshot — pod phases, per-namespace CPU/memory. No LLM, runs anywhere. |
| pod-triage | CEL extracts per-pod failure signals; the LLM picks the single highest-priority pod and next action. |
| resource-hygiene | Detects 14 categories of unused or stale resources; LLM writes the cleanup report. |
| cost-analyzer | Right-sizing from resource specs plus Prometheus P95 usage, per-workload $ savings. |
| workload-troubleshooter | One failing pod: events + logs → LLM root-cause. In-cluster only. |
Browse all samples on GitHub →
# pure-CEL, no LLM, no cluster changes
ottoflow run https://raw.githubusercontent.com/nirmata/ottoflow/main/samples/workflows/production/cluster-overview.yaml
# adds one bounded agent step
GEMINI_API_KEY=AIza... \
ottoflow run -f .../samples/workflows/production/pod-triage.yaml
Install
CLI first, cluster when you're ready
brew install nirmata/tap/ottoflow
# runs in-process against your kubecontext
# read-only -- no controller, no CRDs, nothing to clean up
ottoflow run cluster-overview.yaml
helm install ottoflow oci://ghcr.io/nirmata/ottoflow \
--namespace ottoflow --create-namespace
kubectl apply -f samples/workflows/production/cluster-overview.yaml
ottoflow run cluster-overview -n ottoflow
The Full Stack
Built on the architecture Kyverno proved
OttoFlow shares its governance primitives — per-step RBAC, admission-style webhooks, the same CEL — with the policy engine we created. Declarative and reviewable, all the way down.
Where It Fits
OttoFlow occupies a new seat
Argo runs deterministic jobs with no agent primitives. kagent runs agents with no deterministic DAG. OttoFlow is both at once.
Excellent for CI and data pipelines. No agentic or LLM primitives — every step is a container.
Strong multi-agent runtime from Solo.io. Agents are autonomous loops; tools are called through the LLM.
Deterministic DAGs with scoped agent steps and direct MCP tool calls — the best of both worlds.
Give judgement a boundary.
Run a sample against your own kubecontext in under a minute — no controller, nothing to install, nothing to undo.
