POST /v1/agents/runtime/{runtime_id}/commands/run
run_cmd / runCmd accepts either a single shell string or a command plus an explicit args list:
CLI timeout is in seconds (
--timeout 300). The REST API timeout field is in milliseconds (300000). The Python SDK takes seconds and converts for you.Basic Usage
Install Packages
Guest egress is deny-by-default, sopip install needs a network policy. The example uses allow_all for a short demo; prefer an allowlist for PyPI in production.
Run Shell Scripts
With Environment Variables
Setenv_vars at runtime creation so variables are available to every run_cmd / run_code call, or pass them per command:
Streaming Output
For long-running commands, passon_stdout / on_stderr / on_exit callbacks to receive output incrementally as the process produces it. The transport switches to Server-Sent Events transparently; the returned CommandRunResponse still carries the aggregated stdout/stderr/exit_code so existing code keeps working.
agent user inside the runtime. sudo is configured for the agent user with NOPASSWD, so commands like sudo apt-get install -y ... work without prompting.
Background commands
background: true starts the command and returns HTTP 201 as soon as it is running. The process keeps running after the request ends. Follow it with the pid from that response. If the program cannot be started, the response is HTTP 200 with the same body as a finished command, and there is no pid. The SDK still returns a handle: pid is null, and wait, refresh, and kill return that result without another request. An unknown pid is HTTP 404, and so is the pid of a terminal session, which has its own routes. On a runtime whose template was built before background commands were available, background: true is HTTP 501. Rebuild the template to use it.
background: true together with ?stream=true is rejected. Attach to a running command with GET .../commands/{pid}/stream.
A deadline is optional. Omit timeout (or send 0) and a foreground command is stopped after 300 seconds, while a background command has no deadline. A positive timeout is milliseconds on the REST API and seconds in the SDKs. When the deadline is reached the command exits 124 and timed_out is true.
A command that is still running when a template snapshot is taken is part of that snapshot unless the template defines a start command that replaces it.
A live stream is
text/event-stream. Each event is one JSON object, and every stream ends with exactly one end or error event:
Closing a foreground stream stops its command. Closing a stream that follows a background command leaves the command running. After an
error event, a background command may still be running, so wait() raises and you can attach again. A runtime runs up to 100 commands at once; beyond that, starting another is HTTP 429. Finished commands stay attachable for 10 minutes, and the 32 most recent exits remain listed until then.
Output callbacks passed with background follow the command in the background. If following stops early, because the stream breaks or a callback raises, on_error / onError receives the error and handle.error keeps it. The command keeps running, so you can call wait() to attach again. Stopping with handle.disconnect() is not an error.
A non-zero exit is a normal
200 response. It is not an API error.