mountable.io

Cookbook: refuse a stale agent edit

Two jobs read one task file. The second write sends the ETag from that read, so a newer edit stays, and the second job writes again only after it rereads.

Two agent jobs can read the same short task file. If the second job writes the whole file from the copy it remembers, the first job's change disappears and the write still succeeds.

mountable.io is a persistent filesystem for AI agents. Send the ETag from the read with the write. When the file has changed, the write is refused and the newer bytes stay. The second job reads the file again and sets only the field it owns.

This recipe uses conditional writes on the files API through the Python SDK. The second job copies the file it just read. It does not merge the two proposed copies.

mountable.io maintains this runnable example.

Setup

Use Python 3.11 or newer and uv. Set MOUNTABLE_API_KEY in your private environment or secret manager. Never put the key in a command argument. Use an existing account with a saved payment method, and a filesystem the key can access. The example creates no account, filesystem or credits.

git clone https://github.com/writeitai/mountable.git
cd mountable/examples/two-editors
uv sync --locked
export MOUNTABLE_FILESYSTEM_ID=your-filesystem-id
export RUN="demo-$(date +%s)"

RUN is 1–40 characters: a lowercase letter or digit, then letters, digits or hyphens. Use a new value each time. The task file is etag-edit-$RUN.txt. File operations use the normal usage prices.

Create version A and read it twice

uv run python edit.py seed --filesystem "$MOUNTABLE_FILESYSTEM_ID" --run "$RUN"
uv run python edit.py read --filesystem "$MOUNTABLE_FILESYSTEM_ID" --run "$RUN"
uv run python edit.py read --filesystem "$MOUNTABLE_FILESYSTEM_ID" --run "$RUN"

seed sends If-None-Match: *, so the path is created only when it is absent. A second create is refused and the existing bytes stay. Each read is its own process. Both print version A and the same ETag:

status: open
note: ready

Copy the etag= value. The commands below call it ETAG_A.

Commit one edit, and refuse the stale write

Editor one sets status to review with the ETag both jobs read:

uv run python edit.py commit --filesystem "$MOUNTABLE_FILESYSTEM_ID" --run "$RUN" --if-match "$ETAG_A" --editor one

That file is version B:

status: review
note: ready

Editor two still holds version A. The write it would send puts status back to open and adds editor: two. It sends the same ETag:

uv run python edit.py commit --filesystem "$MOUNTABLE_FILESYSTEM_ID" --run "$RUN" --if-match "$ETAG_A" --editor two

The command prints 412 precondition_failed and a non-zero exit code. current_etag on that error is the ETag of version B. Version B is unchanged. The SDK raises MountableError with code precondition_failed and current_etag. See SDK errors.

Reread, then set only your field

Editor two reads the current file and sets editor to two. It keeps status as it is now:

uv run python edit.py reconcile --filesystem "$MOUNTABLE_FILESYSTEM_ID" --run "$RUN" --editor two

Version C:

status: review
note: ready
editor: two

The write uses the ETag from that new read. A later create of the same path is still refused:

uv run python edit.py create-again --filesystem "$MOUNTABLE_FILESYSTEM_ID" --run "$RUN"

Clean up

Pass the ETag from the latest read. A different ETag leaves the file in place.

uv run python edit.py cleanup --filesystem "$MOUNTABLE_FILESYSTEM_ID" --run "$RUN" --if-match "$ETAG"

One command runs the same steps as separate processes, then deletes the file:

uv run python edit.py live --filesystem "$MOUNTABLE_FILESYSTEM_ID" --run "$RUN"

It prints stale: 412, preserved: B, reconciled: C and collision: 412 when the checks pass.

At the USD usage prices, storage costs $0.20/GiB-month and downloads cost $0.02/GiB. The task file is under 100 bytes. Retained data can remain billable until garbage collection after deletion. Set a filesystem spending cap when this file sits on a filesystem you share with an end user.

Offline checks

uv run --locked pytest -q

These checks run the released SDK against a local fake API. They cover the refused write, the reread, the create collision and a cleanup that leaves a changed file alone. No cloud calls are made.