Skip to main content

exactly-once

Idempotency middleware for agent side-effects

The primitive agent frameworks forgot. Wrap any tool call that must never fire twice — a payment, an email, an onchain transaction — and exactly-once guarantees it runs a single time, even across retries, crashes, and replays.

See it prevent a double-charge in one command:
python examples/crash_mid_payment.py — an agent crashes mid-payment, resumes, and does not double-charge (with vs without).

v0.1 — zero-LLM, tiny surface, drop-in.


Why

Agents retry. They crash and resume. They get replayed during debugging. Every one of those can fire a side-effect twice — a card charged twice, an email sent twice, a transaction submitted twice. In systems that touch money, duplicate side-effects are the difference between a bug and a lawsuit. Frameworks give you retries and checkpoints but not idempotency for the effects those retries cause.

Install

pip install exactly-once            # core, zero heavy deps
pip install "exactly-once[redis]"   # + Redis store   (also: [postgres])

Quickstart

from exactly_once import once, Store, current_key

store = Store.sqlite("effects.db")   # or .memory() / .redis(url) / .postgres(dsn)

@once(store, key=lambda order, **_: f"charge:{order.id}")
def charge_card(order):
    # pass our key through as Stripe's own idempotency key — belt and suspenders
    return stripe.charge(order.customer, order.amount, idempotency_key=current_key())

charge_card(order)   # runs the charge
charge_card(order)   # replays the stored result — Stripe is NOT called again

# context-manager form for an inline effect
with once(store, key="send-welcome:user-4471") as guard:
    if guard.fresh:
        guard.result = send_email(...)        # skipped on any replay

⚠️ Key on stable business identity (order_id), never on a mutable value like amount — two distinct $50 charges must not collapse into one.

See it prevent a double-charge in 15 seconds:

python examples/crash_mid_payment.py    # agent crashes mid-payment, with vs without

More runnable examples in examples/.

The guarantee (honestly scoped)

Classic idempotency-key pattern adapted for agents: compute a stable key → atomically check-and-claim → if committed, return the stored result without re-running; if in-flight, block/deny per policy; if new, run and commit. On a crash mid-effect the key is left in-flight and quarantined — a half-completed payment must never silently re-fire. Single-writer semantics are strong; multi-writer needs a real transactional store (documented, not overpromised).

Pluggable stores: memory · SQLite · Redis · Postgres. An onchain adapter (dedupe by nonce + calldata-hash) is planned for v0.2. See SPEC.md and ROADMAP.md.

What it guarantees — and what it doesn't

Guarantees (given a store with an atomic claim): the effect is entered at most once per key across retries, concurrent workers, crashes, and replays; after a commit every later call replays the stored result; a concurrent second caller never runs in parallel; a crash mid-effect never auto-re-fires.

Does not: it is exactly-once effect (at-most-once execution + replay-on-success), not exactly-once delivery — that's impossible (Two Generals / FLP). It can't know the outcome of a crash-mid-effect; it refuses to guess (quarantine) and lets a prober or a provider idempotency key narrow the window. It's only as strong as the store you pick:

Store Guarantee Use for
memory strong within one process tests, dev
SQLite strong on one host single-node agents, jobs, CI
Redis strong single-instance, best-effort under failover distributed workers, one Redis
Postgres SERIALIZABLE true multi-writer, linearizable multi-host production

Full boundary in docs/ARCHITECTURE.md §9.

Development

uv venv --python 3.11 && uv pip install -e ".[dev]"
uv run pytest                              # full suite (Redis/Postgres tests need Docker)
uv run mypy src/exactly_once               # strict typing
uv run ruff check src tests examples       # lint
uv run python scripts/check_docs_honesty.py  # the docs-honesty gate
uv run python scripts/benchmark.py           # per-call overhead (NFR-8)

Overhead per guarded call is one store round-trip plus key/codec work — a few microseconds on the in-memory store; real deployments are dominated by the store's own latency.

Part of the Swarm Proof toolkit

Trust infrastructure for the agent economy — seven projects, one thesis.

Project What it does
stampede Point a herd of realistic agents at your system before real ones arrive
mockworld A synthetic internet for agents — fake Stripe, Gmail, exchange, instantly
mcp-probe The CI quality suite for MCP servers — lint, contract-test, benchmark, load
costbomb Denial-of-wallet fuzzing — find the inputs that make your agent spend $500
exactly-onceyou are here Idempotency middleware so agent side-effects fire once
agent-postmortems A structured incident database + post-mortem standard for agent failures
awesome-agent-reliability The curated map of the field

License

MIT. No LLM anywhere — it's plumbing. Citable via CITATION.cff.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

exactly_once-0.2.0.tar.gz (97.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

exactly_once-0.2.0-py3-none-any.whl (40.4 kB view details)

Uploaded Python 3

File details

Details for the file exactly_once-0.2.0.tar.gz.

File metadata

  • Download URL: exactly_once-0.2.0.tar.gz
  • Upload date:
  • Size: 97.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for exactly_once-0.2.0.tar.gz
Algorithm Hash digest
SHA256 a96259f9dc8b92992cd108e056366d78f0f66e7d4fd7bfcf2c4b3973264cc373
MD5 2207fe70811d5d2ca6006e020bdde608
BLAKE2b-256 48c98dd626107d0a223b42c2728584d00c6f862d8216a134e6eda3196ee15982

See more details on using hashes here.

Provenance

The following attestation bundles were made for exactly_once-0.2.0.tar.gz:

Publisher: release.yml on swarmproof/exactly-once

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file exactly_once-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: exactly_once-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 40.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for exactly_once-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 231f016c3f48d378afb59d522e193d6c02a52369333398db6ebc9215ce7f1af4
MD5 994f28c78f8cd03e49d172b0044e3e92
BLAKE2b-256 9bbd19d0c23fc65fd43d7b9c9f17b55951d1aff291133d902f95e5a2ebb426e0

See more details on using hashes here.

Provenance

The following attestation bundles were made for exactly_once-0.2.0-py3-none-any.whl:

Publisher: release.yml on swarmproof/exactly-once

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.1

2 files

This release

0.2.0 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page