Hortator
A Kubernetes operator that lets AI agents spawn AI agents — with guardrails
Install / Use
/learn @hortator-ai/HortatorREADME
The Problem
AI agents today run in one of two modes: sandboxed toys (single container, no real autonomy) or terrifying cowboys (SSH into prod, spawn Docker containers, curl | bash whatever they want).
There's no middle ground. No infrastructure that says: "Yes, you can spawn sub-agents, decompose problems, and work autonomously - but within boundaries I define."
Hortator is that middle ground.
What Hortator Does
Hortator is a Kubernetes operator that gives AI agents the ability to create other AI agents at runtime - forming dynamic task hierarchies to solve complex problems. Each agent runs in its own Pod with its own context, budget, and security boundary.
You define the guardrails. Agents do the thinking.
┌───────────┐
│ Tribune │ "Redesign the auth system"
└─────┬─────┘
│
┌─────────┼─────────┐
│ │ │
┌───▼───┐ ┌───▼───┐ ┌───▼───┐
│Centur.│ │Centur.│ │Centur.│ "Handle backend" / "Handle frontend" / "Handle tests"
└───┬───┘ └───┬───┘ └───┬───┘
│ │ │
┌──▼──┐ ┌──▼──┐ ┌──▼──┐
│ Leg.│ │ Leg.│ │ Leg.│ "Fix session.ts:47" / "Update login form" / ...
└─────┘ └─────┘ └─────┘
The task tree isn't defined upfront - it emerges from the work. A Tribune decides it needs three Centurions. A Centurion decides it needs five Legionaries. Hortator manages the lifecycle, result passing, and cleanup.
Key idea: Agents never see YAML. They use a CLI (hortator spawn, hortator result) inside their Pod. The operator handles everything else.
What makes this different from [Argo / Tekton / CrewAI / LangGraph]?
- Argo/Tekton define static DAGs upfront. Hortator task trees are dynamic - agents decide the structure at runtime.
- CrewAI/LangGraph are Python frameworks that run agents in-process. Hortator gives each agent its own Pod, PVC, network policy, and budget. They're complementary - you can run CrewAI inside a Hortator agent.
- Raw Kubernetes Jobs are the primitive Hortator builds on. The value is everything around the Job: result brokering between parent/child, PVC lifecycle, budget enforcement, stuck detection, PII redaction, security policies.
Quickstart
# Install the operator
helm install hortator oci://ghcr.io/hortator-ai/hortator/charts/hortator \
--namespace hortator-system --create-namespace \
--set models.default.endpoint=https://api.anthropic.com/v1 \
--set models.default.name=claude-sonnet-4-20250514
# Create a namespace and API key secret
kubectl create namespace hortator-demo
kubectl create secret generic anthropic-api-key \
--namespace hortator-demo \
--from-literal=api-key=sk-ant-...
# Run your first task
kubectl apply -f examples/quickstart/hello-world.yaml
# Watch it work
kubectl get agenttasks -n hortator-demo -w
That's it. The operator creates a Pod, injects your prompt, runs the agent, collects the result, and updates the CRD status.
For multi-tier examples (Tribune → Centurion → Legionary chains), see examples/advanced/.
How It Works
The Roman Hierarchy
Named after the officer on Roman galleys who commanded the rowers - Hortator orchestrates agents without doing the thinking.
Three tiers, inspired by the Roman military:
| Tier | Role | Think of it as... | |------|------|-------------------| | Tribune | Strategic leadership. Decomposes problems, coordinates Centurions. | The architect | | Centurion | Mid-level coordination. Delegates to Legionaries, aggregates results. | The tech lead | | Legionary | Executes a single focused task. Fast, cheap, disposable. | The developer |
Tiers determine defaults (model, storage, timeout) but aren't rigid - a Legionary can use GPT-4 if you want. They're conventions, not constraints.
Agent Communication
Agents don't talk to each other. The operator is the message broker:
Legionary writes /outbox/result.json
→ Operator detects completion
→ Copies result to parent Centurion's /inbox/
→ Centurion wakes up with new context
→ Repeat until Tribune has all results
Each agent Pod gets four mount points:
| Path | Purpose |
|------|---------|
| /inbox/ | Task definition + results from children |
| /outbox/ | Results + artifacts for parent |
| /memory/ | Persistent state across agent "turns" |
| /workspace/ | Scratch space |
Agent Reincarnation
When an agent's context window fills up, it doesn't crash - it checkpoints its state to /memory/, gets killed, and respawns with a fresh context window and its checkpoint. The agent picks up where it left off. We call this reincarnation.
Install the CLI
The CLI is pre-installed in all agent container images. For local use or custom runtimes:
# Download a binary (macOS / Linux)
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/')
curl -sSL "https://github.com/hortator-ai/Hortator/releases/latest/download/hortator_${OS}_${ARCH}.tar.gz" | tar xz
sudo mv hortator /usr/local/bin/
# Or via Go
go install github.com/hortator-ai/Hortator/cmd/hortator@latest
The CLI
Agents interact with Hortator through a CLI, not YAML:
# Spawn a sub-agent and wait for the result
hortator spawn --prompt "Fix the login bug" --role backend-dev --wait
# Spawn with specific capabilities
hortator spawn --prompt "Scrape the API docs" --cap shell,web-fetch --tier legionary
# Check on your children
hortator tree my-task # Visualize task hierarchy
hortator status child-task-id # Check phase
hortator result child-task-id # Get output
# Budget awareness
hortator budget-remaining # "You have 42,000 tokens left"
# Self-report (feeds into stuck detection)
hortator progress --status "Analyzing auth module, found 3 issues"
Guardrails
The whole point of Hortator is autonomous agents with boundaries. Here's what's built in:
🔒 Security
- Pod isolation - each agent is its own Pod with its own ServiceAccount
- NetworkPolicies - auto-generated from declared capabilities.
web-fetchopens specific egress.shellstays isolated. No capability = no network. - Capability inheritance - children cannot escalate beyond their parent. A Legionary spawned by a Centurion with
[shell]cannot request[shell, web-fetch]. - Per-capability RBAC - agents get minimal ServiceAccount permissions based on their declared capabilities
💰 Budget
- Token and cost caps - per-task and per-hierarchy (shared budget across an entire task tree)
- LiteLLM price map - automatic cost tracking across providers
BudgetExceededphase - tasks stop cleanly when limits are hit, not mid-stream
🛡️ PII Redaction
- Presidio sidecar - scans agent input and output for PII, secrets, API keys
- Input redaction - prompts are scrubbed before reaching the LLM (configurable)
- Output redaction - results are scrubbed before being passed to parent agents
🏥 Health Monitoring
- Behavioral stuck detection - not just "is the process alive" but "is the agent making progress?" Monitors tool diversity, prompt repetition, state staleness.
- Auto-kill or escalate - stuck agents can be terminated or flagged for human review
📊 Observability
- Prometheus metrics -
hortator_tasks_total,hortator_tasks_active,hortator_task_duration_seconds - OpenTelemetry traces - task hierarchy maps directly to distributed traces. Open in Jaeger/Tempo and see the full agent tree.
CRDs
AgentTask
The core resource. One task = one agent = one Pod.
apiVersion: core.hortator.ai/v1alpha1
kind: AgentTask
metadata:
name: fix-auth-bug
namespace: ai-team
spec:
prompt: "Fix the session cookie not being set on login response"
tier: legionary
parentTaskId: feature-auth-refactor
timeout: 600
capabilities: [shell, web-fetch]
budget:
maxTokens: 100000
maxCostUsd: "0.50"
model:
name: claude-sonnet
env:
- name: ANTHROPIC_API_KEY
valueFrom:
secretKeyRef:
name: llm-keys
key: anthropic
Status phases: Pending → Running → Waiting → Completed | Failed | BudgetExceeded | TimedOut | Cancelled
AgentRole / ClusterAgentRole
Behavioral archetypes. Define what an agent is - its rules, anti-patterns, and default tools.
apiVersion: core.hortator.ai/v1alpha1
kind: ClusterAgentRole
metadata:
name: backend-dev
spec:
description: "Backend developer with TDD focus"
rules:
- "Always write tests before implementation"
- "Security best practices (input validation, auth checks)"
antiPatterns:
- "Never use `
Related Skills
node-connect
333.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
xurl
333.3kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
frontend-design
82.0kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
333.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
