Deduplex

Your code will retry things. Deduplex makes sure a retried charge, email, or API call only happens once.

10,000 protected calls a month free. No charge until you're over that.

What it does

A retry should never mean a repeat.

Networks time out. Agents retry. Webhooks get delivered twice. Every one of those is a chance to charge a customer twice, send the same email again, or run a side effect you can't undo.

Deduplex sits in front of the call. It gives each action a key built from its inputs, remembers which keys it has already run, and when the same one shows up again it hands back the original result instead of doing the work a second time.

You wrap the call

One decorator on the function that does something real — charge, send, create. Nothing else in your code changes.

Deduplex keeps the ledger

Every attempt is recorded once, in a tamper-evident log, whether it ran or was caught as a repeat.

Retries come back safe

The second call with the same inputs gets the first call's answer. No double charge, no second email.

incoming

charge(cust_42, $19.99)

deduplex

key seen before?

outcome

run once · repeats return the same result

How you add it

Three steps, about a minute.

  1. Get a key

    Sign up below. Your key is generated as soon as checkout finishes — the free tier covers 10,000 calls a month.

  2. Install

    pip install deduplex or npm install deduplex, whichever matches your stack.

  3. Wrap the calls that shouldn't run twice

    One decorator per function. Or, if you're on LangChain or CrewAI, one line for the whole tool list.

Python — one decorator

from deduplex import Guard, derive_key, guard

g = Guard()

# a retry with the same customer + amount returns the
# first result instead of charging again
@guard(key=lambda customer_id, amount: derive_key(customer_id, amount, namespace="charge"), guard_instance=g)
def charge_customer(customer_id, amount):
    return stripe.charges.create(customer=customer_id, amount=amount)

LangChain / CrewAI — one line for every tool

from deduplex.integrations.langchain import guard_tools

tools = guard_tools([send_invoice, lookup_customer, refund_charge], g)
agent_executor = AgentExecutor(agent=agent, tools=tools)

Not sure which calls need it? Run the scanner on your repo — it lists the lines that charge, send, or post something and aren't protected yet. It only reads; you decide what to change.

pip install deduplex && deduplex init

See it happen

Same charge, sent three times.

This runs in your browser — no account, nothing real is charged. It's the exact scenario Deduplex exists for: a call succeeds, the caller doesn't hear back in time, and retries.

Why it holds up

Built for the messy parts.

Works under anything that retries

LangChain, CrewAI, a plain function-calling loop, a webhook handler, a cron job. It wraps the call, not the caller.

Handles real concurrency

Two callers hitting the same key at the same instant get a clear in-progress signal or can wait for the result — never a silent double run.

An audit trail you can prove

Every attempt, block, and completion is hash-chained and independently verifiable. Export it for a compliance review, not just a log table.

Pricing

Start free. Pay for what you protect.

Free

$0

Up to 10,000 protected calls a month.

  • Python and Node SDKs
  • Hosted key store and audit log
  • Dashboard and live event feed

Card required. No charge until you're over the free tier.

Pro

~$0.005 per call

Usage-based above the free tier. Same signup — it upgrades on its own.

  • Everything in Free
  • Metered billing, no plan to pick
  • Slack and webhook alerts on blocked duplicates

Self-hosted

Talk to us

Run it inside your own VPC for compliance or data-residency needs.

  • Single docker run deploy
  • Your Postgres, your network
  • Audit-grade exports