Try it
Copy the code ↓- Data source
- Decision schema
- Model inference
- Structured result
2 Decision schema 3 typed questions
actionchoiceattackguarddodgespecialretreatthreatscorelowmediumhighcriticalneeds_new_plannoulprobability 0–1
3 Model inference typesafe/jev-1.13
Waiting for a run.
4 Structured result
Raw JSON
Run the demo to see the JSON answers, the highlighted pick and the final action.
FLATKEY_API_KEY and run.curl -sS https://router.flatkey.ai/api/alpha/decisions \
-H "Authorization: Bearer $FLATKEY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "typesafe/jev-1.13",
"state": "Tick 212. You: HP 38%, chakra 70%, special move ready. Opponent: HP 55%, just finished a combo and is in recovery frames at close range. Planner'\''s strategy: bait combos, punish recovery with the special move.",
"questions": {
"action": {
"type": "choice",
"instructions": "Given the current plan, which action should the fighter take this tick?",
"criteria": {
"attack": "Close-range basic attack or combo",
"guard": "Block and hold position",
"dodge": "Evade or reposition away from an incoming attack",
"special": "Use a special move or jutsu that is ready",
"retreat": "Back off to recover resources"
}
},
"threat": {
"type": "score",
"instructions": "How dangerous is the opponent'\''s position right now?",
"criteria": [
"low",
"medium",
"high",
"critical"
]
},
"needs_new_plan": {
"type": "noul",
"instructions": "The situation has changed enough that the System 2 planner should revise the strategy."
}
}
}'// Node.js 18+ (built-in fetch). Run: FLATKEY_API_KEY=... node jev.mjs
const body = {
"model": "typesafe/jev-1.13",
"state": "Tick 212. You: HP 38%, chakra 70%, special move ready. Opponent: HP 55%, just finished a combo and is in recovery frames at close range. Planner's strategy: bait combos, punish recovery with the special move.",
"questions": {
"action": {
"type": "choice",
"instructions": "Given the current plan, which action should the fighter take this tick?",
"criteria": {
"attack": "Close-range basic attack or combo",
"guard": "Block and hold position",
"dodge": "Evade or reposition away from an incoming attack",
"special": "Use a special move or jutsu that is ready",
"retreat": "Back off to recover resources"
}
},
"threat": {
"type": "score",
"instructions": "How dangerous is the opponent's position right now?",
"criteria": [
"low",
"medium",
"high",
"critical"
]
},
"needs_new_plan": {
"type": "noul",
"instructions": "The situation has changed enough that the System 2 planner should revise the strategy."
}
}
};
const res = await fetch("https://router.flatkey.ai/api/alpha/decisions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FLATKEY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if (!res.ok) throw new Error(`Jev request failed: ${res.status} ${await res.text()}`);
const { answers, usage } = await res.json();
console.log(JSON.stringify(answers, null, 2), usage);# Python 3.8+ (pip install requests). Run: FLATKEY_API_KEY=... python jev.py
import json, os, requests
body = json.loads(r"""{
"model": "typesafe/jev-1.13",
"state": "Tick 212. You: HP 38%, chakra 70%, special move ready. Opponent: HP 55%, just finished a combo and is in recovery frames at close range. Planner's strategy: bait combos, punish recovery with the special move.",
"questions": {
"action": {
"type": "choice",
"instructions": "Given the current plan, which action should the fighter take this tick?",
"criteria": {
"attack": "Close-range basic attack or combo",
"guard": "Block and hold position",
"dodge": "Evade or reposition away from an incoming attack",
"special": "Use a special move or jutsu that is ready",
"retreat": "Back off to recover resources"
}
},
"threat": {
"type": "score",
"instructions": "How dangerous is the opponent's position right now?",
"criteria": [
"low",
"medium",
"high",
"critical"
]
},
"needs_new_plan": {
"type": "noul",
"instructions": "The situation has changed enough that the System 2 planner should revise the strategy."
}
}
}""")
res = requests.post(
"https://router.flatkey.ai/api/alpha/decisions",
headers={"Authorization": f"Bearer {os.environ['FLATKEY_API_KEY']}"},
json=body,
timeout=60,
)
res.raise_for_status()
data = res.json()
print(json.dumps(data["answers"], indent=2), data.get("usage"))
No Flatkey key yet? Get one for Jev 1.13 →
About this use case

Who / when
Audience
- game-AI hobbyists and researchers wiring LLMs into real-time games
- agent builders who want a fast reflex layer under a slow planner
- teams whose agent costs are dominated by tiny, repeated decisions
Triggers
- the agent must act every frame or tick, faster than an LLM responds
- most decisions are small (attack, guard, dodge) and a few are strategic
- planner calls dominate cost even though most ticks need no new plan
- you want an explicit rule for when to wake the expensive model
The workflow
- 01Game stateHP, resources, positions, current planInput
- 02System 1 · ChoiceAction this tickJev
- 03Score + NoulThreat level, needs-new-plan flagJev
- 04Gate → System 2Act now or wake the LLM plannerYour code
Question shape
{
"action": {
"type": "choice",
"instructions": "Given the current plan, which action should the fighter take this tick?",
"criteria": {
"attack": "Close-range basic attack or combo",
"guard": "Block and hold position",
"dodge": "Evade or reposition away from an incoming attack",
"special": "Use a special move or jutsu that is ready",
"retreat": "Back off to recover resources"
}
},
"threat": {
"type": "score",
"instructions": "How dangerous is the opponent's position right now?",
"criteria": [
"low",
"medium",
"high",
"critical"
]
},
"needs_new_plan": {
"type": "noul",
"instructions": "The situation has changed enough that the System 2 planner should revise the strategy."
}
}Gate policy
≥ 0.90
Execute the action this tick; no planner call.
0.65–0.90
Take the safer of the top two actions and keep the current plan.
< 0.65
Guard and call the System 2 planner for a new plan.
Failure modes
Pre-launch checks before you trust auto-routing:
- Stale plans: System 1 keeps executing a strategy the situation has outgrown;
- Spatial reasoning from text-only state (distances, facing, hitboxes);
- Oscillating between two actions on consecutive ticks;
- Planner calls that arrive too late for the moment they were meant for;
- Game-specific moves described too vaguely to tell apart;
FAQ
What does the cost split look like in practice?
Vedant had Jev play Naruto as System 1 while Claude played Shikamaru as System 2 (post below). In one fight, 330 Jev decisions cost under 1 cent and 7 Claude calls cost 18.5 cents, which he puts at roughly 900× cheaper per call. His conclusion: neither model wins alone.
When should the agent call the LLM planner?
When the needs_new_plan answer is true, when confidence drops below your low band, or on a fixed timer as a backstop. Everything else stays in the fast loop.
Is this only for fighting games?
No. Any agent with frequent small decisions under a slower strategy fits the same split: RTS unit control, trading bots in dry-run, robotics behaviors or long-running coding agents. See the RTS micro page for a harder, more honest case.
Can I bring my own API key?
Yes. Try the free demo above without signing in. To run it live on your own text, sign in with Google and connect a Flatkey or OpenRouter key (a quick test call runs when you save it). Manage or delete it anytime under Dashboard → BYOK. Keys are stored encrypted on the server, used only for runs you trigger, and never sent back to the browser. Need a Flatkey key? Get one for Jev 1.13 on Flatkey.
Is this the official TypeSafe Jev product page?
No. jev-llm.com is an independent research and practice site. Verify pricing, models and terms at the original TypeSafe sources.
Sources
i made two ai models play a naruto game together lol naruto = jev (system 1) shikamaru = claude (system 2) one fight: 330 decisions from jev → under 1 cent 7 calls to claude → 18.5 cents ~900x cheaper per call. neither wins alone jev is INSANE!!! #jev #anime #software
— @vedant_stone View the post on X →
Wire this gate with your own key
Bring your own key through Flatkey / OpenRouter. Keep exact checks in code.