Is OmniLoop for me?
Most of this documentation is about robots and reward terms, because that is where OmniLoop was built and where it earns the most. That is a statement about our examples, not about the engine.
omniloop-core is a registry of named live variables, a set of numeric
predicates over them, a barrier, and a journal of opaque frames. It contains no
concept of a joint, a policy, an episode or a gradient — grep it. Every
domain-specific thing lives in the optional adapters above it.
So the useful question is not “do I work on robots”. It is the five below. They are what actually decides whether this tool pays for the twenty minutes of instrumentation it costs.
The five preconditions
Section titled “The five preconditions”1. Your work happens in a repeating tick
Section titled “1. Your work happens in a repeating tick”There has to be somewhere to put with loop.tick(): — an iteration, a sweep, an
epoch, a control cycle, a frame. Everything OmniLoop does happens at that
boundary: edits are applied there, tripwires are evaluated there, the barrier
blocks there, telemetry is published there.
If not: a single long-running call with no interior structure gives OmniLoop no place to stand. A profiler or a sampling debugger is the better tool.
Consequence worth planning for: your tick granularity is your detection granularity. A tick that runs a hundred solver sweeps internally cannot be halted between sweeps ninety and ninety-one.
2. The state in memory is expensive to reconstruct
Section titled “2. The state in memory is expensive to reconstruct”This is the whole value proposition, and the one people skip. Model weights, a replay buffer, a loaded simulation world, a converged field, a warmed cache, an open hardware session, forty minutes of accumulated integration.
If not: if your process rebuilds its state in ten seconds, restarting is the better debugger. It is simpler, it is reproducible, and it does not require a control plane. Use one.
3. Your knobs are scalars and booleans that survive being changed mid-flight
Section titled “3. Your knobs are scalars and booleans that survive being changed mid-flight”Learning rate, gain, timestep, threshold, coefficient, a feature toggle. Something whose value can change between two ticks and leave the run still meaning something.
If not: changing a network architecture, a mesh, or a data schema mid-run does not produce a tuned run, it produces an incoherent one. Those belong to the next process, not this one.
4. Your failure mode is numeric and quiet
Section titled “4. Your failure mode is numeric and quiet”NaN propagation, gradient explosion, reward collapse, solver divergence, a value drifting out of its envelope over ten thousand ticks. Failures that produce a bad number long before they produce a stack trace — and that, when they finally do crash, name a line that is not where the problem started.
If not: for a clean exception on a reproducible input, pdb is right there
and it is better at this than we are. Where OmniLoop wins is the class of fault
that a traceback describes badly and a restart cannot reproduce.
5. You can reach the process on loopback, and you are allowed to write to it
Section titled “5. You can reach the process on loopback, and you are allowed to write to it”OmniLoop OSS has no authentication worth the name and mutates live process memory through raw pointers. The supported topology is one operator reaching their own process, directly or through an SSH tunnel — see Tethered Deployment, which covers a robot on your bench and a training node in a rack equally.
If not: a multi-tenant service, a production job with an on-call rotation, or anything where “who changed that” needs a real answer is out of scope for the OSS build. Static tokens can name principals in a journal; they are not an identity system, and we would rather say so here than have you find out.
Reading your score
Section titled “Reading your score”- Five out of five — OmniLoop is aimed directly at you, whatever your field is called. Go to the Quickstart.
- Four, missing #5 — the capability fits and the topology does not. Read Tethered Deployment before deciding; an SSH tunnel resolves most of these.
- Missing #2 — stop. Restarting is cheaper than instrumenting. This is the one that makes the difference between a tool that pays for itself in a day and a dependency you regret.
- Three or fewer — the parts you would use are the parts anything can do.
Where this lands in practice
Section titled “Where this lands in practice”Being concrete, including about the cases we are not the answer for.
| Workload | Fit | Why |
|---|---|---|
| RL / policy training, sim or real | Strong | Every precondition, plus the halt actually has to mean something different on hardware. The original case. |
| Large-model training and fine-tuning | Strong | Days-long runs, an LR you want to move, and a loss spike at hour forty that costs more than the tooling ever will. |
| Numerical simulation — CFD, FEA, MD, climate, plasma | Strong | Unreconstructible state and quiet divergence, exactly. See Computational Steering. |
| Embedded control and HIL benches — motor drives, inverters, BMS, flight controllers | Strong | The C++ SDK, hard limits and the read-only build were built for exactly this shape, robot or not. |
| Long solver runs — MIP, CP, global optimisation | Partial | Preconditions hold, but most solvers already expose callbacks that cover the common half of this. |
| Game and engine parameter tuning | Partial | Real need, already solved: Unity and Unreal ship live tuning natively. |
| Agentic AI / LLM evaluation runs | Weak | The loop looks right, but state is cheap to rebuild and microseconds are irrelevant — every advantage this engine has is worth nothing here. |
| ETL and data pipelines | Weak | State lives in a database and restart granularity is per-task. |
| Web services, request handlers | No | No tick, no expensive resident state, and precondition #5 is a security incident. |
What OmniLoop is deliberately not
Section titled “What OmniLoop is deliberately not”- Not an experiment tracker. It has no opinion about runs, sweeps or leaderboards, and exports to MCAP for those pipelines rather than competing with it.
- Not a profiler.
__tick_duration__tells you a tick got slower. It will not tell you which line. - Not a general-purpose debugger. No breakpoints on arbitrary lines, no expression evaluation, no stack walking. Watchpoints are predicates over registered variables, evaluated at tick boundaries.
- Not production monitoring. One operator, one process, loopback. Everything about the security model assumes that and says so.
If you came here from ROS 2
Section titled “If you came here from ROS 2”Three of the loudest complaints from teams shipping ROS 2 on real machines are not things OmniLoop touches, and it is worth saying so before you install it:
- DDS and QoS tuning. Discovery storms, reliability and history settings, the node count at which your vendor’s middleware stops behaving. OmniLoop observes a tick; it is not in the transport.
rosdepand container image size. A workspace image measured in tens of gigabytes is a packaging problem. Adding a journal to it makes it very slightly larger.- Callback groups and executors. Which callbacks can run concurrently, and why yours deadlocked, is a question about the ROS 2 executor. OmniLoop can show you that a tick stopped arriving, and gives you the state at the moment it did — it cannot tell you which callback group caused it.
What we do address from that same list: safe halt with an operator handoff (see Halt & Step), deterministic replay of a recorded run, and a journal that stays readable without a version-matched workspace, because the schema travels inside the file.
Naming
Section titled “Naming”The Python entry point is available under two names for one class:
from omniloop import Loop # generic — a solver, a simulation, a controllerfrom omniloop import TrainingLoop # identical object, the name to read in a training scriptLoop is what the C++ and Rust
SDKs already call it. Neither name is deprecated and neither is a wrapper —
Loop is TrainingLoop is true, so isinstance and pickling work through
either. Use whichever one a reader of your code would find less surprising.