SDK & CLI

submit runs with the Platform SDK; control MuJoCo/PX4 with the Runtime SDK

Base URL https://sim-orch.sverk.io · Auth a bearer token (get one on Settings, or an admin mints one on Admin). The Platform SDK submits and observes runs through REST/SSE. The optional Python Simulation Runtime SDK runs inside a job and exposes MuJoCo + PX4 as Gymnasium. Full control-plane surface: API reference.

Python Platform SDK — sverk-simolyot

Stdlib only. Importing Client does not load MuJoCo, PyTorch, or PX4 dependencies.

pip install sverk-simolyot
from sverk_simolyot import Client

# base_url from POLYGON_URL, token from POLYGON_TOKEN on the live deploy
c = Client("https://sim-orch.sverk.io", token="slt_…")

print(c.whoami())                 # {'kind': 'user', 'org_id': '…', 'scopes': [...]}
for s in c.list_stacks():         # which base environments can I run on?
    print(s["name"], "->", s.get("display_name", ""))

# Submit a run — only `stack` is required; inline code goes straight in.
job = c.submit_run(
    "mujoco",
    command=["python", "main.py"],
    workspace="inline://print('hello from the pool')",
    env={"POLYGON_SETUP": "pip install numpy"},
    limits={"cpu_cores": 2, "ram_gb": 4, "timeout_sec": 600},
    outputs=[{"artifact": "model", "glob": "model.zip"}],
)
job_id = job["job_id"]

# Block until terminal, then read the outcome + artifacts.
final = c.wait(job_id, poll_interval=3.0)
print(final["phase"], final.get("final_metrics"))
for a in final.get("artifacts", []):
    print("artifact:", a["artifact"], a["ref"])

Prefer live updates? stream() is a generator of events (log | metric | phase) that ends at a terminal phase:

for ev in c.stream(job_id):
    if ev.kind == "metric": print("metric", ev.step, ev.values)
    elif ev.kind == "log":  print(f"[{ev.stream}] {ev.line}")
    elif ev.kind == "phase": print("phase ->", ev.phase)

Python Simulation Runtime SDK — MuJoCo + PX4

Python 3.10+. Installed in the mujoco-sb3-px4 image; locally it is an optional extra. Real PX4 SITL is the default, while px4-style and direct are fast software modes.

pip install "sverk-simolyot[mujoco-px4]"
from sverk_simolyot.sim import DroneSim

with DroneSim(
    scenario="playground",       # playground | pursuit | drone-overwatch
    initializer="hover",
    control="px4",               # real PX4 SITL
) as env:
    obs, info = env.reset(seed=42) # lazy boot → HIL → OFFBOARD → ARM → hover
    obs, reward, terminated, truncated, info = env.step(env.action_space.sample())
    print(env.state())

# Diagnostics in the stack image:
# python -m sverk_simolyot.sim selfcheck

The ready trainer is PPO-only in v1. A run still needs an explicit command; choosing the stack alone never starts training.

from sverk_simolyot.rl import PPOTrainer

result = PPOTrainer(
    scenario="playground",
    initializer="hover",
    control="px4",
    total_timesteps=150_000,
    n_envs=1,
    seed=42,
).train()

# Container commands:
# python -m sverk_simolyot.rl train
# python -m sverk_simolyot.rl eval --model /inputs/model.zip

Node / TypeScript — sverk-simolyot

Node 18+ (global fetch), zero runtime deps, ESM + CJS. OpenAI-SDK-style ergonomics; Client is an alias of Simolyot for parity with Python.

npm install sverk-simolyot
import { Simolyot } from "sverk-simolyot";

const client = new Simolyot({ baseUrl: "https://sim-orch.sverk.io", token: "slt_…" });

const run = await client.runs.submit({
  stack: "mujoco",
  workspace: { type: "git", ref: "https://github.com/user/repo#main" },
  command: ["python", "train.py"],
  config: { episodes: 50, seed: 42 },
  limits: { cpu_cores: 2, ram_gb: 4, timeout_sec: 1800 },
  outputs: [{ artifact: "model", glob: "model.zip" }],
});

for await (const ev of run.events()) {       // live logs / metrics / phase (SSE)
  if (ev.kind === "log") console.log(ev.line);
}

const { final_metrics } = await run.get();   // { ep_rew_mean: 231.5, … }
const [model] = await run.artifacts();
await run.download(model, "./model.zip");

CLI — polygon

export POLYGON_URL=https://sim-orch.sverk.io
export POLYGON_TOKEN=slt_…

polygon stacks                       # what you can run
polygon run --stack hello-sim --wait --follow
polygon jobs                         # your run history
polygon logs <job_id>

curl — the raw wire

Everything a person does in the UI is an API call; the SPA is just a client of this surface.

TOKEN=slt_…
BASE=https://sim-orch.sverk.io

# submit a run (hello-sim is a zero-dependency demo)
JOB=$(curl -s -X POST $BASE/v1/jobs \
  -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" \
  -d '{"stack":"hello-sim"}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["job_id"])')

# stream its logs live (SSE; token via query — EventSource can't set headers)
curl -N "$BASE/v1/jobs/$JOB/events?token=$TOKEN"
Mint a service token with a role for backend-to-backend use (an LMS, another product): submit a user’s run, poll or stream status, fetch artifacts, and gate on the final phase — the user never sees a platform credential. Org tenancy isolates every caller; per-org concurrency quotas apply.