SkillAgentSearch skills...

Hortator

A Kubernetes operator that lets AI agents spawn AI agents — with guardrails

Install / Use

/learn @hortator-ai/Hortator

README

<p align="center"> <h1 align="center">⚔️ Hortator</h1> <p align="center"><strong>A Kubernetes operator that lets AI agents spawn AI agents.</strong></p> </p> <p align="center"> <a href="#the-problem">The Problem</a> • <a href="#what-hortator-does">What Hortator Does</a> • <a href="#quickstart">Quickstart</a> • <a href="#how-it-works">How It Works</a> • <a href="#guardrails">Guardrails</a> • <a href="#crds">CRDs</a> • <a href="#faq">FAQ</a> • <a href="#roadmap">Roadmap</a> </p> <p align="center"> <a href="https://github.com/hortator-ai/Hortator/actions/workflows/ci.yaml"><img src="https://github.com/hortator-ai/Hortator/actions/workflows/ci.yaml/badge.svg?branch=main" alt="CI"></a> <a href="https://github.com/hortator-ai/Hortator/releases"><img src="https://img.shields.io/github/v/release/hortator-ai/Hortator?style=flat-square&color=blue" alt="Release"></a> <img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License: MIT"> <img src="https://img.shields.io/badge/language-Go-00ADD8?style=flat-square&logo=go&logoColor=white" alt="Go"> <img src="https://img.shields.io/badge/kubernetes-1.28+-326CE5?style=flat-square&logo=kubernetes&logoColor=white" alt="Kubernetes 1.28+"> </p>

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-fetch opens specific egress. shell stays 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
  • BudgetExceeded phase - 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: PendingRunningWaitingCompleted | 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

View on GitHub
GitHub Stars12
CategoryDevelopment
Updated12d ago
Forks1

Languages

Go

Security Score

95/100

Audited on Mar 12, 2026

No findings