DBOS is a polyglot durable workflow library on Postgres. Code crashes, and DBOS makes sure you don’t start over — workflow state sits alongside your OLTP data in the same database, and Conductor gives ops a UI for scheduled workflows and durable queues. It’s a serious answer to “how do I keep this running,” and it’s not trying to be anything else.
Kitaru isn’t trying to keep anything running. It answers a different question: once an agent run happened, can you re-run it? Kitaru records runs as sessions — through a framework adapter or by importing the traces you already collect — and replays them against your real code, so a model or prompt change gets tested against what actually happened in production.
The two stack cleanly. An agent that DBOS keeps alive in production can still be wrapped by a Kitaru adapter, or have its traces imported, and its sessions become the regression suite that catches the next bad deploy before it ships.
Use Kitaru if you are
- Testing a model, prompt, or code change to a DBOS-run agent against real production sessions instead of a hunch
- Recording agent runs via a framework adapter (PydanticAI, LangGraph, OpenAI Agents SDK, Mastra, Vercel AI SDK), or importing traces you already send to Langfuse, LangSmith, or Braintrust
- Freezing the sessions that caught a regression into a cohort that gates every future change
- Self-hosting the eval infrastructure so traces and credentials stay in your own systems
Use DBOS if you are
- Running durable workflows across Python, TypeScript, Go, and Java services with one contract
- Leaning on durable queues, cron schedules, and the Conductor UI for ops
- Needing DBOS Conductor's managed workflow console, and on paid plans, SOC 2 / HIPAA-compliant tooling
- Already deep into Postgres and want durable state living in the same database as your app
DBOS makes sure your agent doesn't lose its place when it crashes. Kitaru makes sure you know whether the change you're about to ship is actually an improvement.
Recording, not instrumenting
In DBOS, an LLM call is something you make inside your own @DBOS.step, and instrumenting it — tokens, cost, model identity — is your code. Kitaru doesn’t change how DBOS runs your agent. It sits at the framework boundary: wrap the agent with a Kitaru adapter, or import the traces you already collect, and every model call and tool call lands as a node on a session automatically — model, tokens, latency, cost, no separate logging setup.
openai.chat.completions.create(prompt=…)OTel traces via instrumentation — tokens, cost, and retries are your code.- model
- gpt-5.4 · anthropic
- recorded
- model call + tool call, as nodes
From one session to a regression suite
One replayed session answers a question about one run. Freeze the sessions that matter into a cohort, and an experiment replays that whole cohort with one thing changed — a model, a prompt — and compares the two runs side by side.
DBOS persists step input and output in Postgres so a workflow can resume where it left off. That’s state for a run in progress. A Kitaru session is a recording of a finished run, kept so it can be replayed later — different data, doing a different job.
Wrap it, don't rebuild it
DBOS is a library. You deploy the Python app however you already deploy Python apps, and durable state lives in whatever Postgres you point it at. That’s simple and portable, and Kitaru doesn’t change any of it.
- One wrapper, no rewrite:
KitaruAgent(agent, agent_id=...)wraps the agent you already wrote in PydanticAI, LangGraph, or the OpenAI Agents SDK.run,run_sync, tools, and output types behave exactly as on the wrapped agent. - TypeScript too: Mastra and the Vercel AI SDK get native-signature adapters —
KitaruAgent(existingAgent, options)andcreateKitaruGenerateText(...). - No adapter for your stack yet? Import the traces you already send to Langfuse, LangSmith, or Braintrust, or emit OTLP and import that. Either path lands as a session.
- Self-hosted, Apache 2.0: one FastAPI + Postgres server on your infrastructure. Replays and evaluations execute on workers in your environment — traces and credentials don’t leave your systems.
Two ways in: adapters and imports
DBOS gives you scheduled workflows and durable queues with concurrency limits and deduplication — the operational shape of keeping an app running. Kitaru’s shape is different: getting a run recorded in the first place.
- Wrap it: shipped adapters cover PydanticAI, LangGraph, the OpenAI Agents SDK, Mastra, and the Vercel AI SDK. One wrapper, no rewrite, every run lands as a session.
- Or import it: already tracing to Langfuse, LangSmith, or Braintrust? Import those traces directly. No adapter, no code change.
- Same downstream either way: once a session exists, replay, cohorts, experiments, and evaluators work identically whether it arrived through an adapter or an import.
What makes Kitaru unique
| Feature | Kitaru | DBOS |
|---|---|---|
| Durable execution with checkpoint / step replay | Not supported | Yes |
| Durable queues, cron scheduling, and dedup | Not supported | Yes |
| Polyglot SDKs (Python, TypeScript, Go, Java) | Not supported | Yes |
| SOC 2 / HIPAA compliant managed control plane (Conductor, paid plans) | Not supported | Yes |
| Records agent runs as replayable sessions (adapter or trace import) | Yes | Not supported |
| Replays a session against real code, tool calls answered from the recording | Yes | Not supported |
| Cohorts: frozen session sets as regression suites | Yes | Not supported |
| Experiments: same cohort, one variable moved, compared | Yes | Not supported |
| Deterministic + model-graded evaluators | Yes | Not supported |
| Imports Langfuse / LangSmith / Braintrust / OTel traces | Yes | Not supported |
| Self-hosted, open source (Kitaru: Apache 2.0) | Yes | Yes |
How the two surfaces map
| Concept | DBOS | Kitaru |
|---|---|---|
| Layer | Durable execution (keeps the agent alive in prod) | Replay-based evals (tests a change to the agent) |
| Core unit | Workflow / step | Session — recorded run, re-executable |
| State backend | Postgres, alongside your OLTP data | Self-hosted server (Postgres) plus your own workers |
| Recording | N/A — DBOS orchestrates, doesn’t record for eval | A framework adapter wraps the agent, or traces are imported |
| “Did my change help?” | Not what DBOS answers | Two runs over the same cohort, diffed |
| Deployment | Library embedded in whatever Python app you already ship | Adapter wraps the agent; server + workers self-hosted |
Code comparison
from pydantic_ai import Agent
from kitaru_pydantic_ai import KitaruAgent
reviewer = KitaruAgent(
Agent("openai:gpt-5.4", system_prompt="You're a compliance reviewer."),
agent_id=AGENT_ID,
)
# DBOS keeps this durable in production.
# Every run also lands as a Kitaru session.
result = reviewer.run_sync(case)
# Later: freeze the sessions that matter, test a change.
import kitaru
client = kitaru.KitaruClient()
cohort = client.cohorts.create("hard-cases", sessions=session_ids)
experiment = client.experiments.create(
"cheaper-model",
model="gpt-5-mini",
tool_policy=History(scope="cohort", on_miss="fail"),
)
before = experiment.run(cohort=cohort, version="v1")
after = experiment.run(cohort=cohort, version="pr-311")
client.compare(before, after)from dbos import DBOS
import openai
client = openai.OpenAI()
@DBOS.step()
def research(topic: str) -> str:
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user",
"content": f"Research: {topic}"}],
)
return resp.choices[0].message.content
@DBOS.step()
def draft(brief: str) -> str:
resp = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user",
"content": f"Write a draft:\n{brief}"}],
)
return resp.choices[0].message.content
@DBOS.workflow()
def review_flow(topic: str) -> str:
brief = research(topic)
text = draft(brief)
# Human approval via DBOS.send / recv messaging.
approved = DBOS.recv(timeout_seconds=86400)
return text if approved else "Rejected"
# Plus: start the DBOS runtime, send approval
# from another process via DBOS.send.Put replay-based evals under your DBOS-run agents
If your durability problem is polyglot services against Postgres with a SOC 2 or HIPAA control plane on day one, DBOS is better-shaped for that workload — be honest about which side you’re on. If the question is whether the change you’re about to ship to a DBOS-run agent actually helps, Kitaru replays the sessions that already happened — record them once, via an adapter or an import, and every future change gets tested against real production behavior instead of a guess.
uv add "kitaru[cli,worker]" kitaru-pydantic-ai