Retry only the missing ad variants with previous_run_id on a Format
When a variants run returns some clips as null, continue it with previous_run_id and name the missing slots, so you do not pay for the finished variants again.

To redo only the ad variants that came back empty, send a new run to the same Format with previous_run_id set to the earlier run and an instruction that names the missing slots. Sume replays what the agent produced, so the finished variants stay as they are. Bind the same output_schema again, because it is not inherited.
Start from the partial receipt
This follows the variants schema where each video_url is nullable. A run that makes three of five clips still satisfies the schema, so you get the three and a clear list of which two are null.
What can be continued
A run can be continued only if its receipt shows a thread_id and either completed status or a non-empty artifacts[]. A failed run that left work is fine, and a run that left nothing is not. A continuation is a new run with a new id, its own spend cap and its own single webhook, and the original never changes. The two share a thread_id, which you cannot pass yourself.
| Response | Meaning | Do |
|---|---|---|
| 404 previous_run_not_found | Unknown id or another owner | Check the run id and key |
| 400 previous_run_format_mismatch | Run started on another Format | Call the original Format |
| 409 previous_run_not_terminal | Still running | Poll, then retry |
| 400 previous_run_not_resumable | No thread or nothing made | Start a new run |
Find the gaps and continue
The script reads the earlier receipt, finds variants whose video_url is null, and starts the continuation with an Idempotency-Key that ends in a retry counter. Bump the counter only when you really want another attempt. A replayed key with the same body returns the same run with no second charge.
import json, os, urllib.request
API = "https://api.sume.com"
SCHEMA = json.load(open("variants-schema.json"))
def call(method, path, body=None, key=None):
h = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"],
"Content-Type": "application/json"}
if key:
h["Idempotency-Key"] = key
data = json.dumps(body).encode() if body else None
with urllib.request.urlopen(urllib.request.Request(API + path, data, h, method=method)) as r:
return json.load(r)["data"]
def main():
run_id = os.environ["RUN_ID"]
prev = call("GET", "/v1/format-runs/" + run_id)
out = prev["output"] or {"variants": []}
gaps = [i + 1 for i, v in enumerate(out["variants"]) if v["video_url"] is None]
if not gaps:
return print("nothing missing")
body = {"previous_run_id": run_id, "generation_spend_cap_usd": 10,
"instruction": "Redo only variants " + str(gaps) + ". Keep the others unchanged.",
"output_schema": {"name": "acme/ad-variants/v1", "strict": True, "schema": SCHEMA}}
new = call("POST", "/v1/formats/sume/sume-product-commercial/runs", body, run_id + "-retry-1")
print(new["id"], new["status"])
main()Two things to remember
Save the schema from the first run to variants-schema.json so both calls send the same contract. If output was null on the first run, read artifacts[] instead and list the gaps by hand, since there is no typed list to scan. The continued run's artifacts[] lists all media of the whole conversation, but usage stays per run, so add the two runs when you book spend.
Sources
Related posts
More in Formats
- Retry two scenes in one Format run: scene_ids with previous_run_id
Continue the thread with previous_run_id and put scene_ids in input to redo two clips in one run. Voice and other clips stay; send a cap.
- Revoke a Format grant: in-flight runs finish, new calls fail closed
DELETE .../grants/{workspace} revokes a pending or accepted grant. The grantee's running runs finish, and every new list, read or invoke fails closed at once.
- Route tickets with Clef, then pick a Sume Format by its io profile
Clef routes a ticket by team and urgency. Then read GET /v1/formats/{handle}/{slug} for io.input_kind before you call POST .../runs. A short Python router.
- One Idempotency-Key, two Sume Formats: you start two runs
A Sume idempotency key is scoped to one Format, so one key sent to two Formats starts two paid runs. Build keys from order, Format and version.
Written by Sume