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
- YouTube 16:9 resolutions 240p to 8K and what Timeline renders
YouTube lists eight 16:9 resolutions from 426x240 to 7680x4320. Sume Timeline renders four of them: 1080p, 720p, 480p and 360p. Why the other four fall outside.
- YouTube audio: AAC-LC, Opus or Eclipsa, and what a Sume export carries
YouTube's upload settings name AAC-LC, Opus and Eclipsa Audio at 48 kHz stereo. Read audio_codec, channels and sample rate from video inspect before you upload.
- YouTube 'Info from' under an AI label: what the signing authority is
The 'Info from' line under a YouTube AI disclosure names who signed the Content Credentials. Which labels carry it, and what a Sume export does not add.
- YouTube Live 1080p30 H.264 bitrate: 5 to 14 Mbps, GB per hour
YouTube Live recommends 5 to 14 Mbps for 1080p30 H.264, with 2 B-frames and a 2-second keyframe. The gigabytes per hour for each rung, and what Sume cannot set.
Written by Sume