Podcast trailer: redo one part with previous_run_id, not a full rerun

Fix one weak scene in a podcast trailer by continuing the Format run with previous_run_id, so the agent keeps the rest. Rules, refusals and cost.

5 min readSume
All posts

To change one part of a podcast trailer without paying for a full rerun, send a new Format run with previous_run_id set to the finished run. The Format API treats that as one more turn of the same conversation: Sume replays what the agent produced, so the agent can redo the weak scene and keep the others as they were. The new run has its own id, receipt, spend cap and single webhook.

First run, then continuation

The first call creates the trailer. Which Format you use is your choice; sume-video-hook below is a slug the catalog lists at the sume handle, and you should read it with GET /v1/formats/sume/sume-video-hook before relying on its input shape. The episode_url is a placeholder.

import json, os, urllib.request

def post_run(body, key):
    req = urllib.request.Request(
        "https://api.sume.com/v1/formats/sume/sume-video-hook/runs",
        data=json.dumps(body).encode(),
        headers={"Authorization": "Bearer " + os.environ["SUME_API_KEY"],
                 "Content-Type": "application/json", "Idempotency-Key": key},
        method="POST",
    )
    with urllib.request.urlopen(req) as r:
        return json.load(r)["data"]

first = post_run({"instruction": "30 second podcast trailer from this episode.",
                  "input": {"episode_url": "https://example.com/ep/42"}}, "ep42-trailer-v1")
print(first["id"], first["status"])

The continuation request

After the first run is terminal, post to the same Format with previous_run_id, an instruction that names only the change, and a fresh Idempotency-Key. Bind the same output_schema and primary_output_key again: they are per run and are not inherited. Name the run id, not a thread id; a thread id returns 400 unknown_parameter.

  • Instruction example: "Redo the second clip with a calmer opening line. Keep every other clip and the audio unchanged."
  • Use a new key such as ep42-trailer-v2. Reusing ep42-trailer-v1 with a changed body is 409 idempotency_conflict.
  • Set a smaller generation_spend_cap_usd than the first run, because the work is a fraction of it.

When the API refuses

The previous run must be continuable: thread_id is not null, and the run is completed or has at least one artifact. A failed run that left media can be continued.

Continuation refusals from the Runs and results docs, as of 2026-10-09
Status and codeMeaningWhat to do
404 previous_run_not_foundUnknown id, or another owner's runCheck the id and the key
400 previous_run_format_mismatchThe run started on another FormatContinue on the original Format
409 previous_run_not_terminalThe run is still goingPoll, then call again
400 previous_run_not_resumableNo thread, or nothing completedStart a new run

What it costs

artifacts[] on a continued run lists all the media the whole conversation made, but usage stays per run. So the receipt of the continuation shows only the spend of that turn against its own cap.

Planning a podcast season

For a season of episodes, give every episode its own base key, such as ep42-trailer-v1, and bump the suffix for each continuation. Store three values in your database for each trailer: the episode id, the latest run id and the key. The next continuation needs the run id of the last good run, and the receipt shows previous_run_id so you can walk back the chain.

One caution: a continuation is a new agent turn, so it can change more than you named. Tell it what to keep, as in the example, and check the new receipt's artifacts against the old ones. If the result is worse, you still have the original run, because a continuation never changes it. Cancel a continuation that you started by mistake with its own cancel_url; you pay only for the generation it completed.

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume