Cookbook: hand files from a sandbox agent to a reviewer agent
An agent writes its result in a sandbox. A reviewer agent mounts the same mountable.io filesystem read-only, checks the files, and cannot change them.
Your agent finishes its work inside a sandbox. Then the sandbox stops, and the files are gone.
mountable.io is a persistent filesystem for AI agents. Your agent writes to it from the sandbox. A second agent mounts the same filesystem read-only and checks the result.
The reviewer reads the real files. It cannot change them.
Before you start
Use an existing mountable.io account with a saved payment method.
Keep MOUNTABLE_API_KEY on your orchestrator. It never enters a sandbox. Your orchestrator mints a one-time mount ticket for the writer and another one for the reviewer. Each sandbox gets only its ticket.
Create one filesystem per run, so one run's reviewer cannot read another run's files. Keep the filesystem ID and each session ID on your orchestrator for revocation.
1. Subscribe before the writer finishes
Skip this step if you start the reviewer yourself.
One API call subscribes you to signed files.changed webhooks. They fire on every create, write, rename and delete, from mounts and the API alike.
Subscribe before the writer writes its marker file. When the marker event arrives, check the signature and start the reviewer. Typical delivery takes about 0.2 seconds. That is the typical time, not a promise.
See Webhooks for the signature check.
2. The writer mounts read-write and writes its result
Your orchestrator mints a read-write ticket:
from mountable_sdk import Mountable
client = Mountable() # on the orchestrator; reads MOUNTABLE_API_KEY
writer = client.create_mount_ticket(
fs_id, mode="rw", max_duration_seconds=3600,
idempotency_key="run-123-writer",
)
# Hand only writer.ticket to the writer sandbox, as MOUNTABLE_TICKET.
# Keep writer.id to revoke the session later.Inside the writer sandbox, start the mount with that ticket:
mkdir -p /mnt/work
printf '%s\n' "$MOUNTABLE_TICKET" | mountable mount --ticket-stdin --json /mnt/work &Wait for the JSON mounted event. Then write the result. Write one marker file last, so the reviewer knows the other files are complete:
mkdir -p /mnt/work/result
cp report.md tests.txt run_tests.py /mnt/work/result/
printf '{"ready": true}\n' > /mnt/work/READY.json
mountable unmount /mnt/workThe ticket names the filesystem and the mode. The mount command stays in the foreground, so the example starts it in the background and waits for the mounted event.
3. The reviewer mounts the same files, read-only
Your orchestrator mints a second ticket. This one is read-only:
reviewer = client.create_mount_ticket(
fs_id, mode="ro", max_duration_seconds=600,
idempotency_key="run-123-reviewer",
)
# Hand only reviewer.ticket to the reviewer, as MOUNTABLE_TICKET.The reviewer mounts the same way. Its ticket says read-only, so no mount flag is needed:
mkdir -p /review
printf '%s\n' "$MOUNTABLE_TICKET" | mountable mount --ticket-stdin --json /review &Wait for the JSON mounted event. Then read and check the files:
cat /review/result/report.md
PYTHONDONTWRITEBYTECODE=1 python3 -B /review/result/run_tests.py
mountable unmount /reviewWrites to /review fail, because the ticket is ro. The reviewer can run tests and print a diff. It cannot fix, delete, or rewrite the files it is checking. Tests must not write bytecode or artifacts onto the mount.
Each ticket is single-use and must be exchanged within five minutes. The session then runs until it expires or you revoke it. Revoke both sessions from the orchestrator when the run ends:
client.revoke_mount_session(writer.id)
client.revoke_mount_session(reviewer.id)Revoking a session does not delete its files. Delete that run's filesystem in the mountable.io console when the run is finished. API keys cannot delete a filesystem.
Pass your own idempotency keys, as above. A retry with the same key returns the same session. It never shows the ticket a second time.
Run it offline first
The runnable example lives in the mountable repository. A planner and a coder write in turn. A verifier then checks the same files read-only.
From the repository root:
python3 examples/research-showcases/multi-agent-harness/harness.py
python3 examples/research-showcases/multi-agent-harness/test_harness.pyThe default run is a dry run. It uses memory files, a locally signed webhook, and a temporary folder for tests. The API, the spend cap, and the read-only mount are simulated. It creates no account, no charge, and no mount.
To run the same flow against mountable.io, follow the live steps in the example README. In the live run the planner and coder write with the SDK, and the verifier mounts the same filesystem read-only. This cookbook moves those writes onto ticket mounts, so each stage can sit in its own sandbox.
Next steps
- Permissions: read-only grants, tickets, and revocation.
- Webhooks: signed
files.changedevents and delivery. - Mount from a sandbox: mount the filesystem inside a sandbox.
- One Filesystem for the Planner, the Coder, and the Verifier: the story behind this pattern.