import asyncio
import os
import time
from boxlite import (
ApiKeyCredential,
Boxlite,
BoxliteRestOptions,
BoxOptions,
)
# A name is easier to carry between processes than an id.
VOLUME = os.environ.get("BOXLITE_VOLUME", "<YOUR_VOLUME_NAME>")
IMAGE = "ghcr.io/boxlite-ai/boxlite-agent-base:v0.1.0"
async def run_in_fresh_box(rt, name, script):
"""Create a box with the volume mounted, run one shell script, then remove the box."""
box = await rt.create(
BoxOptions(image=IMAGE, volumes=[(VOLUME, "/data")]),
name=name,
)
try:
await box.start()
execution = await box.exec("sh", args=["-c", script])
output = ""
async for line in execution.stdout():
output += line
result = await execution.wait()
return result.exit_code, output
finally:
# The box is gone after this line; the volume is not.
await rt.remove(box.id, force=True)
async def main():
rt = Boxlite.rest(BoxliteRestOptions(
url=os.environ.get("BOXLITE_REST_URL", "https://api.boxlite.ai"),
credential=ApiKeyCredential(os.environ["BOXLITE_API_KEY"]),
))
stamp = int(time.time())
try:
# Box A writes, then is destroyed.
code, _ = await run_in_fresh_box(
rt,
f"volume-writer-{stamp}",
"echo 'produced by box A' > /data/handoff.txt",
)
if code != 0:
print(f"box A write failed with exit code {code}")
return
# Box B is a different box on the same volume.
code, output = await run_in_fresh_box(
rt,
f"volume-reader-{stamp}",
"cat /data/handoff.txt",
)
print(f"box B exit code: {code}")
print(f"box B read back: {output}")
except Exception as exc:
print(f"handoff failed: {exc}")
asyncio.run(main())