Skip to main content
This guide helps you choose between synchronous and asynchronous patterns in the CoreWeave sandbox Python SDK (cwsandbox) and shows the sync and async form of each common operation. The SDK has a single async implementation internally. The sync/async flexibility comes from how you consume results: use .result() for sync and await for async.

Quick decision guide

Rule of thumb: Use sync patterns (.result()) for simplicity. Switch to await only when you’re already in an async codebase.

Core concept: OperationRef

Most SDK methods return OperationRef[T], a wrapper that is both .result()-able and awaitable. Both paths raise the same exceptions.
Sandbox.exec() returns Process, which extends OperationRef[ProcessResult] with streaming and stdin.
Never use .result() in async contexts. Calling .result() blocks the thread. In an async context this blocks the event loop and can deadlock your application. Use await instead.

Auto-start behavior

session.sandbox() returns an unstarted sandbox. The sandbox auto-starts on the first operation that requires it: Triggers auto-start: exec(), read_file(), write_file(), wait(), wait_until_complete() Does not auto-start: get_status() (raises SandboxNotRunningError), stop() (no-op if never started)

Operations

Create sandboxes

Sandbox.run() calls start().result() internally, which blocks the event loop. In async code, construct with Sandbox(...) and use async with or await sandbox to reach RUNNING status without blocking.

start()

exec()

read_file()

write_file()

stop()

wait()

wait() blocks until the sandbox reaches RUNNING status. It’s sync-only because blocking is the intent. In async code, await sandbox achieves the same thing.

wait_until_complete()

get_status()

get_status() is sync-only. It fetches the current status from the API.

Sandbox.list()

Sandbox.from_id()

Sandbox.delete()

session.list()

session.from_id()

Stream stdout

Stream stdin

Enable stdin with stdin=True. Use write() for raw bytes, writeline() for text lines, and close() to signal EOF.

cwsandbox.results()

cwsandbox.results() is a sync-only batch helper. It calls .result() on one or more OperationRef objects.

cwsandbox.wait()

cwsandbox.wait() is sync-only. It waits for a sequence of Sandbox, OperationRef, or Process objects and returns (done, pending). Sandboxes resolve when they reach RUNNING status, not on completion.

@session.function()

Parallel execution

The sync API supports parallel execution because operations are non-blocking by design. Methods like exec(), read_file(), and write_file() return immediately. You only block when you call .result(). Sandbox.run() blocks until the backend accepts the start request (it calls start().result() internally). For parallel startup, use session.sandbox() (auto-starts on first operation) or collect start() refs:

Jupyter notebooks

The sync API works in Jupyter without nest_asyncio because the SDK runs its own background event loop in a daemon thread:
For async in Jupyter, await works directly since Jupyter has a built-in event loop:

Error handling

Both sync and async paths raise the same exceptions. .result() re-raises any exception from the underlying operation, and await does the same. See the Troubleshooting guide for the full exception hierarchy and recovery patterns.
Last modified on May 29, 2026