Sandboxes
View MarkdownA Sandbox is an isolated, long-running container for agents and untrusted code. You drive it with commands and file operations; it stops when idle and starts again on the next command.
"""Create a Sandbox, run commands in it, move files and delete it.
Run it with `python examples/python/sandbox/main.py`."""
import nodus
def main() -> None: sb = nodus.Sandbox.create( cpu=1, memory="2Gi", idle_timeout="5m", max_cost=1, ) try: p = sb.exec("python", "-c", "print(6 * 7)") print("stdout:", p.stdout.read().strip(), "exit:", p.wait()) with sb.open("/workspace/notes.txt", "w") as f: f.write("written from the SDK\n") print(sb.exec("cat", "/workspace/notes.txt").stdout.read(), end="") finally: sb.terminate()
if __name__ == "__main__": main()Create
Section titled “Create”sb = nodus.Sandbox.create( name="agent-1", # optional; creating the same name again reconnects image="nodus/agent-tools", # the default: Python 3.12, Node 22, git cpu=2, memory="4Gi", timeout="24h", idle_timeout="5m", on_idle="stop", network=nodus.Egress.open(), # outbound access; the default is nodus.Egress.deny() max_cost=5,)create returns as soon as the Sandbox is admitted; commands wait for it to start. Egress is denied unless you
open it. nodus.Sandbox.from_name("agent-1") reconnects and starts it again if you stopped it.
Run commands
Section titled “Run commands”p = sb.exec("python", "-c", "print(6 * 7)")print(p.stdout.read()) # everything the process wrote to stdoutassert p.wait() == 0 # the exit code
p = sb.exec("pip install requests && python app.py") # one string runs under /bin/sh -cfor chunk in p.stdout: # stream output as it arrives print(chunk, end="")
p = sb.exec("bash", pty=True)p.write("ls\n"); p.resize(40, 120); p.signal("SIGINT")Every command is recorded as a Process, and its output is kept, so a reader that reconnects continues where it
stopped. p.stdin.write(...) and p.stdin.write_eof() feed input; p.cancel() stops the process.
with sb.open("/workspace/notes.txt", "w") as f: f.write("hi")print(sb.files.read("/workspace/notes.txt"))print(sb.files.list("/workspace"))Stop, start and snapshot
Section titled “Stop, start and snapshot”sb.stop() # saves the filesystem; compute billing stops, the saved files count as storagesb.start()image = sb.snapshot_filesystem() # Beta: an Image of the current filesystemsb.terminate() # deletes it