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.
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
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.
One decorator on the function that does something real — charge, send, create. Nothing else in your code changes.
Every attempt is recorded once, in a tamper-evident log, whether it ran or was caught as a repeat.
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
Sign up below. Your key is generated as soon as checkout finishes — the free tier covers 10,000 calls a month.
pip install deduplex or npm install deduplex, whichever matches your stack.
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
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
LangChain, CrewAI, a plain function-calling loop, a webhook handler, a cron job. It wraps the call, not the caller.
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.
Every attempt, block, and completion is hash-chained and independently verifiable. Export it for a compliance review, not just a log table.
Pricing
$0
Up to 10,000 protected calls a month.
Card required. No charge until you're over the free tier.
~$0.005 per call
Usage-based above the free tier. Same signup — it upgrades on its own.
Talk to us
Run it inside your own VPC for compliance or data-residency needs.
docker run deploy