Idempotency
Networks are unreliable. The request goes out, the response is lost, your code retries — and the customer gets two messages. Idempotency is what blocks that.
Two layers
Section titled “Two layers”Protection works in two places, and they are different:
| Layer | What it does | Mechanism |
|---|---|---|
| Transport | Does not repeat the same request | idempotency_key |
| Semantic | Does not repeat the same intent | Operation Ledger |
What the semantic key is built from
Section titled “What the semantic key is built from”tenant_id → business_id → actor_ref → capability_id → resource_ref → business_window⚡ It uses the capability_id, not the tool name. So when the
connector changes (Bitrix24 → 1C) idempotency survives: the intent is
unchanged.
In the database this is UNIQUE (tenant_id, semantic_key) — the only real
guarantee.
Choosing a key
Section titled “Choosing a key”✅ Right
Section titled “✅ Right”# Tied to a business event — stableidempotency_key = f"order-{order_id}-confirm"Call it again for the same order and no second effect occurs.
⛔ Wrong
Section titled “⛔ Wrong”idempotency_key = str(uuid4()) # new every time → NO protectionidempotency_key = str(time.time()) # same problemA random key is equivalent to turning the protection off.
Recurring actions
Section titled “Recurring actions”Something like a daily report must repeat every day:
idempotency_key = f"daily-report-{date.today()}"This is the business_window concept: the date becomes part of the key,
so tomorrow’s run is not blocked.
Key conflicts
Section titled “Key conflicts”| Case | HTTP | Meaning |
|---|---|---|
| Same key + same body | 200 |
The existing execution is returned |
| Same key + different body | 409 |
No silent overwrite |
⚠ 409 is not an error — it is protection. It means you reused a key
for a different intent.
Duplicate intent
Section titled “Duplicate intent”If the operation already started, the connector is not called:
| Existing state | Response |
|---|---|
VERIFIED |
409 duplicate_intent_verified — already done |
| Anything else | 409 duplicate_intent — started, outcome unclear |
The distinction is deliberate: the first is success (no new effect needed), the second means “wait”.