# cloud_volume.py — create a named volume, mount it, write and read through it
# Run: python cloud_volume.py
import asyncio
import os
import time
from boxlite import (
ApiKeyCredential,
Boxlite,
BoxOptions,
BoxliteRestOptions,
)
IMAGE = "ghcr.io/boxlite-ai/boxlite-agent-base:v0.1.0"
api_key = os.environ.get("BOXLITE_API_KEY")
if not api_key:
raise SystemExit("Set BOXLITE_API_KEY to your blk_live_... key before running this.")
async def main() -> None:
rt = Boxlite.rest(
BoxliteRestOptions(
url=os.environ.get("BOXLITE_REST_URL", "https://api.boxlite.ai"),
credential=ApiKeyCredential(api_key),
)
)
volume = None
box = None
try:
# rt.volumes is a property. create() takes an optional name that you can
# mount by later, instead of carrying the id around.
volume = await rt.volumes.create(f"demo-{int(time.time())}")
print(f"Created volume {volume.name} (id {volume.id})")
box = await rt.create(
BoxOptions(
image=IMAGE,
# (managed volume name or id, mount path inside the box)
volumes=[(volume.name, "/data")],
),
name=f"volume-demo-{int(time.time())}",
)
await box.start()
# Write through the mount, not to the box's own disk.
write = await box.exec(
"sh",
args=["-c", "echo 'subtitle model v3' > /data/notes.txt"],
)
write_result = await write.wait()
if write_result.exit_code != 0:
print(f"write failed with exit code {write_result.exit_code}")
return
read = await box.exec("cat", args=["/data/notes.txt"])
content = ""
async for line in read.stdout():
content += line
read_result = await read.wait()
print(f"Exit code: {read_result.exit_code}")
print(content)
except Exception as exc:
# Auth failures, creation failures, and local runtimes without a volume
# backend all surface here.
print(f"volume run failed: {exc!r}")
finally:
# Teardown in finally, so a failure above cannot leave a box billing.
if box is not None:
await rt.remove(box.id, force=True)
if volume is not None:
await rt.volumes.remove(volume.id)
if __name__ == "__main__":
asyncio.run(main())