Compare

Kitaru vs Inngest: durable execution and replay-based evals, composed

Inngest keeps your agent running durably in production. Kitaru records what it did and replays it as an eval — a different layer, not a competing runtime.

uv add "kitaru[cli,worker]" kitaru-pydantic-ai
Sign up freeRead the docs

Inngest and Kitaru solve different problems at different layers. Inngest is a durable execution platform: one engine takes your TypeScript, Python, or Go function, wraps it in retries and step memoization, and gives you the flow-control surface (concurrency, throttling, rate limiting, debounce, batching, prioritization) that most workflow engines leave you to wire up yourself. Add managed Inngest Cloud with SOC 2 Type II, enterprise SAML, HIPAA BAA available, and a single-binary self-host path, and you can see why a lot of teams on Vercel or Lambda picked it. If your durability problem is shaped like an event-driven app, Inngest is the pragmatic answer.

Kitaru doesn’t run your workloads at all — it’s a replay-based eval layer. It records a production run as a session — every model call, tool call, decision — and a session re-executes: unchanged, it reproduces the original as a faithful baseline; forked, it re-runs with one thing changed. Agents running on Inngest are no exception. Wrap them with a first-class adapter (Pydantic AI, OpenAI Agents SDK, LangGraph, Mastra, Vercel AI SDK), or import the traces you already collect in Langfuse, LangSmith, Braintrust, or OTel, and every run becomes a session you can replay.

Kitaru

Use Kitaru if you are

  • Running agents in production, on Inngest or anywhere else, and want to test a change before it ships, not just watch logs after
  • Recording production runs as sessions via an adapter (Pydantic AI, OpenAI Agents SDK, LangGraph, Mastra, Vercel AI SDK) or importing traces you already collect
  • Turning the sessions that caught a failure into a cohort that gates every future change
  • Comparing a model or prompt swap on the same frozen population instead of a vibe check
  • Self-hosting eval infrastructure so traces and credentials stay in your own systems
Alternative

Use Inngest if you are

  • Running a polyglot estate (TypeScript, Python, Go) that needs one durability primitive across all of it
  • Building event-driven workflows, background jobs, durable endpoints, or replacing a queue
  • Leaning on a flow-control suite (concurrency, throttling, rate limiting, debounce, batching, prioritization) as a first-class feature
  • Fine adopting managed Inngest Cloud, or self-hosting the single-binary engine
Inngest keeps your agent running in production. Kitaru replays what it did, so you can prove a change before it ships.

Different jobs, not one stack

Inngest’s defaults are events, cron, retries, step memoization, and flow control — a packaged platform for making any function durable. Kitaru’s defaults are record, replay, and improve: wrap or import a run as a session, re-execute it with the recording answering for the world, and compare cohorts before and after a change.

Durable execution platform versus replay-based eval layer.Compares Inngest as a packaged durable-execution platform with Kitaru as a replay-based eval layer that records and replays agent runs.
Inngest · platform across the stackRuntime + event bus + dashboard, packaged together
Inngest platform
events · cron · webhooksdurable engine · retries · stepsflow control · throttle · concurrencydashboard · replay · branch envs
your app re-shaped around it
Adopt the platform, get durability and the rest as one piece.
Kitaru · replay-based eval layerSits beside production, records and replays runs
Recordwrap with an adapter, or import Langfuse / LangSmith / Braintrust / OTel traces
Replaysession re-executes; tool calls answered from the recording
Cohortthe sessions that matter, frozen as an immutable set
Experimentsame cohort, one variable moved, compared side by side
Kitaru doesn't orchestrate anything. It records what already ran and replays it.
  • Different problems, not competing solutions. Inngest makes your production code durable. Kitaru makes your production history runnable as a test bench. Neither one does the other’s job.
  • Composable by design. An agent step running inside an Inngest function is exactly the kind of run Kitaru wants to record — wrap it with an adapter, or import the trace, and it’s a session like any other.

Durable steps vs recorded sessions

The shape of the SDK tells you who the team was watching when they set the defaults. Inngest’s surface is step.run, step.sleep, step.wait_for_event, step.send_event, step.invoke — durable primitives for any function. Kitaru’s surface is the adapter that wraps your agent, and the client that turns its sessions into a test suite.

Durable step primitives versus recorded session primitives.Compares Inngest step primitives across several languages with Kitaru's adapter and client primitives for recording and replaying agent sessions.
Inngest · polyglot durable functionsSteps register with the engine across TypeScript, Python, Go
TypeScriptPythonGoKotlin/Java
step.rundurable step, return value persisted
step.sleeptimer that releases compute
step.wait_for_eventresume on a matching event send
step.invokecall another function across apps
Durable, general-purpose. Session recording isn't built in.
Kitaru · record and replay primitivesOne wrapper to record, one client to test a change
KitaruAgentwraps a Pydantic AI agent transparently
support.run_sync()runs exactly as before · lands as a session
cohorts.create()freeze the sessions that matter into a named set
experiments.create()model, prompt, tool policy — pure configuration
client.compare()diff two experiment runs over the same cohort
Adapters ship for Pydantic AI, OpenAI Agents SDK, LangGraph, Mastra, Vercel AI SDK — or import traces for anything else.
  • Languages: Inngest ships SDKs for TypeScript, Python, and Go (with a Kotlin/Java repo). Kitaru ships a Python SDK, a TypeScript SDK, a CLI, and an MCP server for your coding agent.
  • Recording: KitaruAgent(agent, agent_id=AGENT_ID) wraps a Pydantic AI agent transparently — run, run_sync, iter behave exactly as before, and every call lands as a session.
  • Testing a change: client.cohorts.create(...) freezes the sessions that matter; client.experiments.create(...) moves one variable (model, prompt, tool policy); client.compare(before, after) shows what changed.

Self-hosted, in your systems

Both products take data seriously. The wedge is where it lives, and how much packaging arrives with it.

Customer-controlled data path versus managed cloud.Compares Inngest Cloud as a hosted engine and dashboard with Kitaru's self-hosted server and workers, where sessions and traces stay in the customer's environment.
Inngest · managed cloud is the easy pathEngine, queue, state, dashboard — hosted for you
your app
Inngest CloudSOC 2 · SAML · HIPAA BAA
durable engineflow controlreplay UI
Hosted in US AWS databases
Alt: single-binary self-host
Spend buys managed convenience and a flow-control suite.
Kitaru · self-hosted, Apache 2.0One server, your own workers, your environment
your sessions
Kitaru serverFastAPI + Postgres · sessions, cohorts, experiments, evaluators
your Postgresyour workersyour traces
Pydantic AIOpenAI Agents SDKLangGraphMastra / Vercel AI
Self-hosted, Apache 2.0 — traces and credentials never leave your systems.
  • Kitaru: Self-hosted by default — one FastAPI + Postgres server, Apache 2.0. Workers execute replays, imports, and evaluations in your own environment. Traces and credentials don’t leave your systems.
  • Inngest: Managed Inngest Cloud is the easy path: SOC 2 Type II, enterprise SAML, HIPAA BAA available, encrypted data at rest and in transit, and isolated production, branch, custom, and local environments. Self-hosting is supported via a single-binary engine. Managed-cloud data is hosted in US AWS databases, which is a constraint for some.

Step memoization vs session replay

Both products persist work so you don’t lose it. The data models are built for different jobs.

Step memoization versus session replay.Compares Inngest step memoization and replay tooling with Kitaru's recorded session nodes, cohorts, and experiment comparisons.
Inngest · step memoization + replay UIEngine persists step return values; dashboard turns it operational
function run
step.run · research memoizedstep.run · draft memoizedstep.wait_for_event · approve
replay buttonbulk canceltraces · alertsbranch envs
Operational tools follow from durable step memoization.
Kitaru · sessions + experimentsEvery call recorded, cohorts frozen, runs compared
session · support-ticket-4821
llm_call · triagerecorded: prompt, response, tokens, cost
tool_call · refund_paymentrecorded: args + result (replay answers from here)
evaluator · structured_diffdeterministic check, model-graded for the residue
client.compare(before, after)
before · v1after · pr-311cohort: hard-cases10 sessions
Cohorts freeze the set; experiments diff before vs after.
  • Inngest: Step return values get memoized by the durable engine, so a crashed run replays from the last completed step rather than from the top. The dashboard turns that durability into operational tools: a replay button on stuck functions, bulk cancellation, traces, alerts, and branch environments per Git branch.
  • Kitaru: Every recorded call — model or tool — lands as a node on the session: inputs, outputs, tokens, cost, latency. A session replays with tool calls answered from the recording, so nothing touches real systems. Freeze the sessions that matter into a cohort, and an experiment replays that cohort with one variable moved — then client.compare(before, after) shows what improved and what regressed.

What makes Kitaru unique

FeatureKitaruInngest
Durable execution and replay of production workloadsNot supportedYes
Retries, step memoization, and flow control (concurrency, throttling, rate limits)Not supportedYes
SDKs across TypeScript, Python, and Go (plus a Kotlin/Java repo)Not supportedYes
Managed cloud with SOC 2 Type II, SAML, HIPAA BAA availableNot supportedYes
Record production agent runs as replayable sessionsYesNot supported
Adapters for Pydantic AI, OpenAI Agents SDK, LangGraph, Mastra, Vercel AI SDKYesNot supported
Import traces from Langfuse, LangSmith, Braintrust, or OTelYesNot supported
Replay with tool calls answered from the recording — nothing touches real systemsYesNot supported
Cohorts: frozen, immutable session setsYesNot supported
Experiments: same cohort, one variable moved, comparedYesNot supported
Deterministic and model-graded evaluatorsYesNot supported
Self-hostable (Kitaru: Apache 2.0 server and workers; Inngest server: SSPL with delayed Apache, SDKs Apache 2.0)YesYes

How the two surfaces map

ConceptInngestKitaru
LayerDurable execution platform (how the work runs)Replay-based evals (how you test what it did)
Core unitFunction runSession — recorded model and tool calls, re-executable
CompositionFunction registered with the engine, triggered by an eventAgent wrapped once by an adapter, or a trace imported
Tool calls in testsHit real systems, or you mock them by handAnswered from the recording per tool policy
“Did my change help?”Read the traces, compare by eyeTwo runs over the same cohort, diffed
Crash mid-runStep memoized, engine resumes from therePartial session recorded — the evidence survives
Where it runsInngest Cloud, or a self-hosted single binarySelf-hosted FastAPI + Postgres server; workers replay in your environment

Code comparison

Kitaru (recording the agent)Recommended
from pydantic_ai import Agent
from kitaru_pydantic_ai import KitaruAgent

agent = Agent("openai:gpt-5.4", name="support-agent",
            system_prompt="You resolve support tickets.")

support = KitaruAgent(agent, agent_id=AGENT_ID)

# Runs inside your Inngest step exactly as before —
# and lands as a session.
result = support.run_sync(ticket_text)

# 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("cheap-model", model="gpt-5-mini")

before = experiment.run(cohort=cohort, version="v1")
after = experiment.run(cohort=cohort, version="pr-311")
client.compare(before, after)
Inngest (Python SDK)
import inngest

inngest_client = inngest.Inngest(app_id="agent-app")

async def call_llm(prompt: str) -> str:
  ...

@inngest_client.create_function(
  fn_id="support-flow",
  trigger=inngest.TriggerEvent(event="ticket.created"),
)
async def support_flow(ctx: inngest.Context) -> str:
  ticket = ctx.event.data["ticket"]

  async def triage() -> str:
      return await call_llm(f"Triage: {ticket}")

  result = await ctx.step.run("triage", triage)
  return result

# Trigger:  await inngest_client.send(
#     inngest.Event(name="ticket.created", data={"ticket": "..."}))
# Functions register with the Inngest engine; events route through it.

Record what Inngest already runs

If your durability problem is shaped like an event-driven app — workflows triggered by events, cron jobs, durable endpoints, queue replacement — Inngest is the right tool, and I’d tell any team that. For testing whether a change to your agent actually helped — replay the sessions that already happened, fork them with one variable moved, compare before and after — Kitaru is the layer that sits beside it, not underneath it.

We’ve spent five years building the MLOps-ready version of this problem space at ZenML. JetBrains runs their AI globally on it; Adeo runs across all their brands and geographies on it. Kitaru is that team two years into the agent version. Bet on us for agent infrastructure and you’re betting on the group that’s been doing this the whole time.

uv add "kitaru[cli,worker]" kitaru-pydantic-ai
Sign up free