#Contexts (Process Runtime)

Contexts are execution units within a sandbox. Each context runs a process and can be either a REPL (stateful) or Cmd (stateless) type.

Context Types#

TypeDescriptionUse Case
REPLStateful, interactive processCode evaluation, interactive shells, persistent sessions
CmdStateless, one-shot commandSingle commands, scripts, non-interactive execution

REPL vs Cmd#

REPL contexts preserve state between calls - variables, environment, and working directory persist. Cmd contexts are stateless - each execution starts fresh.

python
# REPL: State preserved between calls _S0_> x = 2 _S0_> print(x) 2 # Cmd: Each command is independent $ x=2 $ echo $x # Empty - variable not preserved

High-Level: Run and Cmd#

For common use cases, use the convenience methods Run (REPL) and Cmd (command).

Run (REPL)#

Execute code in a REPL context. State is preserved between calls.

go
// First call - set variable result, err := sandbox.Run(ctx, "python", "x = 2") if err != nil { log.Fatal(err) } fmt.Print(result.OutputRaw) // Second call - variable preserved result, err = sandbox.Run(ctx, "python", "print(x)") if err != nil { log.Fatal(err) } fmt.Print(result.OutputRaw)

Run with Options#

go
// Create a custom context with specific cwd, env vars, and TTL customCtx, err := sandbox.CreateContext(ctx, apispec.CreateContextRequest{ Type: apispec.NewOptProcessType(apispec.ProcessTypeRepl), Repl: apispec.NewOptCreateREPLContextRequest(apispec.CreateREPLContextRequest{ Alias: apispec.NewOptString("python"), }), Cwd: apispec.NewOptString("/workspace"), EnvVars: apispec.NewOptCreateContextRequestEnvVars(map[string]string{"GREETING": "hello from workspace"}), TTLSec: apispec.NewOptInt32(120), IdleTimeoutSec: apispec.NewOptInt32(60), }) if err != nil { log.Fatal(err) } fmt.Printf("Custom context ID: %s\n", customCtx.ID) // Run using the custom context result, err = sandbox.Run( ctx, "python", `import os, pathlib; print(pathlib.Path.cwd()); print(os.getenv("GREETING"))`, sandbox0.WithContextID(customCtx.ID), ) if err != nil { log.Fatal(err) } fmt.Print(result.OutputRaw)

Cmd (One-shot Command)#

Execute a stateless command.

go
// One-shot command - stateless result2, err := sandbox.Cmd(ctx, `/bin/sh -c "echo hi"`) if err != nil { log.Fatal(err) } fmt.Print(result2.OutputRaw) // Variables NOT preserved between Cmd calls sandbox.Cmd(ctx, `/bin/sh -c "x=3"`) result2, err = sandbox.Cmd(ctx, `/bin/sh -c "echo $x"`) if err != nil { log.Fatal(err) } fmt.Print(result2.OutputRaw)

Cmd with Options#

go
result2, err = sandbox.Cmd( ctx, "bash -c 'echo $GREETING && pwd'", sandbox0.WithCmdCWD("/tmp"), sandbox0.WithCmdEnvVars(map[string]string{"GREETING": "hello"}), sandbox0.WithCmdTTL(120), sandbox0.WithCmdIdleTimeout(60), ) if err != nil { log.Fatal(err) } fmt.Print(result2.OutputRaw)

Create Context#

Create a new context in a sandbox.

POST

/api/v1/sandboxes/{id}/contexts

Request Body#

FieldTypeDescription
typestringContext type: repl or cmd
replobjectREPL configuration (optional for type=repl; defaults to Python when omitted)
cmdobjectCommand configuration (cmd.command required if type=cmd)
cwdstringWorking directory
env_varsobjectEnvironment variables
pty_sizeobjectTerminal size {rows, cols}
ttl_secintegerContext time-to-live in seconds
idle_timeout_secintegerIdle timeout in seconds
wait_until_donebooleanWait for completion (default: false)

REPL Configuration#

FieldTypeDescription
aliasstringREPL alias/language (python, bash, node, etc.)
inputstringInitial input to send
repl_configobjectCustom REPL config (optional; advanced use)

Cmd Configuration#

FieldTypeDescription
commandarrayCommand and arguments
go
// Create REPL context ctxResp, err := sandbox.CreateContext(ctx, apispec.CreateContextRequest{ Type: apispec.NewOptProcessType(apispec.ProcessTypeRepl), Repl: apispec.NewOptCreateREPLContextRequest(apispec.CreateREPLContextRequest{ Alias: apispec.NewOptString("python"), }), Cwd: apispec.NewOptString("/workspace"), EnvVars: apispec.NewOptCreateContextRequestEnvVars(map[string]string{"DEBUG": "true"}), TTLSec: apispec.NewOptInt32(120), }) if err != nil { log.Fatal(err) } fmt.Printf("Context ID: %s\n", ctxResp.ID)

Custom REPL (repl_config)#

Use repl_config when you need to run a non-built-in REPL, customize startup arguments, or tune readiness detection.

FieldTypeRequiredDescription
namestringYesREPL identifier. If alias is also set, it must match repl_config.name.
display_namestringNoHuman-readable name.
descriptionstringNoDescription for this REPL config.
candidatesarrayYesOrdered executable candidates. Each item: { name, args }.
envarrayNoEnvironment variables. Each item: { name, value } or { name, value_from }.
default_termstringNoDefault TERM value when no terminal value is provided.
prompt.custom_promptstringNoCustom prompt string used by REPLs that support prompt env injection.
ready.modestringNoReadiness strategy: prompt_token or startup_delay.
ready.tokenstringCond.Required when ready.mode=prompt_token.
ready.startup_delay_msintegerCond.Used when ready.mode=startup_delay (must be >= 0).

Notes:

  • candidates must contain at least one executable.
  • If ready.mode is omitted, runtime picks a default strategy based on whether ready.token is provided.
  • Common env.value_from values are term and prompt.

Example request:

json
{ "type": "repl", "repl": { "alias": "myrepl", "repl_config": { "name": "myrepl", "display_name": "My REPL", "candidates": [ { "name": "myrepl", "args": ["--interactive"] }, { "name": "python3", "args": ["-q", "-i"] } ], "env": [ { "name": "TERM", "value_from": "term" } ], "ready": { "mode": "startup_delay", "startup_delay_ms": 300 } } } }

List Contexts#

List all contexts in a sandbox.

GET

/api/v1/sandboxes/{id}/contexts

go
contexts, err := sandbox.ListContext(ctx) if err != nil { log.Fatal(err) } for _, ctx := range contexts { fmt.Printf("- %s (type: %s, running: %v)\n", ctx.ID, ctx.Type, ctx.Running) }

Get Context#

Get details of a specific context.

GET

/api/v1/sandboxes/{id}/contexts/{ctx_id}

go
ctxResp, err = sandbox.GetContext(ctx, ctxResp.ID) if err != nil { log.Fatal(err) } fmt.Printf("Type: %s\n", ctxResp.Type) fmt.Printf("Running: %v\n", ctxResp.Running)

Context Control Operations#

Restart Context#

Restart a context process.

POST

/api/v1/sandboxes/{id}/contexts/{ctx_id}/restart

go
_, err = sandbox.RestartContext(ctx, ctxResp.ID) if err != nil { log.Fatal(err) }

Send Input#

Send input to a context's stdin.

POST

/api/v1/sandboxes/{id}/contexts/{ctx_id}/input

go
_, err = sandbox.ContextInput(ctx, ctxResp.ID, "print('hello')") if err != nil { log.Fatal(err) }

Resize PTY#

Resize the terminal dimensions.

POST

/api/v1/sandboxes/{id}/contexts/{ctx_id}/resize

go
_, err = sandbox.ContextResize(ctx, ctxResp.ID, 24, 80) if err != nil { log.Fatal(err) }

Send Signal#

Send a signal to the context process.

POST

/api/v1/sandboxes/{id}/contexts/{ctx_id}/signal

go
// Send SIGTERM _, err = sandbox.ContextSignal(ctx, ctxResp.ID, "TERM") if err != nil { log.Fatal(err) }

Get Context Stats#

Get resource usage statistics for a context.

GET

/api/v1/sandboxes/{id}/contexts/{ctx_id}/stats

go
stats, err := sandbox.ContextStats(ctx, ctxResp.ID) if err != nil { log.Fatal(err) } fmt.Printf("Memory: %d bytes\n", stats.Usage.Value.MemoryRss.Value) fmt.Printf("CPU: %.2f%%\n", stats.Usage.Value.CPUPercent.Value)

Delete Context#

Delete a context.

DELETE

/api/v1/sandboxes/{id}/contexts/{ctx_id}

go
_, err = sandbox.DeleteContext(ctx, ctxResp.ID) if err != nil { log.Fatal(err) } fmt.Println("Context deleted")

WebSocket Streaming#

For real-time I/O, connect to a context via WebSocket.

GET

/api/v1/sandboxes/{id}/contexts/{ctx_id}/ws

WebSocket Protocol#

Client Messages:

TypeDescriptionExample
inputSend input to stdin{"type": "input", "data": "ls\n", "request_id": "req-1"}
resizeResize terminal{"type": "resize", "rows": 24, "cols": 80}
signalSend signal{"type": "signal", "signal": "INT"}

Server Messages:

TypeDescriptionExample
outputProcess output (stdout / stderr / pty){"source": "stdout", "data": "hello\n"}
go
// Create context first ctxResp, err = sandbox.CreateContext(ctx, apispec.CreateContextRequest{ Type: apispec.NewOptProcessType(apispec.ProcessTypeRepl), Repl: apispec.NewOptCreateREPLContextRequest(apispec.CreateREPLContextRequest{ Alias: apispec.NewOptString("python"), }), }) if err != nil { log.Fatal(err) } // Connect WebSocket conn, _, err := sandbox.ConnectWSContext(ctx, ctxResp.ID) if err != nil { log.Fatal(err) } defer conn.Close() // Send input msg := map[string]any{ "type": "input", "data": "print('hello')\n", "request_id": "req-1", } conn.WriteJSON(msg) conn.SetReadDeadline(time.Now().Add(3 * time.Second)) // Read output for { _, message, err := conn.ReadMessage() if err != nil { break } var msg struct { Source string `json:"source"` Data string `json:"data"` } json.Unmarshal(message, &msg) fmt.Print(msg.Data) }

Exec (Synchronous Execution)#

Execute input and wait for completion.

POST

/api/v1/sandboxes/{id}/contexts/{ctx_id}/exec

go
execResult, err := sandbox.ContextExec(ctx, ctxResp.ID, "print(1 + 2)") if err != nil { log.Fatal(err) } fmt.Print(execResult.OutputRaw)

Next Steps#

Files

Read, write, and manage files in sandboxes

Network Policy

Control network access and egress rules

Port Exposure

Expose sandbox ports publicly