One localhost API · Laya + Jev

One API.
Choose the decision provider.

jev-laya-local-daemon keeps Laya ready on your machine and can send the same typed-decision request to Jev through TypeSafe. Your app keeps one local endpoint and selects laya or jev per request.

Local
Laya 0.3.5
Hosted
Jev 1.13.0 · TypeSafe
Contract
state + questions
Tested
Sep 23, 2026
Endpoint
Provider Switch provider without changing the endpoint.
POST /v1/decide 200
Request
Response

Why this exists

Keep one caller contract. Switch providers underneath.

Laya needs a resident Python model process. Jev needs a hosted API key and network request. This gateway hides those provider-specific details behind one localhost endpoint while keeping the actual decision values untouched.

Shared decision primitives

Jev and Laya speak the same three decision types.

Both models take a state plus typed questions and return probabilities instead of generated prose. That shared interface is what makes a direct comparison useful. See TypeSafe's workflow primitives and the Laya model interface.

01

noul

Ask a yes/no question. The result is a probability for “true,” so your code can choose its own cutoff.

should_notify?
P(true) = 0.40

your policy decides
when 0.40 is enough
02

choice

Pick one option from a defined set and get a probability distribution across the available choices.

resume     0.22
inspect    0.24
reanalyze  0.19
test       0.35  ←
03

score

Rate something on an ordered scale, such as ignore → normal → urgent → critical.

ignore    0.0436
normal    0.1200
urgent    0.4692
critical  0.3672

What we actually tested

The useful discovery: wording matters.

When we passed raw flags and numbers, Laya's answers barely changed. When we described what those facts meant in short plain-language sentences, the model reacted much more clearly.

Raw data
{
  "git_dirty": true,
  "analysis_age_minutes": 240
}
reanalyze 0.5326 the answer barely changed from 5 → 240 minutes
Plain-language state
{
  "analysis": "The current analysis
  predates major architectural changes
  and is no longer trustworthy."
}
Result clearer reaction the meaning is stated directly
87.5% Picked the expected action 14 / 16 small decision examples
test
4/4
reanalyze
4/4
inspect
3/4
resume
3/4

This is a small hand-built test, not a general benchmark. The goal was to see how Laya behaves inside an app, where it gets confused, and what kinds of decisions it can help with.

Initial comparison

Same primitives. Different operating envelopes.

I compared the models on next-action routing, binary escalation, ordinal urgency, paraphrase/order robustness, and deliberately ambiguous cases. The same fixture definitions are checked into this repository.

Laya package 0.3.5 · typed-decisions Jev 1.13.0 · TypeSafe Playground Tested September 23, 2026
Initial routing round · local

Laya

14 / 16 87.5% expected action
Input shape
one compact state per request
Observed latency
35.3 ms / case avg
Typical warm calls
31–33 ms
Misses
2, both drifted to reanalyze
Initial routing round · hosted

Jev

16 / 16 100% expected action
Input shape
16 questions in one Playground batch
Server evaluation
162.6 ms total
Network roundtrip
449 ms to us-west
Output profile
mostly 0.99–1.00 top probability
Round Laya 0.3.5 Jev 1.13.0
Choice routing16 strict cases 14/16 · 87.5% 16/16 · 100%
Noul escalation8 true · 8 false 10/16 @ 0.5 · Brier 0.1905
best in-sample cutoff 0.463 → 14/16
16/16 @ 0.5 · Brier 0.00695
positive mean 0.945 · negative 0.100
Score urgency4 levels · 16 cases 8/16 top level · MAE 0.5404 14/16 top level · MAE 0.1356
Choice robustness12 strict paraphrases · rotated option order 10/12 · 2/4 groups fully consistent 12/12 · 4/4 groups fully consistent
Ambiguity diagnostic4 intentionally debatable cases · not accuracy preferred top-1 0/4
top probabilities stayed around 0.31–0.35
preferred top-1 4/4
confidence 0.66–0.99; 3/4 still ≥ 0.97
The surprising part When I copied Jev's multiplexed state shape into Laya, Laya dropped to 4 / 16.

Laya works well when each decision receives only the state it needs. Packing many independent cases into one shared object and asking each question to inspect state.case_XX caused nearly every answer to collapse toward reanalyze. Four-case mixed batches showed the same pattern, so this was not only a long-context effect.

Method notes and caveats

Speed is not apples-to-apples: Laya ran locally on Apple Silicon while Jev ran on TypeSafe infrastructure, and the request shapes differ.

High probability is not the same as calibration. Jev stayed very confident on several deliberately ambiguous cases.

Upstream Laya reports a different ordering on its own typed-decisions benchmark. Different benchmarks measure different domains, so this page treats the results as product experiments rather than a universal ranking. See the upstream benchmark.

Applied benchmark

Then I tested the same idea against real product-shaped decisions.

StateCarry is an open-source macOS app for returning to interrupted development work: it helps you understand where a project stands and decide what to do next. That made it a useful target for testing decisions such as continue, inspect, reanalyze, review a result, wait, reconnect, or choose different work.

20 synthetic StateCarry scenarios 377 cases / provider 754 provider runs · 0 request errors Jev 1.13.0 via jev-latest Tested September 23, 2026
Choice accuracy More options expose Laya's narrow operating range.
Batching related questions Same decisions. Very different efficiency story.
Laya 1.00× quality single = batch decisions 0.92× speed no measured batch speedup
Jev 1.00× quality single = batch decisions 6.96× speed 67% fewer input tokens

Eight StateCarry states · seven related questions per state · identical questions in single and batch modes.

Choose Laya when Locality is the requirement.

Keep the state small, English, and semantic. Prefer narrow choices or calibrated signals.

Choose Jev when Decision breadth matters more.

Use larger choice sets, stronger robustness, and batch related questions when network access is acceptable.

Why this gateway exists Your caller does not have to choose forever.

Keep one state + questions contract and select the provider per decision.

How to use it

Let normal code gather facts. Give Laya one clear, small decision.

The model worked best after the app had already gathered the facts and turned them into a short, clear description of the current situation.

1 Gather facts

Git state, tests, known changes, how old the analysis is.

2 Explain them simply

Use simple templates to turn raw facts into short sentences.

3 Ask the provider

Select Laya or Jev, then ask it to pick one option, rate something, or answer yes/no.

4 Decide what to do

Your app owns the cutoff, fallback, and final action.

“Code gathers the facts. Simple templates explain what they mean. The selected provider handles the small decision. Your app decides what to do with the answer.”

Good request / poor request

For Laya, keep one decision context small and obvious.

Good fit for Laya

One state → one narrow decision context.

small English
semantic state
2–4 choices
or related signals
  • Code computes deterministic facts first
  • The model sees the meaning, not raw telemetry
  • Related questions may share the same state
Poor fit for Laya

Many unrelated states → “find your own case.”

A
B
C
D
“only inspect
case C”
  • Unrelated cases packed into one shared object
  • Large choice sets with overlapping actions
  • Raw flags whose product meaning is left implicit

Jev handled the tested multiplexed batches much better. Keeping cases separate is still the clearer contract when Laya is a possible provider.

The point of the comparison

Choose by constraint, not by a winner.

Local first Laya

No network dependency. Best with small, controlled decisions.

Broader routing Jev

Stronger on these product-shaped tests and efficient when related questions are batched.

Caller contract Same API

Switch per request without rebuilding the application around either provider.

These are observations from this benchmark, not a universal model ranking. Different domains, prompts, hardware, or future versions may change the result.

≈ 847 MB first model download we observed
≈ 1.0–1.2 GiB memory used after loading
0.00B extra download after the model was already cached
22 passed project test suite

Run it locally

Give your coding agent one prompt.

Let the agent handle the environment, install, port check, startup, and verification. The daemon stays on your own computer at a loopback address.

Use a coding agent Copy one setup prompt and paste it into Codex, Claude Code, or another coding agent.
Prefer to run it yourself?
01

Install

python3 --version
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
02

Start

jev-laya-local-daemon
03

Check

curl http://127.0.0.1:8787/ready
Enable Jev cp .env.example .env JEV_API_KEY=your-typesafe-api-key Put the key in the repo-root .env. The daemon loads it automatically, and local callers only send provider: "jev".
Choose per request "provider": "laya" or "provider": "jev" Check both with GET /v1/providers.
About port 8787 It is this project's configurable default, not an upstream Laya requirement. Upstream Laya
Port already in use? lsof -nP -iTCP:8787 -sTCP:LISTEN or launch with DAEMON_PORT=8790 jev-laya-local-daemon

Current conclusion

One caller contract. Two different operating envelopes.

Keep Laya available for small local decisions. Use Jev when broader routing or hosted batching is worth the network hop. The application keeps the same localhost API either way.