On Runtime, every write carries an idempotency key. Both SDKs create one for you and retry with it. A create whose reply was lost never makes a second sandbox, and a retried command never runs twice (errors and retries). The server keeps each key for 24 hours.
Why it matters for AI agents
Networks drop replies. When a create request times out, the client cannot tell
whether the server never received it or completed it and the reply was lost. A
retry without a key may start a second machine, which is billed and forgotten. A
retried exec may run git push or a payment call a second time.
Agents make this worse. They retry by design, often from a new process after a crash. An MCP client may repeat a tool call that it believes failed. An idempotency key turns "did that happen?" into a question that the server answers.
How Runtime treats a key
| Request | What the server does |
|---|---|
| Same key, same body | Returns the first result again, with "replayed": true |
| Same key, different body | Returns 422 idempotency_key_reused |
| New key | Treats the request as new work |
| Header | Idempotency-Key: <any unique string>; a replay adds Idempotency-Replayed: true |
| How long a key is kept | 24 hours |
| What the SDKs retry with the key | Transport failures, 429, 502, 503 and 504, with a growing delay |
A failed fork is final. A retry with the same key returns the same error. To try again, fork with a new key (API).
Survive a process restart
The key that the SDK creates lasts only as long as the call. To make a retry safe after your own process stops, derive the key from the job. The next attempt then sends the same key.
This demonstration chooses a new job ID once. A restarted worker loads the saved ID from its queue, and it keeps both that ID and the input unchanged. Never choose a new job ID inside a retry loop.
TypeScriptimport { randomUUID } from "node:crypto";import { Runtime } from "withruntime";const runtime = new Runtime();const job = randomUUID();const input = { labels: { job } };await using sbx = await runtime.sandboxes.create(input, { idempotencyKey: `create-${job}` });console.log(sbx.id); // a retry within 24 hours answers this same sandboxSend the same body on the retry. If you change the input under the same key, the request is not a retry, and the server returns an error to say so.
Keys over MCP
An agent that calls Runtime's MCP tools directly should choose and record a
unique idempotencyKey before the first call. After a lost reply, it should
reuse that key with identical input. The server generates a key for an omitted
field, and that key cannot be recovered from a lost reply. Read the resource
before you repeat that write (MCP).
When a command's outcome is still unknown after a timeout, inspect its files and processes before you repeat a side effect (troubleshooting).
Related
- What is an agent loop?
- What is tool calling?
- API errors and retries
- How to choose a sandbox for AI agents
Facts on this page were checked on 25 October 2026.