Idempotency
POST /v1/debates requires an Idempotency-Key header. The server uses it to guarantee that retrying a request never starts a duplicate debate.
The rule
If two requests arrive with the same Idempotency-Key, the second request returns the original session instead of starting a new debate, regardless of what the second body says.
This applies to both:
- Server-side retries, where your client resends after a network error
- App-level retries, where your code re-runs the request after a crash
The server ignores the body of the second request once it recognizes the key. The first request wins. If you want a different debate, use a different key.
Without idempotency keys, a network blip during POST /v1/debates would be ambiguous. Did the debate start or not? Retrying the request without a key would risk creating two debates, double-charging your budget. The key makes the retry safe.
What "the same key" means
The server matches the key as a string, byte-for-byte and case-sensitive. "abc" and "ABC" are different keys. "abc" and "abc " are also different keys, the second with a trailing space.
The server scopes keys to your API key. Two different API keys can both use "foo" as their idempotency key without conflict.
Keys live forever until your API key is revoked. You can't reuse a key for a new debate against a different prompt, even weeks later.
Recommended key generation
Three common patterns, in order of preference:
1. UUID per attempt, most flexible
import { randomUUID } from "node:crypto";
const key = randomUUID();
import uuid
key = str(uuid.uuid4())
This makes every attempt unique, which means a real retry will start a new debate. Use this if your prompt is meant to produce a unique debate every time.
2. Hash of the canonical request, deduped by content
import { createHash } from "node:crypto";
const canonical = JSON.stringify({
prompt: "Refactor this React component",
assemblyId: "9fa4f385-…",
});
const key = createHash("sha256").update(canonical).digest("hex");
import hashlib, json
canonical = json.dumps({
"prompt": "Refactor this React component",
"assemblyId": "9fa4f385-…",
}, sort_keys=True)
key = hashlib.sha256(canonical.encode()).hexdigest()
This dedups by content. Sending the same prompt against the same assembly always returns the same session, no matter how many times you retry. Use this if you want one debate per unique prompt and zero risk of duplicate charges.
3. UUID per logical attempt, persisted client-side
Generate a UUID at the start of a high-level operation, persist it in a database or file, and reuse it across all retries of that operation. When the operation succeeds, mark it done. This is the safest pattern for production agents and CI jobs.
What you see on retry
If you send the same Idempotency-Key twice, the second response matches the first. It carries the same id and status. The server starts no new debate and charges your budget only once. The original session keeps running to completion in the background.
HTTP/1.1 202 Accepted
Content-Type: application/json
{
"id": "efb4097e-e58c-49b7-885d-860753a0d7ed",
"status": "queued"
}
HTTP/1.1 202 Accepted
Content-Type: application/json
{
"id": "efb4097e-e58c-49b7-885d-860753a0d7ed",
"status": "RUNNING",
"message": "Returned cached session via idempotency key."
}
Note the message field. Its presence confirms that a dedup happened.
Edge cases
- Different body, same key. The server returns the original session and ignores the body. If you really want a different debate, use a different key.
- Original failed, same key retried. The server returns the failed session with
status: "FAILED". Treat the key as consumed and try again with a new key. - Two simultaneous requests with the same key. The server handles this atomically. One wins, the other gets the cached response.
When the original key is lost
If you forgot the key you used, or want to start a fresh debate with a slightly different prompt, use a new key. You don't need to remember keys. Make each key unique per attempt.
