Agent Completion webhook retries: 10 attempts over about 3 hours

Sume tries an agent.run.terminal webhook up to 10 times. By the documented formula the nine waits add up to about 3 h 3 min, before jitter and Retry-After.

5 min readSume
All posts

If your endpoint keeps failing, Sume stops after 10 attempts, and by the documented backoff formula the nine waits between them add up to roughly 3 hours 3 minutes. That is before jitter and before any Retry-After header your endpoint sends, so treat it as an estimate. After the tenth attempt the run's webhook_delivery.status becomes exhausted, but the run itself stays completed or failed, and you can still fetch it from result_url.

The page's formula is min(max(30s x 2^(attempt-1) with jitter, Retry-After), 1h). Each attempt has a 10-second timeout, a 2xx is success, and a 3xx counts as a failed attempt because Sume does not follow redirects.

The schedule, computed

I read the formula as the wait after attempt k, with the cap at 3,600 seconds. Jitter and Retry-After are left out.

Nine waits between ten attempts, computed from the formula read 2026-10-09
After attempt30 x 2^(k-1) sCapped wait (s)
13030
26060
3120120
4240240
5480480
6960960
71,9201,920
83,8403,600
97,6803,600
def waits(attempts=10, base=30, cap=3600):
    return [min(base * 2 ** (k - 1), cap) for k in range(1, attempts)]

total = sum(waits())
print(waits())
print(total, divmod(total, 3600), total / 3600)
# 11010 seconds = 3 h 3 min 30 s

What to build around it

Sum of the nine waits: 30 + 60 + 120 + 240 + 480 + 960 + 1,920 + 3,600 + 3,600 = 11,010 seconds, or 3 hours 3 minutes 30 seconds.

  • Record the event durably, return 2xx quickly, and process afterward. A slow handler burns the 10-second budget and triggers another attempt.
  • Dedupe on the envelope's request_id, which equals the run id and is stable across retries.
  • A canceled run and a skipped run send no webhook at all, so do not wait for one.
  • If deliveries exhaust, use Redeliver on the delivery row, or fetch the receipt from result_url. Redeliver is documented for Format runs; for Agent Completions poll status_url.

Signature check, briefly

Sume signs <timestamp>.<raw_body> with HMAC-SHA256 and sends x-sume-webhook-signature: sume-v1=<hex>. Verify against the raw body before parsing, reject timestamps outside a window (five minutes is the suggested default), and refuse to run at all if your secret is empty, since an empty secret makes every signature forgeable.

Planning around the window

About three hours is the span in which your endpoint can recover and still get an automatic delivery. If your deploys or outages run longer, do not rely on the webhook alone: keep status_url polling as a backup, which the docs explicitly allow. A reconciliation job that lists recent runs and fetches any that never reported is cheap insurance, and it also covers the canceled and skipped cases that never send a webhook.

Note that a failed delivery never changes the run. The generation has already been billed against the cap, so a missed webhook costs you latency, not money.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume