TYPED DECISION LAYER · SELF-HOSTED · MADE IN EUROPE

A router that knows
when to say no.

mtlm-router turns natural-language requests into typed, calibrated routing decisions — on-prem, on CPU, in ~30 milliseconds. When a request doesn't fit a known route, it says escalate instead of guessing.

US decision APIs bill you per token and keep your prompts. mtlm-router is a 7.5MB appliance that runs on the server you already own — flat cost, data stays inside.

7.2M
parameters
~30ms
CPU inference
8MB
int8 model
0
GPU · cloud · deps
See it decide

Type your own request. Watch it decide.

Live against the hosted router, business-only lanes (IT helpdesk, general tools, chat). Off-topic input should abstain, not guess.

The same POST /v1/route your agents would call. A few tries per visitor; grab a wallet for more.

One call. Three typed answers.

A single request returns a validated route, a calibrated confidence, and a tool-fill proposal — or a clean escalate if it doesn't know.

$ curl -s localhost:8080/assess -d '{"req":"hi team, this is the third time my VPN drops today"}'

{
  "route":       "create_ticket",
  "confidence":  0.87,
  "noul":        0.91   // "novel / unhandled / loss" — abstention dial,
  "candidate":   "open_ticket",
  "score":       0.83,
  "action":      "tool_fill",
  "fill": { "subject": "VPN drops repeatedly", "priority": "high" }
}

It doesn't chat

It's a router, not a chatbot. It emits machine-readable decisions your agent, helpdesk, or dispatcher can act on directly.

It doesn't guess

Out-of-scope requests hit the calibrated escalate route. Small models shouldn't pretend to know things — this one doesn't.

It doesn't argue

No temperature, no sampling, no prompt drift. Deterministic softmax over your routes — the same request gets the same answer, every time.

Built for SME workflows, not datacenters.

The requests that eat SME time are decisions, not essays — sort the inbox, dispatch the ticket, route the quote. That's exactly what a router is for.

Email & ticket triage

Quotes, orders, disputes, urgent asks — classified, prioritized, and pushed to the right queue or ERP. No copy-paste, no lost emails.

Ops commands, typed

"Restart the spooler on srv2", "flag order 4412 for review" — natural language becomes a typed action your automation can execute, or an escalate when it shouldn't.

Compliance hand-off

Low confidence or risky requests escalate to a human instead of executing. Audit trail included — every decision is logged with its confidence.

One instance, many clients

Integrators: deploy the same trunk at every customer and ship a per-client head — a ~7KB file trained on their vocabulary in hours, not a custom model.

Front door for bigger AI

Shadow it in front of your hosted LLM to learn what it could have handled locally — then cut the API bill only where the data says so.

No ML team required

One tarball, one binary, one endpoint. If your stack can POST JSON, it can route. GDPR-native: nothing leaves your network, ever.

Mixture of experts — one trunk, many brains.

The frozen 7M trunk is the shared brain. Domain knowledge lives in ~7KB heads you can ship, swap, and audit like config files. A gate head picks the expert; the expert picks the route.

Each head declares its own feature tap — last-token, mean@-3, max@-3 — so a single instance serves the pooling recipe that actually won each domain's eval. Known-domain clients can also pin their expert and skip the gate entirely.

                 ┌─────────────────────────────────────┐
  request  ──▶  │  mtlm-router trunk — frozen 7M model  │
  tokens         └──────────────┬──────────────────────┘
                    prefill hidden state (1 × d_model)
            ┌────────────┐ ┌─────────────┐
            │ gate.head  │ │ expert.head │   ← per-domain, ~7KB
            │ pick a domain │ │ pick a route   │
            └────┬───────┘ └─────┬───────┘
       it_helpdesk ───┘        reset_password ───┘  + calibrated conf

Ship brains, not models

A customer deployment = the frozen trunk + a handful of kilobyte head files. Onboard a new domain by training a head on ~50 labeled examples per route — a working lane in hours; your full export is what scales it.

Per-head pooling

Pooling wins aren't uniform — mean@-3 takes the synthetic experts, max@-3 takes long-prose traffic, last-token keeps the gate. mhd2 flags carry each recipe; the server just obeys.

Pin your lane

{"state":"depot illicite rue des lilas","expert":"mairie"} — a client that knows its domain skips the gate and the OOD vetoes. Its expert's own escalate class is still the abstention path. Try it in the live demo above.

Numbers — held-out, calibrated, honest.

Metric Head Result
Route accuracy mhd3 decide head, 800-row holdout, leak-free live eval 98.4%
NOUL calibration abstention dial, 800-row holdout, leak-free live eval 99.4%
Score accuracy complexity tier 1–4, 800-row holdout, leak-free live 98.8%
Gate accuracy mhd3 business gate, 149 holdout rows, 3 domains, leak-free live 98.7%
Multi-tap municipal expert mhd3 concat3 (max@-4,-2,-3), 6,402 real rows, leak-free live 78.5% → 81.5%
Municipal, merged taxonomy same head, ambiguous collecte pair merged — the pilot finding, leak-free live 90.7% · 97.8% auto @ <1% err (conformal α=0.02)
Generic intents — CLINC150 mhd3 mean@-2,-3,-4, 151 classes incl. out-of-scope, 5,500-row holdout 73.8% · OOS-detection AUROC 0.842
Data a lane needs few-shot curve, real 16-route municipal corpus, 633-row holdout 50 ex/route → 68% · full export → 80% (merged: 90.7%)
Pooled fleet expert max@-3 tap on long-prose issues 48% → 63%
Live gate eval real canary matrix, not holdout — aggregate across lanes 81.6% · tools 62/63

Held-out sets pass candidates that real canary traffic rejects — both published here. The gap between lab accuracy and live aggregate is what per-domain constraints and the flywheel are for.

How the conformal abstention gate works → blog.intrane.fr

It trains on its own traffic.

Every /v1/route decision is logged. A daily flywheel harvests the log, files uncertain rows into a persistent review queue, merges judged verdicts into the train-only corpus, and dedupes before retraining. The gate thickens from real requests — never from its own confident predictions.

decisions.jsonl ──▶ harvest ──▶ review queue ──▶ judge ──▶ train corpus ──▶ new head
                 (replay domain-less rows · seen = resolved only · dedupe at merge)

Watch a real lane decide.

The municipal lane runs the flagship head — trained on a real production export, served live on the public demo (pin expert:"mairie"): dépôt illicite. micro onde → depot_illicite @ 1.00, demande de passeport → escalate → delegate. ~190ms per decision on CPU.

» "Dépôt illicite. micro onde"          [router] depot_illicite @ 1.00 (186ms)
» "1ere dotation. bac pour le verre"    [router] dotation_bacs  @ 1.00 (174ms)
» "demande de passeport"                [router] escalate       @ 0.42 — delegates, not guesses

The alternatives, honestly compared.

Runs on your hardware Cost model Typed output Knows when to abstain
mtlm-router CPU, ~30ms, air-gap OK Flat — one appliance route + confidence + fill escalate, calibrated
Jev (TypeSafe) No — US API only $0.042/M input tokens noul / choice / score Calibrated probabilities
Chat LLM + prompt parsing Only if self-hosted (GPU) Per-token, in and out Free text you must parse Hallucinates an answer anyway
Hand-written rules Yes Flat Whatever you code Only the cases you foresaw

From zero to routed in days.

1

Drop the appliance — untar, run one binary, POST requests to /v1/route.

2

Train your head — ~50 labeled examples per route get you a working lane; your full export + a calibration run gets you the certified point.

3

Run it in shadow — log decisions against real traffic; the flywheel files what it's unsure about.

4

Promote with evidence — go authoritative only when the live-eval numbers say so, not the holdout.

Honest limits.

It's a router, not a reasoner

It can't summarize, explain, or compose. If you need text generation, route to a bigger model — that's exactly what escalate is for.

Thin lanes exist

Free paraphrase abstains — the municipal head delegates novel phrasing even when close. That's the design: thicken a lane with client-labeled rows via the flywheel, don't lower the bar. The manifest ships per-domain row counts so you see weak lanes first.

Calibration ages

Temperature was fit on today's request mix. Traffic drifts; refit from labeled production rows before trusting the confidences downstream.

Verify before authority

Run it as a shadow router first. Promote to authoritative only after real traffic proves the gate + head on your request mix.

Free route audit on your own requests.

Leave your email. We reply with a short questionnaire (your routes, 30 example requests); 48 hours later you get a report: accuracy on your vocabulary, calibration, what would escalate. No commitment.

Stored in our EU backend, used only to send you the audit. No newsletter.

Ready-made lanes. Certified numbers.

A .lanepack is a decision lane for one domain — head weights plus its leak-free eval, calibration point and license, all in one ~500KB tarball. Drop it in the appliance and that request type is handled. Every pack shows its numbers; demo packs are marked as demos.

lanecoversholdoutstatus
clinc150 151 generic intents + out-of-scope 73.8% · OOS AUROC 0.842 free · certified
helpdesk 5 IT-helpdesk routes + escalate synthetic corpus free · demo

Catalog + install: github.com/javimosch/mtlm-heads — a lane fitted on your routes is the custom-head offer below.

Three ways to run it. One of them is free.

Self-host the appliance for nothing, pay per decision on the hosted API, or have us train the head for your routes. Same trunk, same typed answers, same honest numbers.

APPLIANCE
Free

Apache-2.0, forever.

The v0.3.0 tarball (~8MB): mhd3 multi-tap engine, int8 model, tools/helpdesk/municipal heads, systemd unit. Runs on any x86-64 box, no GPU, no Python. Your data never leaves your network.

Download v0.3.0
HOSTED API
€0.01 / 20 decisions

Pay per decision, prepaid wallet, no subscription.

The same /v1/route on api.mtlm-router.intrane.fr, metered by peage (EUR, Stripe top-ups). New wallets start with free credit, so the first decisions cost nothing. Signed receipt on every charge.

Get a wallet and call it
CUSTOM HEAD
€149 / domain, one-off

Your routes, trained and calibrated, in 3 business days.

Send us your route table (names plus a few example phrasings each). You get a ~7KB .head for the appliance or the hosted API, an eval report with holdout accuracy and calibration, and one free re-train after a week of shadow traffic.

Send your routes

Prices in EUR excl. VAT. Hosted API decisions are served from EU infrastructure; hosted traffic is logged for calibration only and never used to train other customers' heads.

One tarball. Runs anywhere.

The whole stack — server binary, tokenizer, int8 model, heads — ships in one fully self-contained ~7.8MB tarball. Untar, run ./start.sh, done. No anvil install, no pip, no model download, no license server — nothing leaves the machine.

$ tar xzf mtlm-router-v0.3.0-linux-amd64.tar.gz && cd mtlm-router-v0.3.0-linux-amd64
$ ./start.sh &
$ curl localhost:8097/v1/route -d '{"state":"Dépôt illicite. micro onde","expert":"mairie"}'
{"route":"depot_illicite","domain":"mairie","action":"tool_call","confidence":0.999,...}

Agent-operable, not just agent-readable.

The tarball ships a mtlm-router CLI built for AI agents: JSON-only stdout, semantic exit codes, an embedded guide, a health-polled daemon lifecycle, and content-hash self-update. The server self-describes — /guide, /llms.txt, /v1/whoami, /v1/feedback. 28/28 on cli-spec-conformance — checked, not claimed.

$ ./mtlm-router daemon start        # loopback, polls /_health — never a fixed sleep
{"daemon":"up","port":8097,"url":"http://127.0.0.1:8097"}
$ ./mtlm-router guide               # embedded operator manual (JSON)
$ ./mtlm-router update --check      # content-hash self-update → .bak rollback
$ ./mtlm-router daemon stop         # clean POST /_shutdown

Small enough to trust. Typed enough to use.

Apache-2.0, pure-Machin source, built in Europe, with the honest-numbers discipline baked in — holdout and live-eval published side by side. Read the product doc, audit the evals, ship your first head.