Eval tools tell you your prompt scores 72%. ProblemRouter routes the problem to the prompt and model that score 91% — at half the cost. And then, if you want, it keeps it that way.
OpenAI Anthropic Google Meta Mistral DeepSeekX xAIA Amazon
We have no model to sell you — a cheaper one is allowed to win.
Layer one · Search
You describe the problem. It writes the prompts.
It drafts candidate prompts, runs each one against your examples on every model worth trying, and keeps spending your budget wherever the results are still improving. Cheap checks first; full runs only for the candidates still standing.
1Start — or resume — your problem
Classify each incoming support ticket into one of six categories, from the subject and body.▌
Input / output shape
input { subject: text, body: text }
output { category: enum(6) }
✎You never write a prompt. ProblemRouter generates and optimizes the prompts itself — your description is the problem, not the prompt.
Ringed = nothing else we tried beats it on both accuracy and cost.
1 · SEARCH PRODUCESand this is the whole product, if you want it to be
A configuration
You triage support tickets. From the {{subject}} and {{body}}, weigh intent over keywords and return exactly one of: billing, bug, account, feature, refund, other. When ambiguous, prefer the user's primary ask.
↓ WHICH 2 · THE API RUNSpromote it and it serves — there is no separate deploy step
Layer two · API
One URL. Your input in, your typed output back.
The JSON you POST is exactly the input shape you declared; the JSON you get back is exactly the output shape. Everything of ours travels in the headers — never in your payload. Nothing to install, no library, no proxy.
YOUR APPLICATIONwherever it already runs · nothing of ours inside it
REQUESTwhat you send
POST/v1/run/triage_tickets
authorization: bearer fmp_live_…
content-type: application/json
{ "subject": "charged twice",
"body": "I was billed on the 3rd…" }
↑ exactly the input shape you declared — no wrapper, no reserved keys, no field your own data is forbidden from using.
RESPONSEwhat you get · 11 ms
200{ "category": "billing" }
x-fmp-configuration:cfg_4f1c9a
x-fmp-cache:hitx-fmp-version:live
x-fmp-cost-credits:0.04
↑ exactly the output shape, checked against it before you get it. Everything of ours is a header.
the request
the response
WHAT IT PASSES THROUGH
CACHE61%
In-process first, then a shared one. Most requests never reach a model. The key includes a fingerprint of the configuration, so two versions can never serve each other’s answers.
▼
A/B TESTING90 / 10
A stable hash of the caller sends most traffic to what’s live and the rest to a version you’re trying. The same caller always lands on the same one, so nobody flips mid-session.
▼
PROVIDER372 ms
Whichever model won your search. The spend is held before the call and settled against the real cost afterwards, so an empty wallet fails before any tokens are bought.
▼
FALLBACK×2 + 1
Two retries on a transient failure, then a different provider that satisfies the same output shape. Your user still gets an answer — and it still counts as a failure in your numbers.
BEFORE ANY MODEL IS CALLEDThe key is checked, the rate limit is checked, and the body is checked against your input shape — 401 · 402 · 422 are answered in under a millisecond, without reaching a provider. And after the response has gone, in another process: the trace row, the cache write, and settling the cost.
2 · THE API PRODUCESwritten after your bytes have gone — never on your caller’s clock
Requests and responses
One row per request, always: the input, the output, which configuration produced it, which version served it, whether it came from cache, how long each stage took, tokens, cost, and the error if there was one.
↓ WHICH 3 · OBSERVABILITY READSa sample of it, scored — and the interesting part kept
Layer three · Observability
A sample is scored. The interesting part is kept.
The scorer only ever sees the input and the output — production has no answer key. Put every week’s traffic, every verdict it handed down, and every deploy on one axis, and the whole quarter reads in a single picture.
SIXTEEN WEEKS OF ONE ENDPOINT not scored scored well middlingscored badly average score
The block above each bar is the ~22,800 responses a week we didn’t score — off scale, drawn broken, so the sample that was scored stays readable.
3 · OBSERVABILITY PRODUCESversion 5 — stamped, so its scores stay comparable to version 4
A dataset
A quarter of what your users actually asked — including the cases your original examples never contained, and a held-back set that is collected and never trained on.
It arrives on the “Bring data” tab you already know — or presses Resume for you, if you let it.
↑ WHICH IS WHERE 1 · SEARCH BEGANand the loop closes
You bring the problem. We bring the rest.
You can stop at layer one — copy the prompt and go, it runs anywhere.