spawn_detached() when a command must continue after the current Python
process exits. The session records its UUID, source image, parent entry, branch,
command options, and uploaded attachment metadata. It does not start an event
reader. The server still applies the operation’s configured timeout.
Use a SQLite store for persistence across processes. Memory stores implement the
same API but retain records only while that store instance exists. Keep the same
session ID, database, and endpoint when resuming.
Submit work
The first block submits work and closes the local store and client. It leaves the remote operation running. Store the operation UUID in your application or retrieve it throughsession.list_operations() after restarting Python.
The async variant uses native transport and storage. No event loop or background
reader must remain running between submission and collection. Run async blocks
inside an async function or a compatible notebook.
- Sync
- Async
Collect the result
Run the next block in the process that collects the result.wait_operation()
uses the session’s commit policy and records completion atomically with history.
It returns the process result, including a nonzero exit code. The consumer needs
the same working directory and connection profile. It obtains the UUID from
the store, so no Python variables from the submitting process are needed. This
example has exactly one pending operation; applications with several operations
must select the intended record or accept a UUID as an argument.
- Sync
- Async
Branches and commit policy
Completion keeps the parent captured at spawn time. Switching branches or continuing other work does not redirect or reject the result. The completed entry is another child of its original parent. Obtain its ID fromsession.get_operation(uuid).history_id and use navigate() to select it.
Waiting can advance the local position when it still matches the source;
replaying an already completed result does not undo a later rollback.
The default ApiSuccessCommitPolicy retains every successful non-disposable
result, including nonzero exit codes. Pass commit_policy=ZeroExitCommitPolicy()
when resuming to retain only exit code zero. See Customize the SDK for custom
policies. Concurrent completion calls share the first stored decision. A later
policy change or rollback cannot cause a second commit.
Disposable and policy-rejected results remain readable without a history entry.
Final API failures and cancellation remain readable as the same exceptions.
Completed wait_operation() calls use the stored response without remote I/O.
Transport errors remain pending. A timeout or cancellation of a live wait follows
Operation.wait() semantics and requests remote cancellation; it does not merely
stop observing the operation.
wait_operation() closes its internal handle before returning or raising. Async
cleanup completes even after repeated caller cancellation. Synchronous cleanup
uses a bounded reader join; a blocked transport can keep its reader thread alive
until the stream releases it. See Advanced: control a running sandbox for lifecycle details.
Control and inspect registered work
detach(operation) registers an existing session operation without closing its
handle. restore_operation(uuid) reconstructs a handle through create_operation()
with the original context. Override create_operation_record() and
restore_operation_context() together to persist application-specific request
fields. Both restoration and commit policies use these hooks. Use that handle to send signals, cancel the operation,
or read events. After wait(), commit_result() on a restored handle uses the
same atomic completion path. Use wait_operation() to replay a stored response.
list_operations() returns pending records. Set pending_only=False to include
completed records. OperationRecord.history_id identifies a retained result;
response stores the final API response as a JSON object. Records include the effective
command environment and output, but not client credentials. A different client
endpoint is rejected before the UUID is used.
Local file and stdin sources are not serialized or reopened. Attachments retain
their uploaded UUIDs and destination permissions. Restored OperationContext
values have request.files=None and request.stdin=None; inspect attachments
and files for the submitted inputs. Commit policies must use this persisted
context, rather than source objects. Detached titles and file metadata are fixed
at registration; commit_result() cannot override them.
Failure boundaries and custom stores
Remote submission and local registration are separate operations. If registration raises normally,spawn_detached() requests cancellation and preserves the
registration error. A process crash between remote submission and registration
can leave an unregistered remote operation. Registration does not promise exactly
one remote submission. Retrying submission can start another operation.
A pending node stores the original context and the identity reserved for its
result. Completion appends one immutable node containing the final response and
optional retained image. An identical write can be retried. If concurrent
collectors disagree on commit policy, the first saved completion is retained.
Deleting the tree removes both records; it does not cancel the remote operation.
Custom stores need only the tree contract, including atomic and idempotent
append(). They do not implement a second operation registry API. See
Tree stores for the guarantees required across processes.