Skip to content

Start runs safely

When a program starts runs, the same request can arrive twice: a retry after a timeout, a webhook delivered again, a script run a second time. This guide shows how to make sure one piece of work gets one run, how to start a fresh run on purpose, and how to start many runs at once.

You need a registered workflow and a way to call Realm’s tools, such as an MCP client.

Pass an idempotency_key to start_run. Choose a value that names the piece of work, such as an order number:

{ "workflow_id": "sync", "params": {}, "idempotency_key": "order-4417" }

The first call starts a run:

status: ok
deduped: false
run_id: 6c48086c-cb0f-47ea-9c33-6279fe42ffdc

A second call with the same key, for the same workflow, starts nothing. It returns the run that already exists:

status: ok
deduped: true
run_id: 6c48086c-cb0f-47ea-9c33-6279fe42ffdc
Matched existing run '6c48086c-cb0f-47ea-9c33-6279fe42ffdc' (idempotent) in phase 'running'; no new run created. Ready for the agent: 'fetch'.

Notice deduped: true and the same run_id. The caller can carry on with that run as if it had started it: the reply also says what comes next for it, as the first one did (here, sync’s first step, fetch, is ready for the assistant). Saying what comes next on a repeat was added after version 0.46.0, which ends the line at no new run created..

A key belongs to one workflow. The same key under another workflow is a different key.

What should happen on a repeat depends on whether the first run is still going. Two settings control it.

While the first run is still open: on_live_match

Section titled “While the first run is still open: on_live_match”
Value A repeat
use_existing Returns the open run. This is the default.
fail Is refused.

With fail:

status: error
STATE_RUN_ALREADY_ACTIVE: Idempotency key for workflow 'sync' is owned by an active run '6c48086c-…' (phase 'running').

Use fail when a second caller must not join work that someone else is already doing.

After the first run has ended: on_terminal_match

Section titled “After the first run has ended: on_terminal_match”
Value A repeat
reuse Returns the finished run. This is the default.
reject Is refused with STATE_IDEMPOTENCY_KEY_USED.
rerun_if_failed Starts a new run if the first one failed; otherwise returns the first.
rerun Always starts a new run.

With rerun after a completed run, a new run starts and says which run it replaces:

status: ok
deduped: false
run_id: 3fa445f0-6a22-424b-9a64-8a866925039a
rerun_of: 6c48086c-cb0f-47ea-9c33-6279fe42ffdc
Run '3fa445f0-…' created for workflow 'sync'; it supersedes run '6c48086c-…' under the same idempotency key (on_terminal_match). Ready for the agent: 'fetch'.

The key now points at the new run. The old run stays in the store, and the new run’s record links back to it:

Rerun of: 6c48086c-cb0f-47ea-9c33-6279fe42ffdc

rerun_if_failed is the usual choice for work that should be tried again after a failure but never done twice. After a run that failed, it started a new one; after a run that completed, it returned the completed run.

start_run_batch starts several runs of one workflow in one call. Give each item its parameters and, if you want, its own key:

{
"workflow_id": "sync",
"items": [
{ "params": {}, "idempotency_key": "order-21" },
{ "params": {}, "idempotency_key": "order-22" },
{ "params": {}, "idempotency_key": "order-4417" }
]
}

The reply lists one entry per item. Items whose key already has a run are returned as deduped:

order-21 run baf9ec57-… deduped: false
order-22 run cdb126b5-… deduped: false
order-4417 run 3fa445f0-… deduped: true

The whole batch is checked before any run is created. If one item’s parameters do not fit the workflow’s params_schema, nothing starts:

status: error
VALIDATION_BATCH_ITEMS: start_run_batch: 1 item(s) failed schema validation
One or more items failed schema validation. No runs were created.

start_run_batch takes the same on_live_match and on_terminal_match settings, applied to every item.

realm listen does this for you. A workflow’s trigger names where the event’s ID is in the request, and a repeated delivery starts no second run. See Start runs from webhooks.

realm run reconcile --dry-run reports the keys in use, and the keys that have more than one run:

Would write 0 pointer(s) across 4 key group(s); 4 already current.
Duplicate-key groups: 2
- workflow 'sync' → canonical 3fa445f0-…; other runs: 6c48086c-…

A key with more than one run is normal after a rerun: the newest run is the one the key points at.