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 service exec defaults 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
These examples use uv and require public production publication of the named SDK. For staging, use the private project install instead of the PyPI command below, or the approved global CLI bootstrap. A staging release does not make that version available on PyPI.
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.196"
source .venv/bin/activate
antioch auth login
antioch init
antioch service exec python src/main.py
The SDK resolves from PyPI. Use antioch-sim[isaac-lab]>=0.4.196 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 service exec starts or reuses an
interactive session and runs the command. A new session builds the current
project; use 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 or update a released environment
One command installs or updates this computer for one deployment and checks that the result works:
antioch setup
antioch setup --dry-run
ANTIOCH_ENV=staging antioch setup
antioch setup reads the deployment from ANTIOCH_ENV, as every antioch
command does, and selects production when it is unset. Set
ANTIOCH_ENV=staging in the shell to work against staging.
Setup selects the deployed SDK version, not the newest package on an index. The
SDK wheel binds the exact plugin version and tree. Staging also verifies the
existing signed delivery record with your gcloud credential. Production needs
no cloud-provider login. Missing or conflicting artifacts stop setup before
installation.
Setup installs the SDK as a global uv tool, or into one existing virtual
environment with --python .venv/bin/python. Every Claude Code or Codex client
on PATH gets the deployment's verified plugin through the client's own
marketplace and plugin commands; a host without an agent gets only the SDK.
Setup then checks that the installed CLI is signed in to the deployment and that
the Research server answers a real call. It never signs in. A failed check exits
1 after reporting every component and names the exact next step, such as
ANTIOCH_ENV=staging antioch auth login. --dry-run reports what would change
and installs, configures, and checks nothing; native client inspection can still
write that client's ordinary logs. Setup never edits a shell profile or a project.
Setup text and JSON report the same components. mode is plan for a dry run
and apply otherwise. sdk, plugin_tree, and each entry of the agents map
are current (verified before this call), planned (a change is needed but not
applied), or changed (this call changed and verified it). plugin_tree is
null on a host without an agent. authentication and research are ok,
failed with a detail naming the next step, or planned on a dry run.
release is the deployed source commit; sdk_version and plugin_version name
the verified pair. Inside a project whose pyproject.toml owns antioch-sim,
project_sdk reports that project's .venv interpreter and whether it is
current; a project that is behind gets the antioch project update next step.
It is null elsewhere. Setup never edits the project.
Update a project to the deployed release
antioch project update --dry-run
antioch project update
antioch project update converges the current project, never this computer. It
changes literal engine tags in all declared profiles, keeps engine families, and
updates an active direct antioch-sim dependency with its 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.
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.
Bootstrap and rollout limits
Production setup requires public deployment metadata and a published paired SDK; staging uses signed private delivery. Setup refuses missing metadata or an unverified pair before installation.
For a global production CLI, use uvx --from antioch-sim antioch setup once
a setup-capable SDK is published. For staging, use the approved portable installer below; the
infrastructure runbook
owns the reader grants behind it.
The private project install below configures a
project dependency; the index's newest candidate is not an accepted-release
selector.
An authorized staging reader uses the retained portable installer when the
published channel contains an independent SDK/plugin pair. Obtain its exact
ANTIOCH_PRIVATE_INSTALLER_URI (including object generation) and
ANTIOCH_PRIVATE_INSTALLER_SHA256 from the reviewed accepted SDK artifact
record, verify the bytes, and run the installer only after the digest check
passes:
gcloud storage cp "$ANTIOCH_PRIVATE_INSTALLER_URI" private-installer.pyz
python3.12 -I -c 'import hashlib, os, pathlib; actual = hashlib.sha256(pathlib.Path("private-installer.pyz").read_bytes()).hexdigest(); expected = os.environ["ANTIOCH_PRIVATE_INSTALLER_SHA256"]; assert len(expected) == 64 and actual == expected, "installer digest mismatch"' \
&& ANTIOCH_ENV=staging python3.12 -I private-installer.pyz --json
The installer imports no installed SDK, verifies signatures and exact wheel/plugin bytes against the accepted channel before installing, never selects a pending candidate, and uses existing gcloud credentials without signing in.
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.196
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.
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. Running commands,
open shells 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.
A shell or a command that keeps running can still hold a session indefinitely. The platform cannot tell whether that work was forgotten. Close shells and stop commands when finished; there is no absolute session time limit.
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.
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
Every command acts on the project of the current directory and its one live
interactive session; there is no session selector. service exec starts 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 service exec python src/main.py --seconds 60
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
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
Commands stream process output and return its exit status.
service exec has a 900-second default deadline; set --timeout to change
it. A native script starts Isaac itself, usually through
antioch.start_simulation().
Pass Antioch options before the command. Everything from python, bash, or
another executable onward is literal argv, including repeated flags and --.
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.
Exec forwards stdin until EOF and returns when the remote process exits, even
if local stdin stays open. When stdin and stdout are terminals, exec allocates
a terminal and forwards 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
A session has one Isaac GUI stream. service exec requests it by default;
--no-stream runs headless and leaves it available to another process.
A second process cannot claim an occupied stream. Mission Control shows the
active stream to one viewer at a time.
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.
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 run --scenario falling_cube --set drop_height=4.5
antioch suite collect
antioch suite run smoke
antioch suite run smoke --detach
antioch scenario show SCENARIO_RUN_ID
antioch scenario download SCENARIO_RUN_ID
antioch scenario rerun SCENARIO_RUN_ID
antioch scenario cancel SCENARIO_RUN_ID
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.
--detach admits the work to headless background compute and returns;
--detach --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.
Following a scenario or suite shows progress and verdicts, not process output.
Add --verbose to include captured 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. --json follows emit only NDJSON frames,
with no human progress mixed in.
Help stacks option descriptions in narrow terminals. Verbose follow separates CLI messages from an unfinished child line on stderr, without adding bytes to redirected stdout, native exec output, or JSON frames. After Ctrl-C, human progress stays quiet while the CLI waits for the saved terminal outcome.
Ctrl-C during an interactive run requests cancellation and waits for the saved terminal outcome. A second Ctrl-C stops waiting and prints the follow command. Both presses remain responsive while a follow read is waiting for a 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. Ctrl-C while following detached work only stops following it. 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 --detach --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.
Private staging SDK
Staging uses Antioch's Google Artifact Registry Python index. Your account must belong to the staging SDK reader group. Authenticate with the Google Cloud CLI, then install the credential helper:
gcloud auth login
uv tool install keyring --with keyrings.google-artifactregistry-auth
uv tool update-shell
Open a new terminal. Verify that the helper can obtain a short-lived credential without printing it:
keyring get \
"https://us-central1-python.pkg.dev/antioch-poc-2607/sdk/simple/" \
oauth2accesstoken >/dev/null
Add this credential-free configuration to the project's pyproject.toml:
[tool.uv]
keyring-provider = "subprocess"
[tool.uv.sources]
antioch-sim = { index = "antioch-staging" }
[[tool.uv.index]]
name = "antioch-staging"
url = "https://oauth2accesstoken@us-central1-python.pkg.dev/antioch-poc-2607/sdk/simple/"
explicit = true
authenticate = "always"
Replace <sdk-version> below with the exact version approved for the staging
deployment. Use the same command to install, upgrade, or downgrade:
uv add --compile-bytecode "antioch-sim[isaac-sim]==<sdk-version>"
The fixed username oauth2accesstoken is not a credential. This configuration
writes neither an access token nor another secret to the project or lockfile.
Commit pyproject.toml and uv.lock; authorized readers can reproduce the
environment with uv sync --frozen.
The index retains candidates and historical wheels, so an unpinned install
is not an approved-release selector. Installing an old wheel does not
guarantee that staging still serves a compatible runtime. Check the selected
SDK with antioch --version and keep the project's engine tag in sync.
For 401 Unauthorized, check that keyring is on PATH and repeat
gcloud auth login. For 403 Forbidden, check reader-group membership and
the active account. An existing GOOGLE_APPLICATION_CREDENTIALS setting or
Application Default Credentials login can select a different identity. See
the Artifact Registry authentication guide
and uv's Google integration guide.
The full customer guide is in the Antioch docs.
Metadata
Release files for antioch-sim 0.4.281
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.281-py3-none-any.whl | Python 3 | none | any | Details |
Release files / antioch_sim-0.4.281-py3-none-any.whl
| Download URL | antioch_sim-0.4.281-py3-none-any.whl |
|---|---|
| Size | 26.3 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
80d407ac192c694fd11cbc9eb63700b165dffead238a6e96d7c0b445acb9b022
|
|
BLAKE2b-256 checksum How to use checksums |
e1d545cd4ef63226406b423109873161b1605d781a6ec8a92fb69bdebf00ccf2
|
| 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}
|