The pitch for Taskclan Intelligence is simple. You do not pick a model. You describe a task and the router picks the tier that fits.
That is a nice pitch. It is also a hand wave unless we can show what the router actually does. So here it is, in full, no black box.
The philosophy
There are two ways to build a router.
You can train a model to route. Give it examples of prompts and the correct tier, fine tune, and hope it generalises. This gets you a router that is expensive to run, hard to inspect, and drifts every time your prompt distribution shifts.
Or you can encode the rules explicitly. Read the prompt for a small set of well understood signals, apply a short decision tree, and log every choice you make. This gets you a router that costs nothing to run, is trivial to debug, and never mysteriously routes to Max on a call you thought was cheap.
We built the second kind.
The signals the router reads
For every incoming request, the router extracts a handful of signals from the messages and metadata.
- chars. Total character count across all message text.
- messageCount. Number of turns in the conversation so far.
- hasCode. Does any message contain a fenced code block, a shebang line, or an obvious coding cue like refactor, debug, implement.
- hasDeepReasoningCue. Does any message contain a word like analyze, plan, tradeoffs, why does, derive, explain step by step.
- hasTools. Is there a tools array in the request.
- hasImages. Is there an image content part in any message.
- hasStructuredOutput. Is response_format set to json_object.
These are the only inputs. Nothing else about the request influences the decision. No random sampling, no A/B tests hidden behind the interface. Same inputs, same tier, every time.
The seven rules
The router evaluates rules in order. First match wins.
Rule 1. Long context. If the total chars exceed twelve thousand OR the message count exceeds twenty, route to Max. Long conversations get expensive fast; you want the tier that can actually make sense of the whole thing.
Rule 2. Deep reasoning cue. If any message mentions analyze, tradeoffs, plan, derive, or a similar reasoning verb, route to Max. Someone asking to reason through something wants the tier that reasons.
Rule 3. Medium prose. If chars exceed four thousand but no reasoning cue fired, route to Flow. Medium prompts do not need Max, but they are past the point where Core answers well.
Rule 4. Code content. If any message has code, route to Flow. Coding needs a tier that reads code, and Flow is the balanced default for it.
Rule 5. Structured output floor. If the caller asked for JSON, floor the tier at Flow. Core answers structured requests but is more likely to malform the JSON.
Rule 6. Short simple. Nothing else matched and the prompt is short and plain. Route to Core. This is the cheapest tier and it is fine for classification, extraction, and short questions.
Rule 7. Default. If we somehow reach here without matching, route to Flow. Flow is the sensible default when the signals are ambiguous.
Two biases run on top of the rules.
Tools bias. If tools are present and the router picked Core, bump to Flow. Tool calling is a Flow tier and above capability in practice.
Images bias. If images are present and the router picked Core, bump to Flow. Vision requests get expensive fast on the cheapest tier, and our vision safe fallback lives at Flow anyway.
What this looks like in practice
A few real requests and where they land.
hi→ Core. Short, simple, no cues, no tools, no images. Fits the definition of a cheap classification style call.refactor the login helper to accept an email or a phone number→ Flow. Coding cue triggered by refactor, so Rule 4 fires.analyze the tradeoffs between JWT tokens and sessions for the new mobile app→ Max. Rule 2 fires on analyze and tradeoffs.- A fifteen thousand character contract with a request to summarise → Max. Rule 1 fires on length.
what is 2 plus 2with a calculator tool defined → Flow. Rule 6 would have picked Core, but the tools bias floors at Flow.what is in this imagewith an image content part → Flow. Rule 6 would have picked Core, but the images bias floors at Flow.
Every decision is inspectable
When the router picks a tier, it returns three fields in the response metadata.
tier: the tier that actually ran.autoRoutedFrom: 'auto': so you know the routing happened.autoRoutedReason: the human readable name of the rule that fired.
You see them on every reply in the VS Code extension footer. You see them in every ledger entry on your platform.taskclan.com usage view. You see them in the OpenAI compatible response as x_taskclan.autoRoutedReason.
If you ever look at a call and think 'this should have been Core, not Max', you can trace exactly which rule fired and either accept it or file a bug. Every rule and every bias has an assertion; when we change the router, the tests tell us which prompts move tiers.
Boring routers are the ones you can trust
The router lives in about a hundred lines of TypeScript. You can read it. You can predict it. You can override it whenever you want by passing an explicit tier in your model field instead of leaving it on auto.
The point of routing is not to be clever. It is to save you from paying Max prices for Core work, and to save you from paying Core prices when your prompt actually needed Max. The rules are boring on purpose. Boring routers are the ones you can trust.
