Antioch simulation SDK
antioch-sim is Antioch's typed Python SDK and CLI. Write ordinary Python in
your own project, then run it on managed cloud GPUs. Your computer needs
Python 3.12; it does not need Isaac or a GPU. This guide explains customer
workflows; AGENTS.md sets package rules, and the
platform skill guides agents.
Projects, services, sessions, and runs
A project is a directory with one antioch.yaml. Its services are
container workloads. Service names are arbitrary: sim is a starter-project
convention, not a required name.
The simulator is a role determined by verified image lineage: an Antioch
engine image, or an image built from one. Scenarios, suites, and Jupyter need
that role. If several services use supported Antioch images, select the target
in the scenario decorator. A service-only project is valid too:
antioch run and antioch service exec default to the simulator when present,
then to the only active service. Otherwise, select one with --service.
A project revision saves the manifest and exact service images. Dockerfile
COPY puts source in the image; there is no separate run source bundle.
A session is temporary compute running one project's services:
- Interactive sessions support scripts, shells, watch, Jupyter, and attached scenario or suite runs. Placement prefers nearby available compute.
- Background sessions run detached scenarios and suites without the terminal.
A scenario is a typed Python evaluation with parameters, checks, and results. A case names parameter values; a suite selects scenarios and cases. Their saved run records survive session retirement. Temporary service files do not: save results as artifacts or assets.
Mission Control provides a separate temporary development workspace. It is a client of simulation compute, not a simulation session.
Start a project
Use uv to create a project and install Antioch in its Python 3.12 virtual environment:
uv init --bare --python ">=3.12,<3.13" my-sim
uv --directory my-sim python pin 3.12
cd my-sim
uv add --compile-bytecode "antioch-sim[isaac-sim]>=0.4.293"
source .venv/bin/activate
antioch auth login
antioch init
antioch run src/main.py
The SDK resolves from PyPI. Use antioch-sim[isaac-lab]>=0.4.293 for Isaac
Lab 3.0. The extra installs editor types and selects the matching starter
project, not a local simulator.
For Python projects that bring their own simulator, use antioch-sim[base]
and antioch init --engine base. The base image
includes Antioch without Isaac Sim or Isaac Lab; scenarios use config=None.
antioch init creates the manifest, Dockerfile, source, watch rules, and
example suites. It does not start compute. antioch run starts or reuses an
interactive session and runs the script. A new session builds the current
project; use antioch service sync or antioch service watch to apply later local edits.
The generated Dockerfile puts source under /workspace/project and pins its
engine image to the installed SDK version. Package-manager upgrades and normal
builds do not rewrite existing project files. Explicit antioch project update
can update both the SDK dependency and literal project engine pins.
A newer CLI can keep a supported older engine image: Rome records its actual
SDK version, and the CLI uses that returned runtime pin.
Set up agent plugins
From the project directory, install the current SDK and its matching plugin:
antioch setup --python .venv/bin/python
On Windows, use --python .venv\Scripts\python.exe. Without --python, setup
uses the active virtual environment, or the project's .venv if none is active.
Create an environment with uv venv --python 3.12 if you do not have one.
Setup configures every Codex or Claude Code client on PATH, then checks your
Antioch sign-in and Research connection. It reports the next step if a check
fails. Use --dry-run to preview changes. Keep the environment active when you
launch your agent so it can find the CLI and both MCP commands.
Setup updates installed packages without changing the project's dependency
files or engine images. Use antioch project update to update those together.
Update a project
antioch project update --dry-run
antioch project update
antioch project update updates the project's SDK dependency and engine image
tags to the current release. It preserves the selected engine families and
Python dependency extras and markers.
It runs uv lock and uv sync --locked --inexact, keeping installed optional
packages, and skips both when the project SDK already matches the exact release
wheel and pyproject.toml is unchanged. Optional/group-only, editable,
workspace, or direct-URL SDK selections need an explicit existing
--python .venv/bin/python target; that target uses uv's pip interface and does
not rewrite project dependency constraints. A project without its own SDK
environment builds in the SDK that antioch setup installed, so run setup first.
If antioch.yaml is at the repository root but the SDK lives in a nested uv
project, select it explicitly:
antioch project update --sdk-project antioch-integration --dry-run
antioch project update --sdk-project antioch-integration
This updates that directory's dependency, lockfile and .venv alongside the
manifest's image pins. Other nested projects are untouched. Without this
option, only the root pyproject.toml is considered; the result warns when
no SDK dependency or lock was updated. --python only installs into an
interpreter and does not align its project's dependency or lockfile.
Changed Dockerfile pins build through the normal project revision path in the
same update; --no-build leaves that build to the next session start. No
session is started, restarted, or changed: a live session keeps its previous
image, and antioch session new starts on the updated project. The update ends
by naming that step. ARG-based engine references, digest pins, symlinks, and
ambiguous source locations are refused before project edits. A later package or
build failure leaves the local edits for inspection and names the update as the
command that resumes it; it is not a rollback.
The result reports root, the SDK the project runs (sdk, or null when the
project has none of its own), files with project-relative paths including an
observed uv.lock change after sync, and the sync and build actions as
planned, completed, or skipped. Completed builds include revision IDs;
--no-build reports a skipped build, not an accepted revision.
Define services
Antioch uses a validated Compose-style manifest, not the full Docker Compose specification. The manifest guide lists supported fields.
To bind a checkout to its intended organization, add a top-level
organization_id: org_.... Use the tenant_id reported by
antioch auth whoami --json. Remote CLI and SDK operations from that project
refuse a different authenticated organization before submitting work, including
asset uploads and reuse of a live session. Antioch never switches organizations
automatically: use antioch auth switch --org org_... or provide the matching
personal access token. An opaque token requires a read-only identity lookup.
Omitting the field preserves the active-organization behavior. Local manifest
validation and antioch auth remain available when the organizations differ.
id: warehouse-sim-0123456789abcdef
name: warehouse-sim
scenario_paths: ["src/scenarios.py"]
services:
physics:
build:
context: .
dockerfile: Dockerfile
resources:
gpu: rtx-pro-6000
watch:
- action: sync
path: .
target: /workspace/project
autonomy:
image: registry.example.com/robot/autonomy:release
depends_on:
physics:
condition: service_started
restart: on-failure
suites:
smoke:
description: Fast simulation checks
select:
- tags: ["smoke"]
Each service declares exactly one image or build. A build selects a
context and Dockerfile; source enters the image through COPY. Services may
declare dependencies, health checks, resources, restart policies, named ports,
and profiles. Service names are also network names within the session.
resources.region pins the session to one region: us-central or uk.
It is a hard requirement, not a preference: the session waits if the region
has no free machine, and antioch scenario run reports
waiting for capacity in uk while it does. Omit it to let Antioch place the
session wherever a machine is free. Every session reports where it landed as
Session placed in <region>; antioch session list --verbose and
antioch scenario list --verbose add a REGION column.
An engine Dockerfile uses a versioned base:
FROM antioch-engine/isaac-sim-6.0.1:0.4.293
Public external FROM bases may use tags such as python:3.12-slim.
Antioch freezes each base to an exact digest before computing the build key,
without changing your Dockerfile. Use @sha256: to select a fixed base
yourself. A new preparation can pick up a moved tag; saved revisions keep
their exact images. The manifest's image field may also use a tag. Every
session keeps its manifest, revision, images, and containers unchanged.
Antioch supplies its pinned Dockerfile frontend. Remove a leading
# syntax=... directive: selecting another frontend is not supported and is
refused locally before a build starts.
Connect named ports
antioch service ports --serve serves declared forward mappings on local
loopback addresses. For a service-to-client route, set the local destination
explicitly, for example:
antioch service ports --bind physics.callback=127.0.0.1:9090 --serve
The service connects to 127.0.0.1 at its declared callback port. The CLI
relays those bytes to your local port 9090. TCP connections and UDP source
endpoints stay separate. Each reverse registration permits 32 concurrent
peers; idle UDP associations expire after 60 seconds. A blocked peer has a
bounded buffer and is closed instead of blocking its siblings. Stop the
command to close its listener and peers. Port forwarding alone does not keep
the session active.
Reverse ports require the current CLI and a fresh session with support.
Open a Viser viewer in Mission Control
Declare the existing Viser port and select it as the service's viewer:
services:
sim:
build: {context: ., dockerfile: Dockerfile}
ports:
- name: viser
port: 8080
protocol: tcp
direction: client-to-service
viewer:
type: viser
port: viser
Omitting viewer preserves the default Omniverse/Isaac WebRTC stream on
Isaac Sim and Isaac Lab services; base compute has no implicit video viewer.
To select that explicitly, set viewer: {type: omniverse}
on a native-video-capable service. Omniverse uses that service's native stream routes
and does not accept a port. Each service can declare its own viewer, so
multiple Viser and native services can coexist. Mission Control follows the
active service by default; its Viewer service picker pins a specific
service or returns to automatic selection. Opening the same Viser service
from multiple browsers is also supported; shared controls belong to the app.
The old x-antioch manifest extension is no longer accepted. Move its viewer
directly onto the service and remove runner; select scenario targets with
service= and CLI targets with --service. Retained session history stays readable,
but revisions containing the retired extension cannot be rerun or adopted. Update
the manifest and run again with the current CLI to freeze a new revision.
Use Viser's single-file browser client (1.1 or later; validated with 1.1.1).
Your service or interactive Python process must start viser.ViserServer
on that exact port. Newton's ViewerViser and custom Viser applications can
use this endpoint; the console displays their own scene and controls. For
example, this standalone process exposes a button that changes the scene:
import time
import viser
server = viser.ViserServer(host="0.0.0.0", port=8080)
box = server.scene.add_box("/box", dimensions=(0.2, 0.2, 0.2))
button = server.gui.add_button("Toggle box")
@button.on_click
def toggle(_event):
box.visible = not box.visible
while True:
time.sleep(1)
Create a new interactive session from that revision, start the viewer process, and choose Open interactive viewer in Mission Control's Sessions pane. Camera movement and authored controls stay interactive. Rerun telemetry remains separate. The viewer reconnects when its five-minute access ticket expires; server simulation continues during that reconnect. Viewer access is restricted to the session owner. The console does not automatically add pause, step, or force controls to Python.
Update an interactive session
Watch actions are:
sync: copy matching files to a target under/workspace/project.sync+restart: copy, then restart the service process in the same container.sync+exec: copy, then run a declared command with a timeout of at most five minutes.
antioch service sync
antioch service watch
antioch service restart
session new and service sync copy files once without restart or exec
actions. Those actions remain pending for service watch. Restart waits for
fresh authored health checks; a reserved run can block interactive restart.
A service with no effective command stays idle, and restart does nothing.
antioch service ps --json reports process_healthy for each service: the
supervisor has no uncontained processes. It does not report that service's
application health check. session_ready reports the latest aggregate session
readiness, including authored health checks, and is repeated on each row.
Use antioch session status --json to read the session's readiness conditions.
Session replacement and idle policy
After an image or dependency change, run antioch session new. A project has
one live interactive session; session new replaces it with a fresh one without
a confirmation prompt. Rome refuses replacement while the old session runs a command unless
you pass --force, which stops that work as part of replacement. Save
remote files before you replace a session. The default quota is two interactive
sessions across your projects and a separate two background sessions. Build or
quota failure does not change the existing session.
Interactive sessions stop after 15 minutes without work, with a short
reconciliation delay before retirement. Running commands and scenario or
suite execution keep them active, even when no
client follows their output. For antioch jupyter, cell execution counts;
an idle notebook or its server does not. Authentication, status reads, log viewers, streams
and an open console tab do not count. Persistent authored services alone
do not count either. Save remote files before the idle deadline or release.
On a supporting runtime, the default Bash shell waiting at its prompt is idle. Real terminal input resets the allowance; resize, output and attachment alone do not. Quiet foreground commands, builtins, pipelines, background and detached jobs remain protected. The full idle allowance follows completion. Nested shells, editors, REPLs, tmux and stopped jobs are conservatively protected; no keystrokes does not prove that their state can be discarded.
Bash integration requires Bash 4.4 or later, a non-dumb terminal, the managed
image's normal login profile, and intact prompt hooks. Shells that skip that
profile remain protected as running commands. Custom signal traps, readline
bind -x handlers, or changed
hooks can make activity unavailable. Changed or unsupported hooks never
prove idle: antioch service ps reports the state, and its JSON includes work
timestamps and reasons. Save work before reopening a shell. Unsupported shells
and unobservable interactive applications can still hold a session indefinitely;
there is no absolute session time limit.
Put CLI options before the service: antioch service shell --no-stream nav.
Tokens after the service are the remote command, not CLI options.
If the agent cannot report activity, Rome leaves the session running without extending its idle deadline. This avoids stopping work on an incomplete observation. Sessions with older agents need replacement to use this policy. At expiry the CLI and console show an idle-expiry hold, the affected services and known reasons; compute continues accruing usage until it is retired. Upgrading a local SDK does not change an already running session's agent or containers. Save remote files before an owner-approved release or replacement. Downloaded scenario artifacts and retained results survive retirement; arbitrary container files and notebook/editor memory do not.
Managed antioch jupyter uses standard kernel busy/idle observations. A manually
launched jupyter lab is ordinary shell work. A completed cell does not prove
that arbitrary background Python threads or asynchronous GPU work have ended;
late notebook output is not new activity.
antioch session release also runs without a confirmation prompt. Both commands
require --force to stop running work.
Fresh interactive and background preparation checks whether the declared resources fit a serving cell before uploading source, building, or copying images. This check reserves no capacity; admission checks the final revision again. Standalone builds do not need compute capacity.
Sync filters and build source
Watch respects .gitignore, .dockerignore, built-in development exclusions,
and each rule's ignore and include patterns. Watch ignore and include
patterns do not support ! negation; use positive patterns.
If no project-root sync is declared, the CLI copies the remaining project files
automatically. That implicit copy leaves authored sync targets alone, including
their ignored files and change triggers. A rule's filters apply to its own
target, not to separate copies made by other authored rules.
After a rule syncs successfully, deleting its local file or directory removes
only the remote paths that this rule previously synced to that session.
Commands remain usable while the path is absent. Recreating it syncs the new
bytes and triggers the rule's action. A path that never existed is still an
error.
Source capture for builds has different rules. It applies the platform floor
(.venv, venv, .git, Python caches, and node_modules) plus
.dockerignore, not .gitignore. The platform floor is never traversed or
included, even for a Dockerfile or an explicit ! pattern. User-ignored
directories are still visited so a later ! pattern can retain a descendant,
and nested build contexts keep their Docker files. The selected context's
.dockerignore is applied again with Docker semantics. Excluded paths do not count toward
source limits. Special files (FIFOs, sockets, and device nodes) are rejected;
exclude them with .dockerignore if they are not needed.
Work in a session
Run commands from the project directory to use its live interactive session.
run and service exec
start a session when none is live; inspection commands refuse and name
antioch session new, which starts compute explicitly. Outside a project,
a command that needs a session refuses.
antioch run src/main.py --seconds 60
antioch run --no-stream src/main.py
antioch service exec --no-stream python -m src.main
antioch service exec --service autonomy -- ros2 topic list
antioch session list
antioch service ps
antioch service logs SERVICE...
antioch service shell SERVICE
antioch service cp SERVICE:/workspace/project/output.png ./output.png
antioch session status
antioch session release
antioch session new prints a brief confirmation and the session ID when it is
ready. Use antioch session status for the revision, services, resources, and
readiness details.
Terminal lists keep IDs and the main status fields together. Add --verbose
to session list, scenario list, or suite list for additional metadata.
IDs remain complete on narrow terminals; rows wrap when they cannot fit.
scenario list and suite list show up to 10 matching runs by default. Add
--mine to show your own runs, or --limit 25 for a longer list. With --json,
both commands continue to default to 50 runs.
session list shows all your active and failed sessions for the current project,
including background sessions. Add --limit only when you want a shorter list.
Commands automatically select your interactive session, and session release
releases only interactive sessions. Cancel background work with scenario cancel
or suite cancel.
Human session list and session status output uses the same concise readiness
phrases as the console. These commands read durable session records, so
Session ready does not claim that commands are idle. Use service ps for
live service/process detail. JSON retains the original lifecycle states and diagnostics.
Copy files
Copy preserves symbolic links, including a link named as the source.
Uploads and downloads with service cp accept only paths inside
/workspace/project in the service. Other paths, including /tmp, are refused.
Use service exec to copy a file into the project before downloading it, or
to its final service path after uploading it into the project. The command runs
with the service's normal file permissions.
service cp can download owner-private files inside /workspace/project
without changing their modes or owners on the service. Downloads use a private
snapshot capped at 2 GiB of selected file sizes. This can refuse a large source
even when rsync would send only a small delta. Source inspection reads metadata
only. Each agent admits at most two active snapshots. Each snapshot has at most
20,000 filesystem objects and 128 path levels, including generated parent
directories; these limits also apply to metadata inspection. A busy agent
refuses the transfer without queuing it.
Execute commands and attach terminals
antioch run src/main.py runs src/main.py under the service's configured
project directory (/workspace/project in generated projects).
The local file must exist inside the project. Put Antioch options before the file and
script arguments after it. service exec runs an arbitrary command, including
Python modules and helper-service tools. Both stream process output, return
its exit status, and have a 900-second default deadline; set --timeout to
change it. A native script starts Isaac itself, usually through
antioch.start_simulation().
For run, an optional -- immediately after the file separates script
arguments; Antioch removes that separator and passes the remaining arguments
unchanged. For service exec, pass Antioch options before the executable;
the command and its arguments are passed unchanged. Both preserve repeated flags.
Use --service autonomy for a helper; a helper named python never changes
the meaning of python main.py. Use repeated --profile PROFILE options to
activate authored profiles when a session starts. Services without profiles
always run; services with profiles run only when one of their profiles is
enabled. If every service has a profile, select one explicitly. An empty
selection reports the available profiles; it never enables them all.
Source enters a session at startup. Later run and service exec commands use
the files already there; sync local edits with service sync or service watch.
Both commands forward stdin until EOF and return when the remote process exits,
even if local stdin stays open. When stdin and stdout are terminals, they allocate
a terminal and forward window-size changes. Use --tty or --no-tty to
override detection. Terminal output is one channel; non-terminal execution
keeps stdout and stderr separate. antioch service shell uses the same
transport for an interactive shell. Raw commands do not create scenario or suite history.
PTYs have no write-half-close: with explicit --tty, local EOF sends no
synthetic Ctrl-D. Use --no-tty for a piped program that must read until EOF.
Stream and choose picture quality
Each Isaac service has one native GUI stream. run and service exec request
that service's stream by default; --no-stream runs headless and leaves it
available to another process. A second process in the same service cannot
claim an occupied stream. Mission Control displays one selected service at
a time and follows the active scenario across services.
Attached scenario and suite runs use authored
SimulationConfig(stream=..., timeout_s=...) defaults unless CLI flags
override them. Mixed or partly missing defaults across a selection require
one explicit CLI value. Native scripts honor the start_simulation() stream
default, but their outer process deadline remains the CLI deadline.
Pick the picture quality in code before startup:
import antioch
antioch.start_simulation(antioch.SimulationConfig(renderer_quality="quality"))
renderer_quality is the one picture control. Each tier sets a stream
budget, the largest picture the encoder sends, and the RTX startup settings.
The browser keeps its own window shape and fits its screen pixels to the
32-pixel encoder grid, at most one grid step above them. Up to the budget the
picture is pixel exact; above it the browser scales the picture up. These
RTX settings can also affect sensor render products that use them:
| Preset | Stream budget | Startup settings |
|---|---|---|
performance |
1920×1088 | DLSS performance; reflections and translucency disabled |
balanced (default) |
2560×1440 | DLSS balanced |
quality |
3840×2176 | DLSS quality mode and DLAA anti-aliasing |
A streamed process boots at 1920×1088, and the native livestream resizes the
window to what the browser negotiates inside the budget. Headless work does
not start the stream encoder and renders the main viewport at 1280×720; use
extra_args native window or renderer settings to change that. Sensor camera
sizes never change with the preset.
Streaming keeps the native 60 FPS default. Antioch has no FPS control.
Displayed FPS measures video delivery, not physics steps or a guaranteed rate.
Native quality-of-service feedback can adjust delivery. physics_dt,
render_dt, and notebook idle rendering remain separate. Retired
stream_fps inputs are ignored with an ANTIOCH-DEP-010 notice.
The native renderer decides which settings apply to each render product.
Retired renderer inputs are listed in common.deprecations.
Explicit extra_args override preset flags; those arguments come last. After
startup, normal carb.settings or SimulationApp.set_setting() calls remain
yours; Antioch does not reapply the preset. The retired render_quality,
viewport, and stream_resolution inputs are ignored with ANTIOCH-DEP-008,
ANTIOCH-DEP-009, and ANTIOCH-DEP-013 notices. Their values are not
forwarded; a fixed stream size is no longer a setting. Unknown input names
still fail validation.
Process exit status
After antioch.start_simulation(), a clean exit returns 0, an uncaught
exception returns 1, and KeyboardInterrupt returns 130. Use sys.exit(n)
for an explicit status: a bare top-level raise SystemExit(n) in a headless
script can return 0 through Isaac's fast shutdown. Replacing
sys.excepthook without chaining the prior hook also replaces this error
handling.
Use Jupyter
Start an interactive session first. Jupyter uses its simulator service and
does not create a session, change profiles, or target background compute.
When several compatible services are active, choose one with --service on
jupyter lab, jupyter cell, and jupyter lab --stop, for example
antioch jupyter lab --service nav. The Jupyter MCP's jupyter_connect accepts
the same service selector. Each service's notebook server and credentials
remain independent; stopping one leaves the others running.
antioch session new
antioch jupyter lab
antioch jupyter cell '1 + 1'
antioch jupyter cell --stream 'import antioch; antioch.start_simulation()'
antioch jupyter lab --stop
Lab uses the service's reserved jupyter route. Cells execute on its live
kernel through Jupyter's REST and WebSocket APIs; a kernel starts if needed.
Use cell --kernel KERNEL_ID when Lab has several kernels. Without an explicit
ID, the CLI uses the sole kernel and refuses an ambiguous selection.
JupyterLab owns kernel management. Restart replaces only the kernel process,
not its simulation container or session. Failed new server startup stops that
server; an existing server is left running. jupyter lab --stop stops the server and
frees its service command slot. Kernels inherit Lab's GUI stream request. A
cell's --stream or --no-stream choice travels in its metadata and applies
only during that cell's execution. Use it on the cell that starts Isaac, not
an earlier cell. It does not reconfigure a simulator that is already running.
Older kernels still accept
ordinary cells but refuse these explicit flags before running the cell. Start
a new session, or set SimulationConfig(stream=True) or
SimulationConfig(stream=False) in the code that starts Isaac.
jupyter cell --json writes a successful result to stdout. A failed cell exits
1 and writes one error object to stderr. Its error.details.cell_result keeps
the kernel ID, execution count, stdout, stderr, display result, and exception
details that Jupyter returned. Connection and timeout failures do not invent a
cell result. The CLI does not retry the cell. The result's ordered outputs
retain rich MIME data, including PNG images, display updates, and clear events.
Output is capped at 8 MiB; outputs_truncated reports omitted messages while
the CLI still waits for the cell's final result. Plain terminal output shows
text and names image-only output; use --json to receive image data.
The kernel renders between cells and during cooperative await calls. It
does not advance physics or require a World wrapper. Long main-thread loops
must yield or call native Isaac updates. Python cannot render concurrently
with a blocking native call on that same thread. Interrupt or restart the
kernel to recover; a restart must not require a session reset.
jupyter lab prints and opens a private file:// launch URL. With --no-open,
open that exact URL in a browser on the same computer, with access to the same
filesystem. The file signs in to the verified loopback Lab server without
printing its token. Keep the command running: its local tunnel and launch file
close when the command ends. A browser on a different computer cannot use this
local file or loopback address directly.
Use agent tools
The paired plugin's agentic-simulation skill teaches the interactive loop.
antioch-jupyter-mcp connects to this project's existing session, lists kernels,
executes arbitrary Python, returns ordered outputs and images, and controls
the exact selected kernel. It does not allocate compute or inject simulator code.
The CLI owns project files, session creation, dispatch, and recorded evaluations.
After starting simulation once, ordinary notebook code can move the inspection camera and display a fresh frame:
from IPython.display import display
from antioch.lib import navigation, viewport
navigation.look_at(eye=(3, 3, 2), target=(0, 0, 0))
display(await viewport.observe_async())
Capture advances rendering, not physics; metadata reports unavailable frames. Inspect the pixels and measured state before claiming success. Interrupt requests a stop, not confirmed completion. Restart loses Python state: restore it from saved source, never replay uncertain side effects. Disconnect closes only local transport; idle transport also closes after 60 seconds. Kernel shutdown and GPU session release remain separate explicit actions.
Evaluate scenarios and suites
Keep Isaac imports inside functions. Scenario discovery runs locally without a simulator. The scenario guide and shipped examples cover authoring.
A scenario can select its execution container with @antioch.scenario(service="fluoro", ...).
Omitting service selects the only active service derived from a supported
Antioch image. With several eligible services, name the target explicitly;
leave services without profiles to start them together. An interactive suite
runs its children serially in their selected containers. Reruns retain those
targets.
Live Rerun telemetry follows the active scenario container. Authored viewer ports remain attached to their services. Native Isaac/WebRTC video follows the selected service when it provides a stream; selecting another container does not silently change rendering settings.
Submit and follow managed runs
antioch scenario collect
antioch scenario collect --scenario falling_cube
antioch scenario collect --scenario falling_cube --json
antioch scenario run --scenario falling_cube --set drop_height=4.5
antioch suite collect
antioch suite run smoke
antioch suite run smoke --background
antioch scenario show SCENARIO_RUN_ID
antioch scenario show SCENARIO_RUN_ID --json
antioch scenario download SCENARIO_RUN_ID
antioch scenario rerun SCENARIO_RUN_ID
antioch scenario cancel SCENARIO_RUN_ID
Use scenario collect --scenario NAME to show one exact authored scenario and
all its cases. Repeat --scenario to select several names, or combine it with
the optional file or directory path. An unknown name reports the available
names and exits with an error. Collection still validates every discovered
scenario under the selected paths. Without a name filter, human output keeps
its bounded preview and --json includes the complete catalog.
In terminals, scenario show summarizes the verdict, duration, checks,
artifacts, and any failure or wait reason. Parameters and results appear as
counts. Use --json for the complete saved record, including all parameters,
results, check details, errors, and startup logs.
Output redirected to a file or pipe retains the complete existing field layout.
--follow waits for completion and exits with the run's verdict; combine it
with --json for complete records as JSON events. Add --verbose to stream
process output while waiting.
Submission uses the project's interactive session and stays attached by
default. --no-follow returns after admission and keeps that session and
stream intent; Mission Control uses this mode and follows the returned IDs.
--background admits the work to headless background compute and returns;
--background --follow also watches progress. Background submission independently
builds the current YAML and applies no watch rules. Children use available
background sessions automatically within quotas and capacity; interactive
children remain serial. Suites also have show, rerun, and cancel commands.
Interactive runs use files already in the session. Syncing files can affect an active run; reruns preserve images and parameters, not these unbuilt edits.
For background work, --queue-timeout 30m sets a deadline for Antioch to
request execution, measured from the start of submission preparation. Build
time counts toward that deadline, but expiry does not interrupt a build.
After admission, a run whose deadline passes before execution is requested
is recorded as an error. Without this option, the deadline is 24 hours after
admission. --timeout 900 separately limits each scenario's execution to
900 seconds; if omitted, it uses the scenario's configured value or 900 seconds.
Scenario and suite commands show progress and verdicts while waiting for completion.
Add --verbose to include captured process output, including Isaac startup logs.
--no-stream controls the viewer stream; it does not control terminal logs.
Direct commands (antioch service exec) still stream their
process output by default.
Record from ordinary Python
Ordinary Python on your computer or over SSH records by default too. Run from
a valid Antioch project. A Scenario context also works in a notebook cell
or REPL with no source file. Sign in first, or supply an existing personal
access token. The full project manifest
is still required, including at least one service; caller recording does not
build or start those services, allocate a machine, create a revision, or boot
a simulator.
import antioch
with antioch.Scenario("inspection", capture=False, recording_timeout_s=900) as run:
run.raise_if_cancelled() # An explicit cooperative checkpoint, not a worker
run.check("inspected", True)
Source-backed @antioch.scenario(config=None, capture=False) functions use
the same recording path when called directly. A function with simulation
config still requires a compatible simulator that you have already started.
Decorated definitions still need a real source file inside the project.
Source-free managed contexts save their source as <kernel> and cannot be
rerun from history; execute the cell or context again instead.
Caller records have no revision and do not support managed rerun or live
streaming. Use Scenario(..., control=None) for deliberate offline execution;
missing auth, project, or managed context never selects offline mode for you.
recording_timeout_s defaults to 900 seconds and must be a finite positive
number at most 86400 seconds. This is the whole reporting window, including
artifact publication, with no renewal. Remote cancellation records intent;
your Python process stops cooperatively at run.raise_if_cancelled() or
observes it when the context closes. Deadline expiry closes the record but
does not prove that your process stopped.
A decorated scenario's Python callable omits the injected run argument and
returns run.results. Calling it records a run with telemetry and artifacts,
both in managed session commands and in authenticated caller-owned programs.
Caller recording requires a valid project but does not allocate compute or
start the simulator. Use Scenario(..., control=None) for explicit offline
recording, as described above.
Capture viewport images and telemetry
For an authored viewport image, call antioch.capture_viewport() between
physics steps on the main thread, outside physics, render, and Kit-update
callbacks. Headless and streamed processes use the same native viewport.
Set its camera or resolution with ordinary Isaac APIs, then capture. The
function waits for a new frame before pixel read-back and drives render-only
updates for up to ten seconds. It returns RGB pixels, or None if no viewport
or completed frame is available. It never returns an earlier call's cached
image or advances physics. Asset loading and scene lighting remain native
Isaac behavior. Callback contexts are unsupported and are not automatically
detected. Automatic recording is asynchronous: it uses authored render updates
and never renders from a physics callback. Code that disables rendering must
render explicitly when it needs images.
The scenario-design skill
owns capture and telemetry guidance. Native renderer readiness and material
settling are separate from a completed capture: Kit being app-ready does not
mean its viewport has rendered a frame. Before the first capture, call
ViewportManager.wait_for_viewport() (or await
ViewportManager.wait_for_viewport_async() in a notebook) and check the
returned readiness flag. Choose max_frames for renderer startup; this setup
wait is separate from capture's ten-second read-back deadline.
Log the returned RGB array with antioch.Logger("camera").image("front", rgb).
The first frame, downsampled to max_width, sets that entity's canvas for the
current recording. Later frames keep their aspect ratio and fit inside it;
black borders fill unused space. They are not cropped, stretched, or upscaled.
max_width still limits content resolution and jpeg_quality applies to each
frame. Another entity or a new recording chooses its own canvas. This keeps
live and saved Rerun playback compatible when the source viewport resizes.
Recover recordings
If artifact upload or terminal acknowledgement fails, managed scenarios keep
their default recording and runner output in an owner-private directory under
the project and report its path. Recover that directory with service cp
before the session stops. The retained files are not durable artifacts.
Explicit recording paths and unmanaged local runs keep their chosen paths.
Caller recording keeps unconfirmed default files in an owner-private local
temporary directory and reports that recovery path. Successful publication
removes that temporary directory. A local file alone is not a durable artifact.
Follow output and cancel runs
Submission displays its current phase in one transient line. Redirected
output and TERM=dumb use plain phase changes instead of animation;
FORCE_COLOR never adds terminal controls to a pipe. NO_COLOR disables
color without disabling progress. With --json, progress is a stream of
newline-delimited JSON objects with no human messages mixed in.
Help stacks option descriptions in narrow terminals. With --verbose, CLI
messages appear on separate stderr lines so they do not run into process output.
Redirected stdout, native exec output, and JSON remain unchanged.
Ctrl-C during an interactive run requests cancellation and waits for the saved terminal outcome. A second Ctrl-C stops waiting and prints a command to view progress. Both presses remain responsive while the CLI waits for a server response. Remote cancellation and cleanup are not confirmed until the saved result says they are complete. The summary reports the session's current state; cancelling a run does not stop its interactive session. For background work, Ctrl-C stops the local progress display and leaves the run active. During submission, an interruption stops the client; if admission may already have reached Rome, the CLI gives the identity to inspect. A remote build that has started can continue after the client exits.
Rerun saved work
A rerun gets a new ID and reuses the original revision, service images, parameters, and selection. It does not rebuild or resolve moving tags. Unbuilt interactive edits are not preserved. A runtime below the supported minimum is refused before allocation; its saved history remains readable. Exact inputs do not guarantee the same outcome or timing: scheduling, simulator behavior, and external asset availability can differ.
Run in CI with a personal access token
For an unattended workflow, open Settings > Personal access tokens, create
a token with a finite expiry, and copy its secret once. Save it as a GitHub
Actions repository secret named ANTIOCH_TOKEN, then pass it to the step that
runs Antioch:
- name: Run simulation suite
env:
ANTIOCH_TOKEN: ${{ secrets.ANTIOCH_TOKEN }}
run: antioch suite run smoke --background --follow
CI needs no browser login and must not create or copy auth.json. The CLI reads
ANTIOCH_TOKEN directly and does not persist it in the local credential store.
Assets and immutable builds
Assets are named file versions from your organization or Antioch's shared library. Pin their versions for repeatable evaluations.
antioch asset list
antioch asset show ASSET
antioch asset pull ASSET --version ASSET_VERSION --output ./asset.usdz
antioch asset push ./asset.usdz --name ASSET --version ASSET_VERSION
antioch asset verify ASSET --version ASSET_VERSION
antioch project show
antioch project build
antioch project revision list
Python offers antioch.fetch_asset, antioch.load_asset, and
antioch.save_asset.
Inspect projects and build revisions
Every antioch project command acts on the project of the working directory.
antioch project show prints the project's registry facts and one row per
service: its source (build with the Dockerfile path, or image), the GPU
class of the machine it lands on, its CPU and memory requests, and the
profiles that activate it. A manifest that declares more than one
placement group gets a GROUP column; this release refuses a session that
spans groups. antioch project show PROJECT and
antioch project list are the doors to other projects in the organization.
Project builds need no simulation session. They finalize immutable revisions
and reuse a cached build only when its content-derived key matches an
immutable digest and the expected OCI labels. antioch project revision
lists, shows, and tags the current project's revisions; --json carries the
full image digests. Revision tags name existing revisions; moving one does
not rebuild anything.
A failed build reports a bounded build-log tail in the terminal error and
the JSON error's message. Reading that tail does not retry the build.
If the retained log is unavailable, the build failure still reports its
operation ID and cause. JSON retryable carries the build operation's verdict.
Retired inputs
Known retired inputs are ignored or refused with a coded deprecation notice. They do not restore old behavior. Remove them when updating a project:
| Code | Ignored input | Current behavior |
|---|---|---|
ANTIOCH-DEP-001 |
A watch rule with action: rebuild |
The whole rule is dropped; image changes need a fresh session |
ANTIOCH-DEP-002 |
Run --parallel or request requested_parallelism |
Background fan-out is automatic |
ANTIOCH-DEP-003 |
Run request project_tree_digest |
Source comes from the frozen revision and image |
ANTIOCH-DEP-004 |
Preflight request profiles |
Admission owns selection |
ANTIOCH-DEP-005 |
antioch plugin install |
No action; use antioch setup |
ANTIOCH-DEP-008 |
SimulationConfig.render_quality |
Value is dropped; set renderer_quality explicitly |
ANTIOCH-DEP-009 |
SimulationConfig.viewport |
Value is dropped; renderer_quality sets the stream picture budget |
ANTIOCH-DEP-011 |
Live service rebuild from an older CLI | Refused; copy source into the image and start a new session |
ANTIOCH-DEP-012 |
SimulationConfig.renderer_quality="ultra" |
Value selects quality; frame generation is retired |
ANTIOCH-DEP-013 |
SimulationConfig.stream_resolution |
Value is dropped; renderer_quality sets the stream picture budget |
CLI notices use stderr; with --json, each is a JSON object under notice
with type, code, message, and region. Command stdout is unchanged.
Python callers receive common.deprecations.AntiochDeprecationWarning, a
visible FutureWarning with a structured notice attribute. Unknown inputs
still fail validation. These notices do not bypass SDK or runtime version checks.
An older CLI is never refused for its age. When it calls a route the deployment
no longer serves, or cannot read a newer response, the message names the
deployed SDK version and the one update path: install that version with uv,
then run antioch setup and antioch project update.
Command help and scripts
Use antioch --help or a command's --help for the current option list.
Most non-interactive commands support --json: data goes to stdout,
diagnostics to stderr. Single repeatable mutations use changed: false for an
already-complete action. Setup instead reports each selected component and its
uv/build actions, as described above; a no-op update still exits 0.
The full customer guide is in the Antioch docs.
Metadata
Release files for antioch-sim 0.4.320
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| antioch_sim-0.4.320-py3-none-any.whl | Python 3 | none | any | Details |
Release files / antioch_sim-0.4.320-py3-none-any.whl
| Download URL | antioch_sim-0.4.320-py3-none-any.whl |
|---|---|
| Size | 26.3 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
74be8af329556880c4c23d8114a2f91d9cabe78b4677c7ebc0e7f07c69e570e9
|
|
BLAKE2b-256 checksum How to use checksums |
510e33a18545a8eb5cfc8b58d81536fdbf005a6105f009f1c00547aef0a087de
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|