NodeOps
UK

Managed Processes

Managed process resources let you start commands that keep a process ID inside a sandbox. Unlike /exec, a managed process can be listed, inspected, reattached to, sent input, waited on, signaled, resized when it is a PTY, and stopped later.

Use this API for long-running commands, reconnectable output, background jobs, persistent shell sessions, and commands that need lifecycle controls after they start.


At a glance

  • Base URL: https://api.sb.createos.sh
  • Auth: X-Api-Key: <token> header. Get a token
  • Response envelope: Buffered responses use JSend, {"status": "...", "data": ...}
  • Stream format: /connect returns application/x-ndjson

When to use exec, process, or PTY

NeedUse
Quick one-shot commandexec: POST /v1/sandboxes/{id}/exec
Reconnectable command with retained outputprocess: POST /v1/sandboxes/{id}/processes without pty
Background command you will inspect or stop laterprocess, then use GET, /connect, /wait, /signal, or DELETE
Interactive shell, REPL, curses/full-screen app, or command that checks for a terminalPTY: include the pty object

Pipe process resources keep stdout and stderr separate. PTY processes combine terminal output into a single pty stream and support resize.

Output retention

Managed process output is retained for replay and reconnect, but it is bounded:

LimitValue
Per process output journal1 MiB
Aggregate process output budget per sandbox32 MiB
Maximum single output event32 KiB

When a process or sandbox exceeds these limits, the oldest retained output is discarded first. If you reconnect with an after sequence number older than the retained window, /connect returns 410 Gone with output_offset_expired and the oldest available sequence number.

cmd is one executable name or path and args contains its individual arguments. Commands are executed directly, without implicit shell parsing. For pipes, redirects, globbing, or shell syntax, run a shell explicitly:

JSON
1{
2 "cmd": "/bin/bash",
3 "args": ["-lc", "echo hello > /tmp/out.txt"]
4}

POST /v1/sandboxes/{id}/processes

Create a managed pipe process or PTY in a running sandbox.

Path parameters

ParameterDescription
idSandbox id

Request body

FieldTypeRequiredDescription
cmdstringNo for PTY, yes for pipe processProgram to execute. If omitted for PTY, the agent starts /bin/bash -i -l when Bash exists, otherwise /bin/sh -l.
argsstring[]NoArgument list.
cwdstringNoWorking directory inside the sandbox.
envobjectNoPer-process environment overrides.
ptyobjectNoInclude to create a PTY instead of separate stdout/stderr pipes.
pty.rowsintegerNoInitial terminal rows. Defaults to 24 when omitted or zero.
pty.colsintegerNoInitial terminal columns. Defaults to 80 when omitted or zero.

Create a pipe process

Bash
1curl -X POST https://api.sb.createos.sh/v1/sandboxes/sb-01K.../processes \
2 -H "X-Api-Key: $CREATEOS_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "cmd": "bash",
6 "args": ["-lc", "echo hello; echo warning >&2"],
7 "cwd": "/root",
8 "env": { "EXAMPLE": "value" }
9 }'
JSON
1{
2 "status": "success",
3 "data": {
4 "process_id": "proc_dGVzdF9wcm9jZXNzX2lkMQ",
5 "kind": "process",
6 "pid": 123,
7 "state": "running",
8 "leader_exited": false,
9 "tree_exited": false,
10 "created_at": "2026-08-19T12:00:00.123456Z",
11 "finished_at": null,
12 "exit_code": null,
13 "output": {
14 "oldest_seq": 0,
15 "newest_seq": 0,
16 "bytes": 0
17 }
18 }
19}

Create a PTY

Bash
1curl -X POST https://api.sb.createos.sh/v1/sandboxes/sb-01K.../processes \
2 -H "X-Api-Key: $CREATEOS_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "cmd": "/bin/bash",
6 "args": ["-i", "-l"],
7 "cwd": "/root",
8 "env": { "TERM": "xterm-256color" },
9 "pty": { "rows": 24, "cols": 80 }
10 }'

For a default shell PTY, the body can be as small as:

JSON
1{
2 "pty": {
3 "rows": 24,
4 "cols": 80
5 }
6}

Both PTY create forms return a standard JSend response with kind: "pty":

JSON
1{
2 "status": "success",
3 "data": {
4 "process_id": "proc_cHR5X3Byb2Nlc3NfaWQ",
5 "kind": "pty",
6 "pid": 124,
7 "state": "running",
8 "leader_exited": false,
9 "tree_exited": false,
10 "created_at": "2026-08-19T12:00:01.123456Z",
11 "finished_at": null,
12 "exit_code": null,
13 "output": {
14 "oldest_seq": 0,
15 "newest_seq": 0,
16 "bytes": 0
17 }
18 }
19}

GET /v1/sandboxes/{id}/processes

List managed pipe processes and PTYs in a sandbox.

Bash
1curl https://api.sb.createos.sh/v1/sandboxes/sb-01K.../processes \
2 -H "X-Api-Key: $CREATEOS_API_KEY"
JSON
1{
2 "status": "success",
3 "data": {
4 "processes": [
5 {
6 "process_id": "proc_dGVzdF9wcm9jZXNzX2lkMQ",
7 "kind": "process",
8 "pid": 123,
9 "state": "running",
10 "leader_exited": false,
11 "tree_exited": false,
12 "created_at": "2026-08-19T12:00:00.123456Z",
13 "finished_at": null,
14 "exit_code": null,
15 "output": {
16 "oldest_seq": 1,
17 "newest_seq": 2,
18 "bytes": 14
19 }
20 }
21 ]
22 }
23}

GET /v1/sandboxes/{id}/processes/{process_id}

Inspect one managed process.

Bash
1curl https://api.sb.createos.sh/v1/sandboxes/sb-01K.../processes/proc_123 \
2 -H "X-Api-Key: $CREATEOS_API_KEY"
JSON
1{
2 "status": "success",
3 "data": {
4 "process_id": "proc_123",
5 "kind": "process",
6 "pid": 123,
7 "state": "exited",
8 "leader_exited": true,
9 "tree_exited": true,
10 "created_at": "2026-08-19T12:00:00.123456Z",
11 "finished_at": "2026-08-19T12:00:02.456789Z",
12 "exit_code": 0,
13 "output": {
14 "oldest_seq": 1,
15 "newest_seq": 2,
16 "bytes": 14
17 }
18 }
19}

Possible lifecycle states are starting, running, terminating, exited, and failed.

For a signal exit, exit_code is null and signal carries the signal name.

Output summary fields

Create, list, get, wait, and delete responses include an output summary:

JSON
1"output": {
2 "oldest_seq": 1,
3 "newest_seq": 2,
4 "bytes": 14
5}
FieldDescription
oldest_seqOldest retained output event sequence number currently available for replay.
newest_seqNewest retained output event sequence number currently available for replay.
bytesRetained output bytes currently held for this process.

Use these fields to decide where to attach. For example, pass ?after=<newest_seq> to follow only new output, or pass ?after=0 to replay everything still retained. If you request output before oldest_seq, /connect returns 410 Gone with output_offset_expired.

GET /v1/sandboxes/{id}/processes/{process_id}/connect

Replay and follow ordered output events.

Bash
1curl -N https://api.sb.createos.sh/v1/sandboxes/sb-01K.../processes/proc_123/connect \
2 -H "X-Api-Key: $CREATEOS_API_KEY"

Response headers:

HTTP
1Content-Type: application/x-ndjson
2Cache-Control: no-store

Pipe-process output preserves stdout and stderr as separate ordered events:

JSON
1{"type":"data","seq":1,"stream":"stdout","data_base64":"aGVsbG8K"}
2{"type":"data","seq":2,"stream":"stderr","data_base64":"d2FybmluZwo="}
3{"type":"exit","exit_code":0}

PTY output is a single terminal stream:

JSON
1{"type":"data","seq":1,"stream":"pty","data_base64":"cm9vdEBzYW5kYm94OiNfIA=="}

Idle streams emit heartbeats:

JSON
1{"type":"heartbeat"}

To reconnect after output you already consumed, pass the last sequence number:

HTTP
1GET /v1/sandboxes/sb-01K.../processes/proc_123/connect?after=42

Only events with seq > 42 are replayed. If the requested offset has been evicted from the retained output window, the API returns 410 Gone with output_offset_expired.

POST /v1/sandboxes/{id}/processes/{process_id}/input

Write bytes to pipe stdin or PTY input.

Bash
1curl -X POST https://api.sb.createos.sh/v1/sandboxes/sb-01K.../processes/proc_123/input \
2 -H "X-Api-Key: $CREATEOS_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"data_base64": "aGVsbG8gd29ybGQK"}'
JSON
1{
2 "status": "success",
3 "data": {
4 "input_seq": 1
5 }
6}

input_seq increases for each successful non-empty write. Concurrent writes are serialized in submission order. Each decoded input request is limited to 256 KiB.

POST /v1/sandboxes/{id}/processes/{process_id}/stdin/close

Close stdin for a pipe process. This operation is only valid for pipe processes. A PTY returns 409 wrong_process_kind.

Bash
1curl -X POST https://api.sb.createos.sh/v1/sandboxes/sb-01K.../processes/proc_123/stdin/close \
2 -H "X-Api-Key: $CREATEOS_API_KEY"
JSON
1{
2 "status": "success",
3 "data": {}
4}

POST /v1/sandboxes/{id}/processes/{process_id}/resize

Resize a managed PTY. A pipe process returns 409 wrong_process_kind.

Bash
1curl -X POST https://api.sb.createos.sh/v1/sandboxes/sb-01K.../processes/proc_123/resize \
2 -H "X-Api-Key: $CREATEOS_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"rows": 40, "cols": 120}'
JSON
1{
2 "status": "success",
3 "data": {}
4}

POST /v1/sandboxes/{id}/processes/{process_id}/signal

Send a signal to a pipe process group or PTY foreground process group.

Bash
1curl -X POST https://api.sb.createos.sh/v1/sandboxes/sb-01K.../processes/proc_123/signal \
2 -H "X-Api-Key: $CREATEOS_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"signal": "SIGINT"}'
JSON
1{
2 "status": "success",
3 "data": {}
4}

Supported signals are SIGHUP, SIGINT, SIGQUIT, SIGKILL, SIGTERM, SIGUSR1, SIGUSR2, and SIGWINCH.

GET /v1/sandboxes/{id}/processes/{process_id}/wait

Wait for a managed process to exit.

Query parameterDescription
scopeleader waits for the top-level process. tree waits until every process it started has also exited. Defaults to leader.
timeout_msOptional long-poll timeout in milliseconds. Omitted or zero uses the server's 30-second deadline. Maximum is 30000.
HTTP
1GET /v1/sandboxes/sb-01K.../processes/proc_123/wait?scope=tree&timeout_ms=30000
JSON
1{
2 "status": "success",
3 "data": {
4 "process_id": "proc_123",
5 "kind": "process",
6 "pid": 123,
7 "state": "exited",
8 "leader_exited": true,
9 "tree_exited": true,
10 "created_at": "2026-08-19T12:00:00.123456Z",
11 "finished_at": "2026-08-19T12:00:02.456789Z",
12 "exit_code": 0,
13 "output": {
14 "oldest_seq": 1,
15 "newest_seq": 5,
16 "bytes": 512
17 }
18 }
19}

If the wait times out while the process is still running, the API returns 408 wait_timeout. Call wait again to continue.

DELETE /v1/sandboxes/{id}/processes/{process_id}

Terminate a managed process and everything it started.

Query parameterDescription
grace_msMilliseconds to wait after SIGTERM before force-killing remaining descendants. Defaults to 1000; valid range is 0 to 60000.
Bash
1curl -X DELETE "https://api.sb.createos.sh/v1/sandboxes/sb-01K.../processes/proc_123?grace_ms=1000" \
2 -H "X-Api-Key: $CREATEOS_API_KEY"
JSON
1{
2 "status": "success",
3 "data": {
4 "process_id": "proc_123",
5 "kind": "process",
6 "pid": 123,
7 "state": "exited",
8 "leader_exited": true,
9 "tree_exited": true,
10 "created_at": "2026-08-19T12:00:00.123456Z",
11 "finished_at": "2026-08-19T12:01:00.123456Z",
12 "exit_code": null,
13 "signal": "SIGTERM",
14 "output": {
15 "oldest_seq": 1,
16 "newest_seq": 5,
17 "bytes": 512
18 }
19 }
20}

The agent sends SIGTERM, waits for the grace period, kills the process cgroup if descendants remain, waits for the complete tree to exit, and returns final process details. Repeated deletion is idempotent while the process record exists.

Common errors

StatusMeaning
400Invalid request, process ID, signal, wait options, or grace period
404Sandbox or managed process not found
408Wait/control operation timed out or was cancelled
409Sandbox not running, wrong process kind, process exited, or stdin closed
410Requested output sequence was evicted from the replay journal
429Per-sandbox managed-process limit reached
502Owning host or guest process agent unavailable

Common failure codes include process_not_found, wrong_process_kind, process_exited, stdin_closed, and process_limit_reached.

100,000+ Builders. One Platform.

Get product updates, builder stories, and early access to features that help you ship faster.

NodeOps is the agentic operating system for production AI. CreateOS is its flagship product.