How tooloutbox works

The methodology behind tooloutbox: a write-ahead persist → apply → commit → reconcile lifecycle that makes tool writes crash-recoverable, at-most-once, and re-attestable offline from the log alone.

← Back to tooloutbox.dev

The lifecycle

Every tool write moves through four ordered stages. The write-ahead log is our durable state; the adapter models the external world.

  1. Persist. The intended write is written to the write-ahead log with a canonical fingerprint before the caller is acknowledged. If the process dies here, the intent survives.
  2. Apply. The adapter performs the external effect exactly once, keyed by the fingerprint so a replay cannot double-apply.
  3. Commit. The outcome is recorded against the log entry, which closes the write.
  4. Reconcile. On restart, any write that persisted but did not commit is recovered. Before retrying, the engine probes the adapter to discover whether the effect already happened, so it never blindly re-applies.

Three distinct verdicts

Reconciliation does not pretend to certainty it does not have. A recovered write resolves to one of three verdicts, and the CLI exit code matches:

At-most-once and tamper-evidence

Because the fingerprint is written before the effect and checked before any retry, a write is applied at most once across crashes. The persisted receipt store is tamper-evident: each record must still hash to its recorded fingerprint, and the whole store can be re-attested offline from the log alone — no adapter, no re-apply — with node src/cli.mjs verify.

Why “crash” is deterministic

The crash is a deterministic injected signal (afterPersist / afterApply), not a real fault. That makes the crash/restart acceptance gate reproducible in CI with no real datastore and no real fault injection, and it is proven against more than one adapter so the contract generalizes.