🎯 Why Kitaru?
Most traces are transcripts — you read them. A Kitaru trace re-executes: your actual code runs again, with the trace answering for everything the original run saw. Kitaru is a debugger with a memory, sitting beside your observability stack — it tells you what happened; Kitaru re-runs it. That turns production traffic into the eval suite you never had to write: every incident is a reproducible test case, and "would the cheaper model have held?" is an experiment over real traces instead of a guess.
- Every trace is a recording. Each checkpoint output — model call, tool call, decision — is written to your object store as a typed, versioned artifact. Step through it, diff it against other runs, trace a bad output back to the step that produced it.
- Replay is re-execution, not re-scoring. An unchanged replay reproduces the original exactly — and that faithful baseline is what lets you fork from any checkpoint with one thing changed and trust that the diff is your change, not replay noise.
- Decide with evidence. Every trace includes the model traffic — prompt,
response, tokens, latency, estimated cost — recorded automatically by the
framework adapters, or by
kitaru.llm()in raw Python.
🔁 The loop
uv add "kitaru[pydantic-ai]" # plain `kitaru` for the raw @flow/@checkpoint path
kitaru init
No decorators, no graph, no rewrite. Wrap the agent you already have and run it — Kitaru opens a flow around the call and records every model request and tool call as a checkpoint:
# agent.py
from pydantic_ai import Agent
from kitaru.adapters.pydantic_ai import KitaruAgent
agent = Agent("openai:gpt-5.4", name="support-agent",
system_prompt="You resolve support tickets.")
@agent.tool_plain
def refund_payment(order_id: str) -> str:
return payments.refund(order_id) # your real API
support = KitaruAgent(agent)
support.run_sync("Refund order #4821 — the card reader was double-charged.")
Traces recorded elsewhere land the same way — import them, and they become executions like any other:
from kitaru import KitaruClient
client = KitaruClient()
client.executions.import_traces("support-traces.jsonl", format="otel")
client.imports.langfuse(
"langfuse-observations.jsonl",
source_project_id="prod",
agent_name="support-agent",
)
Every run is now a trace you can replay:
trace = client.executions.latest()
# Replay — start from the agent's first model call, and your real code
# runs again against the recorded world. Unchanged, it reproduces the
# original exactly. That's your baseline.
client.executions.replay(trace.exec_id, at="support-agent_model_request")
# Fork — same trace, one thing changed: patch the recorded tool output.
# What would the agent have done if the refund had succeeded?
client.executions.replay(
trace.exec_id,
at="refund_payment_tool",
checkpoint_overrides={
"refund_payment_tool": {"output": "refund issued: $129.00"},
},
)
# Widen — the same call takes a list. Replay last week's traces against
# the code in your working tree, and the cohort is a regression test.
traces = client.executions.list(limit=20)
client.executions.replay(
[t.exec_id for t in traces],
at="support-agent_model_request",
tag="pr-1234-check",
)
Overrides can also swap the model on an LLM call, edit tool arguments, or
swap a checkpoint's code — see
Replay and overrides.
Explicit @flow/@checkpoint decorators are there when you want named
replay boundaries or multi-turn workflows, and flow.deploy() ships a winner
as a versioned deployment invoked by name — optional; stopping at the
regression test is a fine place to stop.
Durable execution (the plumbing)
Recording a run means surviving one. Checkpoints double as crash recovery — a
crash or pod eviction resumes from cached outputs instead of re-burning
tokens. kitaru.wait() pauses a flow for hours or days until a human or
webhook responds. flow.deploy() freezes versioned snapshots that consumers
invoke by name, and @checkpoint(runtime="isolated") runs heavy steps in
their own pod on Kubernetes, AWS, GCP, or Azure. This is how a faithful
recording gets minted — not the reason you reach for Kitaru.
Works with your agent SDK
Adapters for six agent frameworks — wrap your existing agent, no rewrite:
| Framework | Adapter |
|---|---|
| PydanticAI | kitaru.adapters.pydantic_ai.KitaruAgent |
| OpenAI Agents SDK | kitaru.adapters.openai_agents.KitaruRunner |
| Claude Agent SDK | kitaru.adapters.claude_agent_sdk.KitaruClaudeRunner |
| LangGraph | kitaru.adapters.langgraph.KitaruGraphRunner |
| Gemini | kitaru.adapters.gemini.KitaruGeminiInteractionsRunner |
| Google ADK | kitaru.adapters.google_adk.KitaruADKRunner |
For raw-Python agents, @flow and @checkpoint around your calls give you
the same recording without an adapter. Your model, your tools, your
framework — Kitaru wraps them, not the other way around.
Drive it from your coding agent
Everything in the loop is scriptable: each step has a CLI command
(kitaru executions list / logs / replay) and an MCP tool, so Claude Code,
Codex, or any MCP-capable agent can inspect traces, replay them, and read
back the diff. Hook up the MCP server:
uv add "kitaru[mcp]"
claude mcp add kitaru -- kitaru-mcp # or point any agent's MCP config at `kitaru-mcp`
Claude Code users can also install the kitaru-skills plugin — quickstart, workflow authoring, and adapter-migration skills:
/plugin marketplace add zenml-io/kitaru-skills
/plugin install kitaru@kitaru
Self-hosted, batteries included
A single server on your own infra. Flows run on whichever stack you pick — local, Kubernetes, GCP, AWS, or Azure — with artifacts in your own S3/GCS/Azure Blob bucket, and a built-in UI to step through executions, diff replays, and approve human-in-the-loop wait steps. No mandatory SaaS control plane.
📚 Learn more
| Resource | Description |
|---|---|
| Getting Started Guide | Full setup walkthrough with all examples |
| Documentation | Complete reference and guides |
| Agents guide | Run, replay, and improve production agents end to end |
| Examples | Runnable workflows for every feature |
| Stacks | Deploy to Kubernetes, AWS, GCP, or Azure |
| MCP server | Query, replay, and manage executions from any MCP-capable agent |
🌱 Origins
Kitaru is built by the team behind ZenML, drawing on five years of production orchestration experience (JetBrains, Adeo, Brevo). The orchestration primitives (stacks, artifacts, lineage) are purpose-rebuilt here for autonomous agents.
🤝 Contributing
We welcome contributions! See CONTRIBUTING.md for development
setup, code style, and how to submit changes. The default branch is develop —
all PRs should target it.
💬 Community and support
- Discussions — ask questions, share ideas
- Issues — report bugs, request features
- Roadmap — see what's coming next
- Docs — guides and reference
No comments yet
Be the first to share your take.