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.
Construction
Section titled “Construction”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.
Re-run detection
Section titled “Re-run detection”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.
When to expect a same key vs a new key
Section titled “When to expect a same key vs a new key”| Situation | Same key? |
|---|---|
| Re-running the same verb with the same input | Yes — no-op. |
| Re-running with a typo fix in the input | New key — new PR. |
| Re-running with a property reordered | Yes — canonical form is identical. |
Re-running with a different actor or triggered_by.ref | New key — those go into the canonical form. |
| Re-running after the original PR was closed/merged | Same key, but no open PR matches → new PR opens. |
Why this matters for fleets
Section titled “Why this matters for fleets”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.
See also
Section titled “See also”- 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.