PRE-ALPHA — v0.2.1 PUBLISHED ON PYPI

Durable execution for AI agents that survive the real world.

Kestrion is an open-source Python framework for AI agents built around one idea: every step is recorded as an immutable event. That now includes multi-role approvals, approval deadlines, parallel tool calls, sub-agents, handoff, and MCP tools on top of crash recovery.

kubectl_agent.py — actual run, unedited
# An agent proposes scaling up a deployment, then needs approval
# before it's allowed to touch the cluster.
$ python3 examples/kubectl_agent.py
status=waiting_on_human current_node=apply_change
pending approval: {'tool': 'apply_manifest', 'kwargs': {'yaml': 'replicas: 3'}}
# The run is now parked. No thread is blocked, nothing is held
# in memory. A second, independent process resumes it later —
# this is the actual crash-recovery test, not a simulation.
$ engine.resume(run_id) # from a fresh process
status=completed
apply_result={'applied': True, 'yaml': 'replicas: 3'}
total events for this run: 13

Prototyping an agent is easy. Running it in production is where things break.

Several frameworks can get a working agent loop running in an afternoon. The gap shows up after that — when the agent has to survive contact with a real environment.

Replayable state

Current state is derived from the event stream, so every decision has a trail.

Approval gates

Mutating tools can require one role, many roles, or expire after a deadline.

Crash recovery

Resume from persisted checkpoints in a new process after a restart or deploy.

Agentic patterns

Parallel tool calls, sub-agent delegation, and full handoff are built into Agent.

The process restarts mid-run.
A pod gets rescheduled, a deploy rolls out, a laptop sleeps. What happens to the agent that was three tool calls into a task when that happens?
A tool call needs a human first.
Before an agent runs a database migration or applies a Kubernetes manifest, someone needs to approve it — and that approval might arrive five seconds or five hours later, from an entirely different process.
You need to know what happened.
Not just "the agent finished" — which tool calls were made, in what order, what each step cost, and why the agent took the path it took.
You need more than one agent.
Ten thousand concurrent sessions, not one notebook cell — shared rate limits, no thread blocked per run, and a store that doesn't fall over under load.

Everything that happens is an event. State is just a replay.

Every LLM call, tool call, and transition is recorded as an immutable event with its own timestamp and cost. The agent's current state is never mutated in place — it's derived by folding that event log. This is the single design decision underneath every other claim Kestrion makes about durability.

01

Plan the next step

The agent chooses a node or tool call while the engine owns the run state.

02

Record the event

Inputs, outputs, timestamps, and transition metadata are persisted.

03

Pause when required

Approval-required tools park the run without keeping a thread alive.

04

Replay and resume

A fresh process folds the log, rebuilds state, and continues from the checkpoint.

PROVEN
Execution engine
Drives the node graph, checkpoints on every transition, enforces approval gates centrally
PROVEN
Event log + checkpoint store
SQLite-backed today, behind a protocol that swaps to Postgres without engine changes
PROVEN
Agent / @tool decorators
Declarative API on top of the raw engine primitives — signature introspection generates JSON schemas automatically
PROVEN
LLM providers
Anthropic, OpenAI, and Ollama behind one protocol — Ollama is live-smoke-tested locally
PROVEN
MCP integration
Consume external MCP tools over stdio/HTTP, or expose a Kestrion agent as one MCP tool
PROVEN
Agent orchestration
Parallel tool calls, sub-agents, approval propagation, and full multi-agent handoff
PROVEN
CLI & Deploy
Project scaffolding, kestrion init/run/deploy — generates full K8s manifests and Dockerfile
PROVEN
Trace viewer & Dashboard
Terminal trace inspector and local web dashboard with gated-tool approvals UI
PROVEN
Memory compaction
Long-running conversations compact older turns via LLM summary when turn/token thresholds are hit
PLANNED
Scheduler
Rate-limited, concurrent execution across many agent runs sharing one provider quota
PLANNED
Postgres store
Production store for multi-worker deployments; the CheckpointStore protocol is already pluggable

Made for agents that touch real systems, not just demos.

Kestrion is useful wherever an agent has to make progress over time, call tools with side effects, pause for review, and still leave a clean record of what happened.

Infrastructure copilots

Let an agent inspect Kubernetes, Terraform, or cloud state while requiring approval before it applies a manifest, scales a deployment, or changes production config.

approval-first ops

Long-running workflows

Build workflows that wait on engineer and manager sign-off, then expire cleanly if nobody approves inside the allowed window.

approval chains

Auditable automation

Record every transition, tool call, provider response, and cost signal so teams can inspect behavior after the run instead of guessing from logs.

traceable by default

Support and back-office agents

Route work to specialist agents, delegate sub-tasks, or fully hand off a conversation while keeping run IDs and approvals scoped correctly.

sub-agents + handoff

MCP-connected agents

Import tools from a real MCP server, apply Kestrion approval gates to selected MCP tools, or serve a full agent as one MCP tool.

stdio and HTTP

Parallel tool batches

When a model requests multiple tools in one turn, Kestrion runs the safe batch concurrently and pauses the whole batch if any gated tool is unapproved.

all-or-pause safety

Small primitives that make agent behavior easier to trust.

The framework is still pre-alpha, but the core design is intentionally narrow: record facts, derive state, and put risky tool execution behind engine-level controls.

What Kestrion gives you as defaults

OK
Checkpoint after transitionsEvery meaningful step can be persisted before the agent moves on.
OK
No hidden mutable stateThe current run state is reconstructed from stored events and checkpoints.
OK
Central approval enforcementApproval-required tools pause through the engine instead of relying on scattered app logic.
OK
Batch safety for toolsIf one tool in a parallel batch is gated and unapproved, none of the tools in that batch execute.
OK
Agent boundaries stay explicitSub-agents and handoff targets get their own run IDs, avoiding approval leakage across agents.

Current proof points

110tests passing locally, with 1 optional Ollama smoke test skipped.
2-wayMCP support: consume external tools and serve a Kestrion agent as one MCP tool.
6agentic features: approval chains, timeouts, parallel calls, sub-agents, handoff, memory compaction.

Most frameworks are strong at authoring. Few make production behavior the default.

This is the honest version, including where Kestrion is not uniquely positioned. AWS Strands and Bedrock AgentCore make a similar production-grade pitch, backed by far more engineering capacity. The bet here is an independent, MCP-native alternative for teams that don't want cloud lock-in — not an unchallenged advantage.

LangGraph CrewAI AWS Strands Kestrion
State model Mutable, opt-in checkpoints Mostly in-memory Event-driven hooks Event-sourced by default
Crash recovery Possible, needs setup Not native Tracing, not full replay Default, independently verified
Approval gates Manual graph wiring No native primitive Hooks can cancel a call Enforced by the engine itself
Storage backend In-memory or custom In-memory Bedrock-default Pluggable: SQLite to Postgres

The next features that make Kestrion more useful in production.

The current build proves the core execution model. The next layer is about making that model easier to deploy, inspect, and connect to real tool ecosystems.

NEXT

Approval API

A first-class Agent.approve() flow so paused runs can resume cleanly without manual scratch-state edits.

NEXT

MCP tools

Connect agents to external MCP servers as tool providers, and expose Kestrion agents back out as MCP-compatible services.

NEXT

Postgres store

Move beyond SQLite for multi-worker deployments while keeping the same checkpoint-store protocol.

PLANNED

Scheduler

Run many agent sessions concurrently with shared provider limits and durable work queues.

BUILT

CLI and deploy

Project scaffolding, local inspection commands, and generated Kubernetes manifests for stateless workers.

BUILT

Trace viewer

A lightweight UI for reading event timelines, approvals, tool calls, and provider cost data per run.

What's actually built, and what's still a plan.

Kestrion is pre-alpha at 0.2.1, published on PyPI. The claims above are backed by working code — 110 passing tests — where marked built below; everything else is designed but not yet implemented.

BUILT
Core execution engine — state types, the run loop, checkpointing, approval gating.
BUILT
SQLite checkpoint store — behind a protocol designed for Postgres to replace it without touching the engine.
BUILT
Agent / @tool decorator API — function signatures auto-convert to JSON schemas; Agent(provider=..., tools=[...]) wraps the engine in an LLM tool-calling loop.
BUILT
Three LLM providers — Anthropic, OpenAI, and Ollama, each an optional install extra behind one shared protocol.
BUILT
Worked example — a Kubernetes scaling agent demonstrating pause-on-approval and resume-after-restart.
BUILT
MCP client & server — consume external tools and serve a Kestrion agent.
BUILT
CLI & deployment — scaffolding, running scripts, and generating Kubernetes manifests.
BUILT
Six agentic features — multi-step approval chains, time-boxed approvals, parallel tool calls, sub-agents, multi-agent handoff, and memory/context compaction.
BUILT
CLI & Deploy toolingkestrion init, kestrion run, kestrion deploy --target k8s for generating Kubernetes manifests and Dockerfiles.
BUILT
Trace viewer & Web Dashboardkestrion trace for colorized terminal timelines and kestrion dashboard for the local web approval console.
PLANNED
Postgres store and scheduler — production-grade storage for multi-worker deployments and rate-limited concurrent agent execution.
# published on PyPI — each provider is an optional extra
pip install kestrion[anthropic] # or [openai], [ollama], or [all]

From first tool to production agent in four steps.

Kestrion is intentionally layered. You can start with a single decorated function and add approval gating, crash recovery, and sub-agents only when you need them.

01

Write a tool

Any Python function with @tool. Type hints become the JSON schema the model receives.

02

Create an agent

Agent(provider=..., tools=[...]) wires a model provider to your tools and a SQLite store.

03

Gate dangerous tools

Add requires_approval=True to any tool that writes, deletes, or modifies production state.

04

Resume from anywhere

A paused run stores everything in SQLite. agent.resume(run_id) works in a completely new process.

Step 1 — Simple tool

from kestrion.agent.decorators import tool @tool def get_server_status(server: str) -> dict: """Check the health of a server.""" return {"server": server, "status": "ok", "disk_pct": 45}

Step 2 — Agent with store

from kestrion.agent.agent import Agent from kestrion.llm.anthropic_provider import AnthropicProvider agent = Agent( provider=AnthropicProvider(model="claude-sonnet-4-6"), tools=[get_server_status], store="sqlite:///runs.db", ) result = await agent.run("Check web-01 server status") print(result.status) # RunStatus.COMPLETED

Step 3 — Gated tool

@tool(requires_approval=True) def restart_server(server: str) -> dict: """Restart a server. Requires approval.""" return {"restarted": server} result = await agent.run("Restart web-01") print(result.status) # waiting_on_human # Nothing was restarted yet!

Step 4 — Approve & resume

from kestrion.core.engine import Engine from kestrion.core.types import Checkpoint, new_id from datetime import datetime, timezone Engine.record_approval( result.state, "restart_server", role="__any__" ) await agent._store.save(Checkpoint( checkpoint_id=new_id("ckpt"), run_id=result.run_id, state=result.state, created_at=datetime.now(timezone.utc), event_seq=result.state.last_event_seq, )) final = await agent.resume(result.run_id) print(final.status) # RunStatus.COMPLETED

Multi-role approval chains

Require sign-off from multiple roles before a tool executes. The run stays paused until all roles have approved.

@tool(requires_approval=["engineer", "manager"], approval_timeout_seconds=3600.0) def deploy_to_prod() -> dict: """Deploy. Needs engineer + manager, within 1h.""" ... # record each role independently: Engine.record_approval(state, "deploy_to_prod", role="engineer") # still waiting for manager... Engine.record_approval(state, "deploy_to_prod", role="manager") # now it can proceed.

Sub-agents & Handoff

Wrap any agent as a tool another agent can call. For full conversation transfer, use as_handoff_target().

# Sub-agent delegation: specialist = Agent(provider=..., tools=[cleanup]) cleaner = specialist.as_tool( "clean_disk", "Ask disk specialist to clean" ) parent = Agent(provider=..., tools=[cleaner]) # Multi-agent handoff: billing = Agent(provider=..., tools=[issue_refund]) handoff = billing.as_handoff_target( "transfer_to_billing", "Transfer conversation to billing" )

Memory & context compaction

Long-running agents automatically summarize older conversation turns when thresholds are hit, preventing context overflow.

agent = Agent( provider=OllamaProvider(model="llama3.2"), tools=[my_tool], store="sqlite:///runs.db", # Summarize when history exceeds 20 turns max_history_turns=20, # Always keep the 4 most recent turns intact keep_turns=4, ) # When threshold is exceeded, older turns are # summarized by the LLM and replaced with a # compact context block automatically.

MCP integration

Connect to real MCP servers as tool providers, or expose a Kestrion agent as an MCP-compatible service.

# Consume MCP tools (with approval gating): async with MCPClient.stdio( command="python3", args=["my_mcp_server.py"] ) as client: tools = await client.list_tools( requires_approval=["apply_manifest"] ) agent = Agent(provider=..., tools=tools) # Expose agent as an MCP server: mcp_server = serve_agent(agent, name="ops") mcp_server.run(transport="stdio")

How to wire Kestrion into a real application.

Kestrion is a Python library, not a hosted service. Wiring it into an existing codebase means choosing a store, connecting your LLM provider credentials, and deciding which tools need gating. Here's the canonical path.

STEP 1
Install
pip install kestrion[anthropic] — pick exactly the providers you use; nothing else is installed
STEP 2
Set API keys
Export ANTHROPIC_API_KEY or OPENAI_API_KEY. For Ollama, no key is needed — just run ollama serve locally
STEP 3
Define tools
Decorate Python functions with @tool or @tool(requires_approval=True). Docstrings become model descriptions automatically
STEP 4
Create an Agent
Agent(provider=..., tools=[...], store="sqlite:///runs.db") — point the store at a local file for dev, a shared volume in production
STEP 5
Handle paused runs
Poll result.status == RunStatus.WAITING_ON_HUMAN and wire Engine.record_approval() to your existing approval UI or webhook
STEP 6
Deploy
Run kestrion deploy --target k8s to generate Namespace, Deployment, PVC, and Service manifests — then kubectl apply -f
Connecting an existing approval webhook
Your webhook receives the run_id and tool name from result.state.scratch["_pending_approval"]. Call Engine.record_approval(state, tool_name, role="approver"), persist a new Checkpoint, then call agent.resume(run_id) — all from a completely independent process.
Using Ollama for local development
ollama serve starts the local model server. pip install kestrion[ollama] installs only httpx — no other deps. Use OllamaProvider(model="llama3.2") as the drop-in provider. Swap to AnthropicProvider or OpenAIProvider in production without changing any tool code.
Exposing a Kestrion agent as an MCP tool
serve_agent(agent, name="ops-agent") exposes a single ask_agent(prompt) MCP tool. The full reasoning loop — including all approval gates — runs on every call. A paused run surfaces as a clear human-readable message, not an MCP error.
Handling long conversations (memory compaction)
Set max_history_turns=20 and keep_turns=4 on Agent. When the threshold is exceeded, older turns are summarized by the same LLM provider and replaced with a compact context block. A context_compacted event is logged durably for full traceability.

Commands built into kestrion — no extra tools needed.

Install Kestrion once. Get project scaffolding, run management, Kubernetes deployment generation, a terminal trace inspector, and a local web approval console out of the box.

kestrion init

Scaffold a new agent project with the correct directory layout, a starter agent script, and a Dockerfile — zero configuration required.

kestrion init ./my-agent

kestrion run

Run any agent script directly through the CLI with environment isolation and clean error reporting.

kestrion run agent.py

kestrion deploy

Generate a complete Kubernetes manifest set — Namespace, ConfigMap, Deployment, PVC, and Service — plus a production-ready Dockerfile.

kestrion deploy --target k8s --name my-agent

kestrion trace

Print a colorized, chronological event timeline for any run directly in your terminal — token counts, tool calls, transitions, and pending approvals.

kestrion trace <run_id>

kestrion dashboard

Launch a local web dashboard to visually inspect runs, browse event payloads and costs, and approve pending gated tools through a clean UI.

kestrion dashboard --port 8080

MkDocs docs site

Full API reference documentation for the core engine, Agent API, providers, and store protocol — served locally or hosted via GitHub Pages.

mkdocs serve
kestrion CLI — live commands
# Scaffold a new project
$ kestrion init ./my-agent
Initialized project at ./my-agent
# Generate Kubernetes manifests
$ kestrion deploy --target k8s --name my-agent --image registry.example.com/my-agent:latest
Generated my-agent-k8s.yaml and Dockerfile
# Print a colorized terminal timeline for a run
$ kestrion trace run_abc123 --store kestrion_runs.db
[llm_call_completed] tokens=289 cost=$0.0008
[tool_call_completed] get_server_status → {"status": "ok"}
[human_intervention] restart_server — missing roles: ["ops"]
# Launch the visual web approval dashboard
$ kestrion dashboard --port 8080
Dashboard running at http://localhost:8080

The actual code you'd write.

Every line below maps to code that exists and is covered by the test suite — not aspirational API design.

quickstart.py
from kestrion.agent.agent import Agent
from kestrion.agent.decorators import tool
from kestrion.llm.anthropic_provider import AnthropicProvider
@tool
def get_cluster_state() -> dict:
    """Read current deployment replica counts."""
    return {'deployment': 'checkout-api', 'replicas': 2}
@tool(requires_approval=True)
def apply_manifest(yaml: str) -> dict:
    """kubectl apply a manifest against the cluster."""
    return {'applied': True}
agent = Agent(
    provider=AnthropicProvider(model="claude-sonnet-4-6"),
    tools=[get_cluster_state, apply_manifest],
    store="sqlite:///agent_runs.db",
)
result = await agent.run("Scale up checkout-api if it's under 3 replicas")
status=waiting_on_human # paused before the mutating call
What you can build today
Tool-calling agents where some actions are safe to auto-run and others need a human gate first. Agents that survive a crash mid-task — agent.resume(run_id) works from a completely independent process. Long-running approval workflows: start a run, let it sit paused for hours, approve and resume it from anywhere with access to the same store. Multi-turn tool use, where the agent keeps calling tools and reasoning over results until it has a final answer.
Known gaps, honestly
No concurrency control scheduler across separate runs yet. Agent.approve() is still a stub — approving a paused run means manually calling Engine.record_approval() and saving a checkpoint by hand. SQLite only; Postgres support is designed but not yet implemented. Anthropic and OpenAI providers are implemented but not yet smoke-tested against a live API.

Reference — install, resume, and develop locally.

kestrion 0.2.1 — pypi.org/project/kestrion

Install

Each LLM provider is an optional extra. Install only what you use.

pip install kestrion[anthropic] pip install kestrion[openai] pip install kestrion[ollama] pip install kestrion[all] # every provider

Resuming a paused run

Works from a completely independent process — the actual crash-recovery guarantee, not just a convenience method.

Engine.record_approval( result.state, "apply_manifest", role="__any__" ) await agent._store.save(Checkpoint(...)) result = await agent.resume(run_id)

Local development

Clone, install in editable mode with dev extras, run the suite.

git clone https://github.com/VinayakDubey07/kestrion.git cd kestrion python3 -m venv .venv source .venv/bin/activate pip install -e ".[dev]" pytest tests/ -v

110 tests passing, 1 skipped.

Examples

examples/kubectl_agent — the original worked example, demonstrating pause-on-approval and resume-after-restart using the raw Engine/Node primitives directly, useful for understanding what Agent builds on top of.

Links

GitHub repository  ·  PyPI package  ·  Full README  ·  Issues

Licensed under Apache 2.0.