Workflow DevKit replays: a stable Idempotency-Key for Sume submits
Workflow DevKit 4.8.12 fixed replay clock tracking. A replayed step must send the same Sume Idempotency-Key, so derive it from the run id, not Date.now.

Workflow DevKit v4.8.12, dated October 2, 2026, fixed deterministic clock tracking where concurrent replays called Date.now with different amounts of events read from the log. The same lesson applies to Sume submits: a step that is replayed must send the same Idempotency-Key each time. Build the key from the workflow run id and step name, never from Date.now.
What the release says
From the Vercel release updates page, read on 2026-10-03: the release fixed deterministic clock tracking, and correlation IDs are preserved across concurrent step replays. See the release for the details of the fix.
Why replay and billing meet
A durable workflow re-runs code from its log. If a step submits a paid job and the process dies before the result is recorded, the step runs again. With a key derived from the clock or a random value, the second run looks like a new request and can create a second paid job.
What Sume guarantees with a key
Sume's docs say to send Idempotency-Key on submit requests when retrying after a client-side timeout or network failure, to reuse the same key only for the same operation and payload, and that a retried submit with the same key returns the original job. A client timeout does not cancel the job, which keeps running and billing.
| Key derived from | Replay-safe? | Why |
|---|---|---|
| Workflow run id plus step name | Yes | Identical on every replay |
| Date.now() | No | Differs between replays |
| Random UUID in step body | No | New on every execution |
| Random UUID stored by a previous step | Yes | Replays return the logged value |
A stable key in code
Pass the run id in from the workflow context and add a step label, plus a version if the payload changes.
async function submitScene(runId: string, scene: number, prompt: string) {
const res = await fetch("https://api.sume.com/v1/videos", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SUME_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": `${runId}:scene-${scene}:v1`,
},
body: JSON.stringify({ model: "sume/auto", prompt }),
});
if (!res.ok) throw new Error(`submit failed: ${res.status}`);
return (await res.json()).id as string;
}Change the key when the payload changes
If you edit the prompt, bump the version in the key. Reusing a key for a different payload is outside what the docs promise. Store the returned job id in the workflow state and poll it, rather than submitting again.
Sources
Related posts
More in Developers
- Which MCP server lets Claude Code or Cursor generate video and images?
MCP servers that let Claude Code and Cursor make video and images: Sume, fal, Replicate, Runway, Higgsfield. Endpoints, sign-in, billing, setup.
- Idempotency keys for AI video APIs: retry without paying twice
An idempotency key makes a retried create return the original run or job instead of a second paid one. How Sume's Idempotency-Key works on each API.
- Signed webhooks for Sume video runs: events, retries, verification
Sume sends one HMAC-SHA256 signed POST when a Format, Action, or Agent Completion run completes or fails. Verify the raw body and dedupe on request_id.
- Spend caps for unattended AI agents: how Sume bounds each run
An unattended agent has no one to approve spend, so Sume caps generation per run: required on Agent Completions, and up to $500 on Format runs.
Written by Sume