Skip to content

Idempotency keys

An idempotency key is a 64-character hex string that uniquely identifies a verb invocation by its inputs. Re-running a verb with the same key against the same target repo is a no-op — the existing PR is returned, no second PR is opened.

SHA256(`${verb}|${target_repo}|${canonicalize(input_params)}`)
.toString("hex")

Where canonicalize recursively sorts object keys (arrays preserve order). The implementation lives at cli/src/idempotency.ts.

This means:

  • Same verb + same repo + same params → same key.
  • Reordering keys in the input JSON → same key (canonicalize sorts).
  • Adding whitespace, comments, or formatting → same key (it’s parsed JSON, not raw text).
  • Changing any param value → different key.

Every PR the verb emits embeds the idempotency key in its body’s metadata block:

petrova:
idempotency_key: 4f8c3e21d97a...
...

Before opening a new PR, the emitter searches the target repo’s open PRs for this key. A match returns status: skipped_idempotent with the existing PR’s ref. No second PR. No duplicate state.

SituationSame key?
Re-running the same verb with the same inputYes — no-op.
Re-running with a typo fix in the inputNew key — new PR.
Re-running with a property reorderedYes — canonical form is identical.
Re-running with a different actor or triggered_by.refNew key — those go into the canonical form.
Re-running after the original PR was closed/mergedSame key, but no open PR matches → new PR opens.

Agent fleets retry. CI loops fire twice. Audit checks re-run on schedule. Without idempotency, every retry would risk a duplicate PR. With idempotency, retries are mechanically safe — the fleet treats applied and skipped_idempotent identically for downstream bookkeeping.

The key is also the audit handle: given a key, you can find every PR that ever emitted from those exact inputs across history.

  • Verbs — the pipeline that generates the key.
  • Schema fingerprints — different mechanism, different purpose (contract version, not input identity).
  • PR body template — where the key lives in emitted PRs.