Technical specifications
Routedge is a policy gate and a decision record, not an inference engine. It checks a supervisory decision against a rule you wrote and signs it into a tamper-evident chain; model routing is its first adapter. Every figure on this page comes from the vehicle it is deployed on — a working inspection class ROV — or from a bench run, or is marked as not yet run.
Routedge is validated on a working underwater vehicle rather than a desk. It is deployed there as a managed service, running beside that vehicle's own autonomy software, on the vehicle's own computer — an 8 GB single board ARM machine on tether power, with its camera and sensors live. Everything below happened on that vehicle unless it says otherwise.
Nothing has been under water or under thrust. The thrusters and their drivers were unpowered throughout, the computer sat outside the pressure hull, and the tank run is on hold — for reasons on the vehicle, not in this software. Hull temperature in a sealed enclosure is unmeasured; the open air peak was 64.5 °C.
The supervisory hold results used simulated sensors. The vehicle's software ran with its sensors stubbed so detections could be injected, so the hold path is proven end to end but has not been driven by a real detector on a real camera. On that board there is also no processor headroom left for one: a substitute detector load pushed the vehicle past the budget its own control loop is held to.
Two edges worth knowing before you ask. An outage that begins while a request is already in flight is the weakest case — it is held when the link refuses or goes silent, but a request already waiting on an answer sits out its timeout. And the record's timestamps are only as good as the vehicle's clock: this board has no battery backed one, and a deliberate ten minute clock step during a mission was enough to make the vehicle's own software abort for the wrong reason. The chain still verifies and the decisions are still sound; the wall clock times around such an event are not.
ARM and x86 Linux, Python 3.9 to 3.13, as a native service or a container. It speaks HTTP, including the OpenAI-compatible chat API for the model routing adapter, and talks to any model server that speaks the same — on the vehicle it runs against Ollama. The cloud side works with OpenAI-compatible endpoints and with Anthropic's API directly. Inference frameworks, quantization and accelerators are deliberately absent from that list. Whether your model runs through a GPU optimized runtime, a CPU build or a dedicated accelerator is your model server's business, and Routedge sits in front of it without needing to know — so you can change any of that without changing anything here. A second ARM target and a general decision adapter beyond chat are intended and not yet built; neither is claimed.
Four constraints decide whether inference survives on a vehicle. Each one below is something we put the board through rather than reasoned about.
A sealed bay with a failed fan does not announce itself. The hardware quietly reduces its own clock, and inference that met its deadline yesterday misses it today. A temperature rule can return a safe answer before that happens.
Warning 42–56 s ahead of the slowdown, across four runsSupply voltage and battery level are read continuously, so a rule can step down before the board turns unreliable. The harder question is what the record looks like when power simply goes away while it was writing — which it did, twice and unexplained, on the vehicle.
5 hard pulls while it was writing: 0 entries lost, chain verified every timeThe failure that ends long missions is a slow leak, not a crash on hour one. The router itself has to stay small and stay flat, and the model server beside it has to be watched for the same thing.
Router ≈ 74 MB, +0.2 MB over 8 h; record growth ≈ 0.65 MB/hOn a metered satellite link or an acoustic modem, the cheapest request is the one that never leaves the vehicle. Every request the local model answers is uplink you did not spend and API budget you did not burn.
On the ROV, 961 of 961 routine requests never left the vehicleOne process on the vehicle, on the decision path and nowhere else. It replaces nothing below it and requires nothing above it — and it never sits between a controller and an actuator.
The same five steps every time. Steps 1, 2 and 5 happen on a bench; 3 and 4 happen on the vehicle.
Fig. 2 — LifecycleBench to field and back
Routedge answers the same requests your client already sends. Point the client at it; the request body, the streaming behaviour and the response shape are unchanged. There is no SDK to adopt, because there is no new protocol to learn.
Pythonone line changes
# before — straight to a cloud endpoint
client = OpenAI(base_url="https://api.provider.example/v1")
# after — routed on the vehicle
client = OpenAI(base_url="http://localhost:8000/v1")
# every call below is untouched
msgs = [{"role": "user", "content": "Describe this frame."}]
resp = client.chat.completions.create(messages=msgs)
C++ · any HTTP clientno SDK needed
// libcurl, cpr, Boost.Beast — whatever the vehicle
// already links. It is one POST.
cpr::Response r = cpr::Post(
cpr::Url{"http://localhost:8000/v1/chat/completions"},
cpr::Header{{"content-type", "application/json"}},
cpr::Body{R"({"messages":[{"role":"user",
"content":"Describe this frame."}]})"});
Shell · curlsame API
# with no link and no cloud key, the same call is
# answered by the local model instead.
curl http://localhost:8000/v1/chat/completions \
-H "content-type: application/json" \
-d '{"messages": [{"role": "user", "content": "..."}], "stream": true}'
Routedge governs the advisory and supervisory path — what the vehicle is allowed to decide as conditions degrade, and what record that leaves. It never sits between a controller and an actuator. It is not a certified safety component, and the vehicle keeps its own watchdog and its own declared default for when Routedge does not answer in time. It is also not an inference engine: it does not execute, compile or quantize models, and it adds no accelerator support your model server does not already have.