Get started
Five minutes, start to finish
No SDK to install, no rewrite. Two calls wrapped around something you already do.
1. Get a key
Free, no card. One request, or use the console.
2. Connect your agent
Pick the one that matches your setup.
3. Wrap one action
Start with a single high-stakes effect — the one that would hurt if it happened twice. Prove it there before spreading it around.
Tips that save real pain
Derive keys from the work
The idempotency key is the whole mechanism. It must be identical on a retry of the same logical action.
- invoice:2026-08:acct_88
- uuid4()
- "send-" + Date.now()
Report failed only when you're sure
Only when the action provably never reached the outside world. On a
timeout, report nothing — the lease lapses into an honest
indeterminate. A false failed is worse than silence, because
it licenses a duplicate.
Set the lease to the real duration
A 60s lease on a 5-minute job means the effect goes indeterminate while it is still running. Match the lease to how long the action actually takes, plus headroom.
Decide fail-open vs fail-closed first
Ratchet is in your critical path. Decide before integrating what your agent does when it is unreachable — the contract spells out both.
Put block on anything irreversible
It is the default for a reason. Only choose retry when
the vendor genuinely deduplicates, and probe when a human must verify
first.
Group multi-step work
Pass group_key and declare each step's
compensation while you still know what undoing means. It cannot be worked
out later from a log.
When something looks wrong
| What you see | What it means | What to do |
|---|---|---|
in_flight forever | A holder crashed and the lease has not lapsed yet. | Wait for retry_after_seconds. It becomes indeterminate on its own. |
idempotency_key_reuse | Same key, different payload — usually a key built from unstable data. | Make the key deterministic, or genuinely distinct per action. |
blocked repeatedly | A prior attempt's outcome is unknown and policy forbids guessing. | Check the vendor, then POST /effects/{id}/resolve with evidence. |
lease_lost on report | Your lease was superseded — you took too long. | Do not assume your work counted. Re-run begin to learn the truth. |
402 insufficient_credit | Allowance exhausted and no prepaid credit. | Existing effects still replay. Add credit or upgrade. |
429 rate_limited | Over your plan's per-minute limit. | Back off by detail.retry_after_seconds. |