Open source · Apache-2.0

The transactional rollback engine for autonomous AI agents.

Agents mutate real systems — databases, CRMs, payments — and they do it non-deterministically. When one hallucinates mid-run, SagaOps unwinds every side effect it caused, in reverse order — or refuses to start the one thing it could never undo.

$pip install agent-saga
REVERSIBLE — restored exactly COMPENSABLE — inverse action IRREVERSIBLE — gated up front
“Undo” is not one thing. It's three.

REVERSIBLE  ·  COMPENSABLE  ·  IRREVERSIBLE

Run it yourself

The same workflow, with the switch off and on.

Three steps: charge $499.00, provision the account, send the welcome mail. The mail server refuses the connection. Flip the switch and watch what each run leaves behind.

Optimistic SagaOps
Stripe compensable
$0.00
no charges
Postgres compensable
0
accounts
Email irreversible
0
sent
Press Run the agent to start.

What you actually change

One wrapper, one inverse per call.

before — optimistic
# nothing unwinds. an exception just propagates.
charge  = stripe.charge(customer, 49900)
account = db.insert_account(customer, email)
mail.send_welcome(email)   # ← raises
after — transactional
async with saga_scope() as saga:
    charge = await saga.execute(
        tool="stripe.charge", semantics=COMPENSABLE,
        forward=lambda: stripe.charge(customer, 49900),
        # the inverse, derived from the RESULT:
        compensate=lambda r: Compensation(
            fn=refund, handler="stripe.refund",
            kwargs={"charge_id": r["id"]}))

    account = await saga.execute(...)   # same shape
    await saga.execute(...)             # ← raises here
# charge refunded, account deleted, LIFO, on the way out

The only new idea is compensate: a factory that receives the forward call's result, because you cannot refund a charge_id you have not seen yet.

Why it exists

A rollback layer built for agents, not for backups.

Two things people reach for don't fit. SagaOps sits exactly where they fall short.

vs. enterprise backup / DR suites

Backups restore a machine. They don't unwind a workflow.

Snapshotting a whole database can't help when an agent charged a card, emailed a customer, and updated three SaaS systems in ninety seconds. SagaOps is a developer-first library — a decorator and a proxy, not an ops platform — that undoes the actions, in order.

vs. plain database transactions

You can't hold BEGIN…COMMIT open while a model thinks.

A transaction locks rows and pins a connection for the seconds an LLM takes to decide — and it can't span Stripe, Salesforce and Postgres at once anyway. SagaOps records forward calls and their runtime-derived inverses, then compensates LIFO across every system the agent touched.

Wrap a boundary · watch it unwind

One saga_scope. Every side effect accounted for.

from agent_saga import saga_scope
from agent_saga.connectors import stripe, salesforce

async with saga_scope() as saga:
    await salesforce.patch_object(saga,
        object_type="Lead", object_id="00Q…",
        patch={"Status": "Won"}, credential_ref="sf")

    await stripe.charge(saga, customer_id="cus_…",
        amount=42000, credential_ref="stripe_prod")

    # the agent hallucinates a field and raises →
    # charge refunded, Lead reverted, LIFO, on the way out.
    # had a step been IRREVERSIBLE, the pre-flight
    # gate would have refused to start it at all.
time-travel debugger · saga_7f2c ROLLED_BACK ✓ clean
salesforce.patch_object
Lead 00Q… · reverted to prior JSON
compensated
postgres.update_row
leads#4821 · restore guarded
compensated
stripe.charge
ch_… · refunded, idempotency-keyed
compensated
email.send_receipt
blocked before send · needs approval
gated

Representative view of the built-in time-travel debugger, rendered from the WAL.

The engine

Four parts. The gate is the one a risk committee buys.

Typed compensation semantics

Every effect is classified before it runs.

REVERSIBLE restores exactly. COMPENSABLE emits an inverse that leaves an honest trace (a refund, not a rewind). IRREVERSIBLE can't be undone — so it's never quietly attempted.

Pre-flight policy gate

Refuse the uncompensable, up front.

The gate evaluates a tool call — including its arguments — before the side effect. Cross an irreversible boundary or a value threshold and it pauses for a human. That refusal is the contract, not the cleanup.

Write-ahead log

Intent is durable before the effect.

A tiered WAL fsyncs the plan for money-path steps and rides a lock-free fast path for the rest. Optional BYOK at-rest encryption; a configurable backpressure policy that never silently drops a record.

Recovery daemon

A crash mid-saga isn't an orphan.

If the process dies after a charge but before the rollback, an independent daemon reads the WAL, runs the compensations by name, and fails closed to a human queue for anything it can't resolve with certainty — no double refunds.

The wedge

The agent chose the action. So the inverse is derived at runtime.

Durable-workflow engines make a developer declare each compensating step at authoring time. But an LLM picks the tool, and its arguments, while it runs — the refund can't be known until the charge returns its id. SagaOps derives the compensating action from the forward call's actual result. That's the part a statically declared workflow can't express.

Batteries, not lock-in

Wraps the tools your agents already call.

Connectors compensable

Stripe (idempotent refunds), Postgres (full CRUD, compound keys, concurrency-guarded restore), Salesforce (field-scoped revert).

Framework adapters

LangGraph, CrewAI, and the OpenAI Agents SDK — wrap a tool, keep its name and schema, and it records on the active saga.

Snapshot capture

In-process reversible state and durable, crash-recoverable file snapshots — with a conservative store GC that never reaps what a rollback still needs.

Time-travel debugger

A zero-dependency WAL viewer: every saga, every step, latency, and what could not be undone — secrets scrubbed on read.

Credential-safe by design

Compensations carry credential references, never values. An authoring-time guard refuses a secret before it can reach the log.

Zero-dependency core

pip install and go. No broker, no Redis, no service to stand up. Extras are opt-in, per connector.

176
tests, pytest-only core
3
compensation semantics
0
core dependencies
LIFO
deterministic rollback

Deploy agents you can actually roll back

Start in one line.

$pip install agent-saga