🎯 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

📄 License

Apache 2.0