Raw SDK Primitives
While the TrainingLoop API provides a convenient wrapper, it is a thin layer over the OmniLoop SDK primitives. You can call these primitives directly for full control over your execution flow and telemetry.
When to use
Section titled “When to use”Use the raw primitives when:
- You need to integrate OmniLoop into an execution flow you cannot easily restructure (e.g., a C++ engine calling into Python).
- You need fine-grained control over exactly what gets published and when.
- You do not have a centralized configuration dataclass to derive a schema from.
Basic Usage
Section titled “Basic Usage”When using raw primitives, you must manually define your parameter schema, block on halts, poll for mutations, and publish telemetry.
import jsonfrom omniloop import tracker, load_param_schema
# 1. Define schemaload_param_schema("my_params.yaml") # or use declare_param(...)
for epoch in range(num_epochs): # 2. Pause point: block if the dashboard has halted the loop tracker.wait_if_halted()
# 3. Apply dashboard edits mutations = tracker.get_mutations() if "learning_rate" in mutations: lr = float(mutations["learning_rate"])
# ... your application logic ...
# 4. Publish telemetry tracker.publish_telemetry_raw(json.dumps({ "learning_rate": lr, "reward_mean": reward_mean, # ... other state ... }))Core Methods
Section titled “Core Methods”| Method | Description |
|---|---|
tracker.wait_if_halted() |
The halt barrier. Call once per iteration. Blocks until resumed under the default block policy; returns immediately under handoff/advisory, where the caller reads poll_halt() instead. |
tracker.poll_halt() |
Non-blocking barrier. Returns action (run / run_safety / released), halted, reason, escalation, halted_for_ns — all as strings. run_safety means: run your fallback controller this iteration, not the loop body. |
tracker.set_halt_policy(p) |
"block", "handoff" or "advisory". Local-only by design — no IPC command sets it, so a remote operator cannot make a hardware loop freeze its own control thread. |
tracker.step_barrier() |
Consume single-step mode. Call only after an iteration that ran the real loop body. |
tracker.set_halted(halted, reason=None) |
Halt or release, optionally recording operator / watchpoint / exception / step. |
tracker.get_mutations() -> dict |
Returns parameter edits from the dashboard since the last call. Keys are parameter names; values are strings. |
tracker.publish_telemetry_raw(json_str) |
Publishes a JSON-encoded state snapshot to the shared-memory channel. |
tracker.register_variable_pointer(name, addr, var_type) |
Register a raw memory pointer for zero-copy reflection. |
Advanced & Diagnostic Methods
Section titled “Advanced & Diagnostic Methods”| Method | Description |
|---|---|
tracker.add_watchpoint(name, condition, threshold) |
Arms a conditional halt (e.g., halt if a metric exceeds a threshold). |
tracker.set_watch_all_nonfinite(bool) |
Automatically halts the loop on any NaN or inf value. |
tracker.stats() -> dict |
Returns IPC health counters. |
tracker.dump_flight_recorder(path) |
Dumps the black box ring buffer to disk. |
tracker.set_flight_recorder_capacity(n) |
Sets the capacity of the ring buffer. |
tracker.state_hash(exclude=[...]) -> int |
Hashes the registry’s canonical state to help detect divergence. |
Safe halt on the raw primitives
Section titled “Safe halt on the raw primitives”wait_if_halted() is policy-dependent, which matters most for the loops that use
these primitives — they are usually the ones closest to hardware. A raw loop that
must not stop looks like this:
tracker.set_halt_policy("handoff")
for _ in range(steps): decision = tracker.poll_halt() if decision["action"] == "run_safety": damping_hold() # halted: keep commanding the machine else: controller_update() # running normally tracker.step_barrier() # spend a step only on a real iteration tracker.publish_telemetry_raw(json.dumps(state))Note that poll_halt() returns strings, and halted is Rust’s lowercase
"true"/"false" — not Python’s "True". Compare case-insensitively.
See Halt & Step for the policies, halt reasons, and the deadman.
Session Isolation
Section titled “Session Isolation”If you run multiple concurrent instances of your application, you must isolate their OmniLoop sessions to prevent IPC collisions.
- Set the
OMNILOOP_SESSION_IDenvironment variable before starting your process. - Alternatively, use the CLI wrapper which handles this automatically:
omniloop up --session my_run