Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Cloudflare R2 workspace backend

Mnemo’s MnemoSnapshotStore — the OpenAI Agents SDK GA snapshot store — supports persisting workspace trees to any S3-compatible object store. v0.3.4 ships CloudflareR2Workspace as a thin subclass of S3Workspace so R2-backed snapshots inherit every feature of the AWS path unchanged: signed manifests, Ed25519 verification, per-blob digest checks, batched delete.

Install

pip install 'mnemo-db[openai-sandbox-r2]'

The extra pulls boto3>=1.34 and cryptography>=42. R2’s S3 API is wire-compatible with AWS SDK v4 signing, so no R2-specific client library is needed.

Quick start

from mnemo.openai_sandbox.r2_workspace import CloudflareR2Workspace
from mnemo.openai_sandbox.manifest import WorkspaceSigner

signer = WorkspaceSigner.generate_ephemeral()  # or load yours from KMS

ws = CloudflareR2Workspace(
    bucket="agent-snapshots",
    account_id="abc123def456",   # R2 account ID
    access_key_id="...",         # R2 access key
    secret_access_key="...",     # R2 secret access key
)

spec = ws.save_workspace(
    workspace_root="/tmp/agent-state",
    signer=signer,
    workspace_id="run-2026-04-25-1",
    created_at="2026-04-25T00:00:00Z",
    key_prefix="agents/agent-1",
)

# `spec` carries backend="r2" — MnemoSnapshotStore dispatches via
# this field to keep the load path symmetric with save.
print(spec)
# RemoteSnapshotSpec(backend='r2', bucket='agent-snapshots',
#                    key_prefix='agents/agent-1', manifest_sha256='...')

Differences from S3 in one line

KnobAWS S3Cloudflare R2
endpoint_urlregional defaulthttps://{account_id}.r2.cloudflarestorage.com
regionus-east-1 etc."auto" (literal)
Addressingpath or virtual"virtual"
Signaturesigv4sigv4
Credential providersfull AWS chainaccess keys only

CloudflareR2Workspace sets every R2-specific knob in its constructor; nothing else in the snapshot path needs to know it’s R2.

Storage layout

Same as S3Workspace. One R2 object per file in the workspace plus two top-level objects per snapshot:

<bucket>/<key_prefix>/manifest.json     # signed JSON manifest
<bucket>/<key_prefix>/manifest.sig      # detached Ed25519 signature
<bucket>/<key_prefix>/files/<rel_path>  # one per source file

Symlinks are recorded in the manifest (not as separate objects) so the load path can recreate them after every regular file is fetched

Live-credential test

The Mnemo test suite runs a moto-S3 round-trip against CloudflareR2Workspace on every CI build. To run a real R2 round-trip locally, export:

export R2_ACCOUNT_ID=<account>
export R2_ACCESS_KEY_ID=<key>
export R2_SECRET_ACCESS_KEY=<secret>
export R2_BUCKET=<bucket>

pytest python/tests/test_r2_workspace.py::test_live_r2_round_trip -v

The test creates a small workspace tree, dumps it to R2 under the mnemo-tests/live-r2/ prefix, fetches it back, asserts file contents match, and cleans up. Skipped silently when any of the four env vars are unset.

Cost note

R2’s free tier is 10 GB storage + 1M Class-A operations / month + 10M Class-B operations / month. A typical mnemo workspace snapshot is ~10 files at ~1 MB each, so a few thousand snapshots fit inside the free tier — see Cloudflare R2 pricing.

R2 also has zero egress fees, which makes it a good fit for snapshot restore traffic patterns (lots of reads on a bad day, very few on a good one).

Sources