Jev Bounds the Answer. Who Bounds the Process?
TypeSafe just shipped a model that cannot answer outside the options you give it. That is the FloMorphic thesis, pushed one layer down — and it makes the layer above it more necessary, not less.
This week TypeSafe announced a model called Jev, and the pitch was not smarter. The pitch was narrower on purpose.
You give it a block of state — a ticket, a JSON object, a sentence like "my card was charged twice" — and a list of typed questions. A choice question carries the options it may pick from. A score places the state on an ordered scale of two to ten levels. A noul is yes or no. Jev evaluates all of them at once and returns a probability over each option you listed:
state: "Customer emailed twice about a duplicate charge..."
questions: category → choice of [billing, technical, sales]
urgency → score of [low, medium, high, critical]
answer: category → { billing: 0.85, technical: 0.08, sales: 0.07 }
urgency → high
No prose. No undeclared output. No option that was not in the list. TypeSafe's phrasing is that it is mathematically impossible for Jev to produce an invalid value, because the structure is the primitive — the output is not text that gets parsed into a shape afterwards, it is the shape. It is not a reasoning model and does not try to be: no memory, no tools, no chain of thought. TypeSafe reports 70–500 milliseconds end to end, and says it only works when the space of valid answers is bounded and known up front.
One distinction before going further, because the rest of this post lives in it. Impossible to produce an invalid value is not impossible to produce a wrong one. Jev cannot return legal if legal was not an option. It can still return billing: 0.85 when the case was technical. The type guarantee is about the shape of the answer, not its truth.
I read that and recognised it. It is the sentence I have been drawing on a canvas for a year.
The same thesis, one layer down
Here is how a model node in FloMorphic decides. The system and user prompt describe the situation and the scenarios that matter. The functions you bind to the node — approve, escalate, search_docs — appear as outbound ports on the diagram. At run time the model receives those as tools; when it picks one, only that port fires. The model's decision becomes an edge you can see. It selects among the routes; it cannot invent one.
Now put the two side by side.
| FloMorphic model node | Jev | |
|---|---|---|
| Who draws the option set | you, on the canvas — bound functions become ports | you, in the options list of the question |
| Where the scenarios live | system and user prompt | the state block |
| What the model does | picks one bound function | returns a distribution over the options |
| Can it produce a route you did not draw? | not as an executable route — only a bound port can fire | not as a value — the output layer cannot emit anything outside the declared type |
| Where the boundary is enforced | the runtime | the model |
| Does it reason first? | yes — reads, retrieves, iterates, then chooses | no — one shot |
| What comes out | one tag | probabilities for every option, for many questions in parallel |
Same principle in both columns: a decision is a selection from a set that a human drew before the run, not a sentence the model composes during it. FloMorphic holds that line at the process layer. Jev holds it inside the model.
That a company built an entire model category — they call it System One, and their stated aim is a decision primitive that software can act on directly, decisions rather than strings — around the bounded-decision idea is the most direct validation of the thesis I have seen. When the industry was arguing that the way to govern a model was a better prompt, we said the way to govern it was to draw where its reasoning can lead and let it think freely inside that. Jev is a model that only does the second half. It cannot wander because it has no place to wander to.
What the model cannot bound
So why is this not the end of the argument? If the model itself refuses to answer outside the options, do you still need a process layer that refuses on its behalf?
Look at what Jev leaves open — not as a weakness, but because it is a model and not a system.
Who drew the options, and where is that list now? In the example above, [billing, technical, sales] lives in a request body. Which means it lives in code. When compliance asks why legal was not an option in March, the answer is a git blame, if you are lucky.
What fires after the choice? Jev returns billing: 0.85. Something has to turn that into an action. In most codebases that something is an if. The decision was schema-safe, and then it landed in the one place nobody can see.
Where is the record? Not the log line — the record. What state the model saw, which options it had, what it returned, which threshold accepted it, where the process went next. Jev gives you the middle of that sentence. The beginning and the end are yours to lose.
Who changes the threshold? if p > 0.8: auto_route else: human is a policy. TypeSafe's own examples apply it exactly there — outside the model, in the caller — which is the right place, and also means it is a literal in a handler, and moving it is a deploy.
Here is the point compressed: a schema-safe decision that lands in an if-statement is still a hidden branch. Bounding the answer does not bound the process. It bounds one step of it, and leaves the routing, the policy, the history, and the authorship of the option list exactly where they were — distributed across services, invisible to the domain expert, reconstructed after the fact.
Which is the seam FloMorphic exists to fill. Not around the model. Around the decision.
You can draw a Jev today
Before treating Jev as a new kind of node, notice that the shape of it is already a configuration of the model node you have.
Take the routing example and draw it. The prompt carries the state and the question. Each option becomes a bound function, and each bound function becomes an exposed port. The prompt does not describe the routes in prose and hope; it points at the ports by name, and asks for a typed answer:
system: You classify support cases. Return JSON only:
{ "category": one of billing | technical | sales,
"confidence": 0..1,
"reason": one line }
Then call the function matching "category".
ports: billing ──► R1
technical ─► R2
sales ──► R3
_exception ─► R4 (model picked none of the above)
What comes out is a JSON object and a port. The JSON is the typed decision — the same {category, confidence} Jev would hand back. The port is the contract: the only routes that can fire are the ones drawn, and the model's answer lands on whichever drawn edge it is closest to. It cannot route to legal because there is no legal port. If it produces nothing that matches, the _exception port fires — which is the "no route matched" case as a visible edge rather than a silent fallthrough.
That is the Jev shape, end to end: state in, bounded typed answer out, next action determined by which of a pre-drawn set the answer falls into. Built from a prompt, a schema, and ports — nothing the runtime had to learn.
So what does Jev add over this? Two things, and they are honest ones. The confidence is calibrated, not self-reported. When a general model writes "confidence": 0.85 that number is itself generated text — a plausible-looking value, not a measurement. Jev is trained specifically so that its probabilities are intended to track actual outcome frequencies. A threshold on a self-reported number is a threshold on a guess. And the answer costs milliseconds, not seconds. For a decision that is made ten thousand times a day, that difference is the whole budget.
Which is exactly why Jev belongs in the palette rather than replacing anything in it.
Jev is a decider. FloMorphic has a slot for that.
In the introduction post I wrote that the tag mechanism is not owned by any node type: a rule node emits tags from a JavaScript or Rego evaluation, a model node emits them from the function the model picked, a call into your backend emits them from your service's reply. Same enforcement, different decider.
Jev is a fourth decider — the same shape as the node drawn above, with the judgment swapped for a calibrated distribution. It slots in beside the others without the runtime learning anything new, because a node in a palette is a configuration of a primitive, not a feature implemented in the engine. And it brings three things a general model node does not.
Confidence becomes a value on a visible path. A model node emits one tag: the function it picked. Jev emits the whole distribution. That is a number, and a number can be routed on by a rule node that sits on the canvas:
┌──────────┐ ┌───────────────┐ p ≥ 0.80 ┌── billing
state ──────►│ Jev │─────►│ rule: top_p │──────────────┼── technical
│ category │ │ threshold │ └── sales
└──────────┘ └───────┬───────┘
│ p < 0.80
▼
human review
The threshold is a node. It is changeable without a redeploy, readable by the compliance officer, and evaluated outside the model. This also sharpens the question every routing design eventually faces — what happens when nothing matches? It is tempting to assume a calibrated model would tell you, with a flat distribution. It will not. If the option list does not cover the case, Jev has to push it into a listed bucket, and the guidance around it says the probabilities will then look more decisive than the situation deserves. The recommended fix is to add an other or none of the above option — which is to say: the no-match case has to be drawn, as an option in the schema and as a route after it. That is what _exception is on a model node. Calibration does not remove the need for that edge; it tells you where it belongs.
Many decisions from one read of the state. Jev evaluates every question in parallel. A chain of four small classifier nodes — category, urgency, sentiment, is-this-a-repeat — collapses into one node that emits four tags. Fewer model calls, one place to look.
The cheap, fast decisions stop paying the reasoning tax. Most routing decisions in a real process never needed open-ended reasoning. They needed the state read once and a calibrated guess in under a second. Spending a frontier call on "is this billing or technical" was always a waste; it was just the only bounded thing available.
Where each one belongs
None of this displaces the model node. It sharpens what it is for.
A model node is the corridor. It is where the model reads every document, weighs contradicting evidence, calls a plugin, gets a second turn with instructions it did not have when it started — and then chooses among the ports. Bounding where that reasoning can lead is what makes it safe to let the reasoning be as clever as the model is able. That is the interesting part of an agent, and Jev does not touch it.
Jev is for the other kind of decision — the one where the option set is known, the answer does not require open-ended reasoning, and what you want is speed, cost, and a confidence number you can trust enough to route on. In a claims flow that is most of the decisions by count and almost none of them by weight.
Both are bounded. Neither can invent a route. The difference is whether the model thinks first, and whether you get one answer or a distribution.
┌─────────────────────────────────────────────────────────┐
│ THE PROCESS │
│ │
│ ┌──────────┐ fast, bounded ┌──────────────┐ │
│ │ Jev │ selection │ model node │ reads, │
│ │ node │─────────┐ │ (corridor) │ thinks,│
│ └──────────┘ │ └──────┬───────┘ picks │
│ ▼ ▼ │
│ ┌───────────────────────────────┐ │
│ │ tags → edges drawn on canvas │ │
│ │ policy → rule nodes │ │
│ │ approval → human nodes │ │
│ │ record → the event stream │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
The bigger consequence
There is a line in Jev's announcement I keep returning to: people can't be the only consumers of intelligence. The output is meant for software, not for a reader.
I agree, and I would push it one step. If the consumer of a decision is software, the decision needs a place in that software that is not a branch in a handler. It needs to be a node on a path someone drew, with a name, a position, a scope, and a history. Otherwise you have made the model honest and left the system exactly as opaque as it was.
Jev is what it looks like when the bounded-decision idea is taken seriously at the model layer. It is a real contribution, and I expect more models shaped like it. But it makes the process layer more necessary, not less — because the moment a model returns a typed decision in 200 milliseconds, the only remaining question is what you did with it, and where.
The model bounds the answer. Somebody still has to bound the process. That has always been the job.
Jev is described here from TypeSafe's announcement and early coverage; I have not run it in production and the API shape above follows their published example. If you have, and the mapping breaks somewhere, I would like to hear where.