Skip to content

Action ledger

Agents retry. Processes crash. Without care, that means two Slack posts, two issues or two comments. Every tool call in Azhi passes through the gateway, which keeps an action ledger.

Each external write is a logical action with a stable id derived from the run, node, tool, the intended operation and an ordinal. A retry of the same operation computes the same id, so it finds the earlier action instead of creating a second one. Changing the operation produces a new id.

planned → dispatched → confirmed
↘ failed (the target definitely did not apply it)
↘ outcome_unknown (we cannot tell)

Every transition is recorded and fenced by the attempt generation: a stale attempt can never commit after a newer one took over.

Effect classes decide what recovery may do

Section titled “Effect classes decide what recovery may do”

If a previous attempt ended after sending but before recording a receipt, the action becomes outcome_unknown. What happens next depends on the tool’s declared effect class.

Effect classRecovery
write-idempotentResend with the same idempotency key
write-dedupableLook the write up on the target by its dedupe key. If it is found, mark it confirmed and reuse the receipt. If not, resend
write-unsafeStop. An operator must reconcile it before any retry. Azhi does not guess

For Slack, that lookup is how a fresh gateway finds the message a crashed one had already posted.

The alpha demo kills the gateway right after Slack accepted the post. A fresh gateway finds the message by its dedupe key. Exactly one message exists, and the ledger line shows how.

Terminal window
npm run demo # check 4: crash mid-post
npx azhi inspect <run> # state, flags, attempts, approvals, usage, context manifests and the ledger

The test suite injects crashes at named points (after planned, after dispatched, after sent) by killing the process, the same as a power loss.

  • Loops: each iteration has its own ledger ordinal, so writes inside a loop are deduplicated per iteration.
  • Sticky comments: the PR review tool is registered with a sticky marker, so a later run edits the earlier review comment instead of adding another.
  • Alerts: writes left in outcome_unknown raise an alert in Mission Control.
  • Test runs: azhi test-node mocks writes, so nothing reaches the ledger.