Skip to content

Idempotency

View as Markdown

Networks fail. A request can time out after the server has already done the work, and a plain retry would then create a second session, a second message or a second answer. K-Agent gives you two tools to make retries safe.

Send a unique key with any POST or DELETE. If you retry with the same key, you get the stored result instead of a second action:

نافذة الطرفية
curl https://api.k-agent.kerneltics.com/v1/sessions \
-H "Authorization: Bearer $KAGENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2a0e-8d3b-4c55-9a77-1e2f3d4c5b6a" \
-d '{"agent": "store-assistant", "external_id": "order-8812", "input": "Where is my order?"}'
  • Scope. A key is scoped to your project, the credential that sent it, and the route (method and path pattern). The same key on another route is a different key.
  • Length. 1 to 255 characters (400 invalid_idempotency_key otherwise). A UUID v4 is ideal.
  • Lifetime. Results are kept for 24 hours. After that, the key can be used again.
  • Replays return the original status and body, with the header Idempotent-Replayed: true.
  • Same key, different request — another body or another path ID — returns 422 idempotency_key_reused. The comparison uses the resolved session, so addressing it by sess_… or by external_id counts as the same request.
  • Still running. If the first request hasn’t finished, a retry returns 409 idempotency_in_progress. Wait and retry with the same key.
  • Server errors are not stored. A 5xx that happens before any work started can be retried with the same key and will run again.

For ask, POST /v1/sessions with input, messages and submit_tool_outputs, the key is tied to the run as soon as it exists:

  • a retry returns the run’s current state in the endpoint’s normal response shape — if it has finished since, you get the finished run;
  • a retry of a streaming request re-attaches to that run’s stream from the start;
  • 409 idempotency_in_progress is only possible in the brief moment before the run exists.

Creating or rolling an API key, minting a client token, starting a widget session, creating a webhook endpoint or rotating its secret, and reading the tool signing secret all return a secret once. Their replays return the same resource with the secret set to null and "secret_redacted": true — the secret itself is never stored for replay.

For chat messages there is a second, simpler mechanism: give each message your own ID.

نافذة الطرفية
curl https://api.k-agent.kerneltics.com/v1/sessions/order-8812/messages \
-H "Authorization: Bearer $KAGENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input": "Thanks!", "client_message_id": "wa-msg-77121"}'
  • The same client_message_id in the same session returns the original {session, message, run} with 200 and Idempotent-Replayed: true — no second message, no second answer.
  • The same ID with different text returns 409 client_message_id_conflict.
  • It never expires while the session exists, which makes it the right tool for channels that redeliver messages hours later (webhooks from messaging platforms, mobile apps that resend after reconnecting).

Use both when you can: client_message_id to deduplicate the message itself, and Idempotency-Key to make the HTTP request safe to retry.