Skip to main content

Jev (TypeSafe) judgment client

Overdeck can ask TypeSafe AI’s Jev model small, typed questions: yes/no, pick-one, or a score on a rubric. Jev is a judgment model, not a coding model. It answers questions about a piece of text and never generates text, so it cannot run an agent. It is optional and off by default.

What Jev is

Jev (“System One”) takes a state (text or JSON) and a set of named questions, and returns a calibrated answer for each one:
  • a Noul question returns a probability from 0 to 1 that the statement is true;
  • a Choice question returns a probability for each option;
  • a Score question returns an expected score on a rubric.
Answers typically come back in under half a second. Overdeck uses them for fuzzy judgments that are hard to do with keyword lists, such as “does this agent message end by asking a question?”.

Two routes

You can reach Jev through OpenCode Zen or directly through TypeSafe. The Zen route needs no new account if you already have an OpenCode Zen key. Both routes use the same key slot.

Configuration

Add a jev: block to ~/.overdeck/config.yaml:
You can also set the key in Settings → Background AI → TypeSafe API key (Jev). Overdeck looks for the key in this order:
  1. api_keys.typesafe;
  2. the environment variable named by jev.api_key_ref (default TYPESAFE_API_KEY).
There is no default model. With jev.model unset, every Jev feature reports model-not-configured and makes no request. Overdeck never falls back to the SDK’s own default model. Each Jev feature has its own toggle under background_ai.features, and all three are off by default:
  • jevTurnEndAssessment
  • jevAcceptanceCriteriaReview
  • jevMemoryRelevance
Low-cost mode (background_ai.cheap_mode, on by default) turns all of them off regardless of their toggles. With no jev: block, low-cost mode on, or a toggle off, Overdeck behaves exactly as it does without Jev: no request, no startup check, and no warning.

Set it in Settings

Settings → Background AI also exposes the route, model and timeout directly, below the TypeSafe API key row — no manual YAML editing required (PAN-4508):
  • Route — a select with three options. OpenCode Zen sets jev.base_url to https://opencode.ai/zen. TypeSafe direct removes base_url. A third option, Custom, appears only when jev.base_url is already some other URL; choosing it again keeps that URL as-is — there is no field here to type a new custom URL.
  • Model — a text field with suggestions jev-1.13-free, jev-1.13, jev-1.13.0. It is required while any Jev toggle above is on; clearing it in that case shows an error and the change is not saved.
  • Timeout — a number field, 1–30000 ms.
Every field saves automatically as you edit it (debounced while typing) and applies to the next Jev request — no restart needed. jev.api_key_ref has no Settings control and stays config.yaml-only. Turning a Jev toggle on while jev.model is blank shows an error and the toggle change is not saved.

What is sent to TypeSafe

jevTurnEndAssessment and jevAcceptanceCriteriaReview are both live. jevTurnEndAssessment sends the agent’s role and the tail (trimmed to 6,000 characters) of its last assistant message to TypeSafe, and nothing else from the transcript. It runs only for idle interactive agents — plan agents and conversations — whose transcript is a claude-code JSONL or a codex rollout; every other harness kind is unsupported-harness and never reaches Jev. jevMemoryRelevance is not yet called by anything; turning it on today sends no request. Turning a toggle on sends the following data: The same text appears under each toggle in Settings. Acceptance-criteria text can quote issue text that anyone wrote in a public tracker, so Overdeck treats the Jev result as advice only: it prints warnings and never blocks plan finalize.

Turn-end classification

jevTurnEndAssessment (PAN-4371) reads why an idle interactive agent (a plan agent, or a conversation) stopped talking without opening a modal or asking through a tool call. Jev classifies the message into one of five kinds — asks_operator, reports_complete, reports_blocked, progress_update, other — and separately answers whether the message needs an operator answer. Three of the five kinds replace the generic “Answer the agent” label with a specific one on the Needs-you row and on a parked idle-running row: Asked you a question (asks_operator), Reported done (reports_complete), and Blocked (reports_blocked); progress_update and other keep the generic label. A classification is shown only when Jev’s confidence in the chosen kind is at least 0.7 (TURN_END_MIN_CONFIDENCE) — below that, nothing is attached and the row reads exactly as it did before this feature existed. Nothing is persisted: the result lives only in an in-process, mtime-keyed store that a restart clears, and it is read back on the next poll tick or parked-population read. Readiness: advisory; accuracy under measurement. The 2026-09-29 measurement against a 40-row labeled fixture (evals/jev-turn-end.eval.ts, model jev-1.13-free) put asks_operator precision at 0.7778, recall 0.875 — below the 0.9 bar this feature would need to be called ready. See evals/README.md for the full per-class table.

Privacy

On the direct route, requests go straight to TypeSafe AI. On the Zen route, they go to OpenCode Zen, which forwards them to TypeSafe. TypeSafe states that it does not train on customer data. Zero data retention is available only on TypeSafe’s enterprise plan. Overdeck never logs the API key or the request body. The client pins the SDK log level to warn, which also overrides a TYPESAFE_LOG_LEVEL=debug environment variable.

Cost

Jev costs $0.042 per million input tokens, and output is free. jev-1.13-free records $0. Every real request (not a repeat served from Overdeck’s in-process memo) appends one event to the cost ledger with the source background:<feature>, for example background:jevTurnEndAssessment. The 24-hour spend appears next to each toggle in Settings → Background AI.

Usage readout

The Jev settings panel also shows, per feature: calls in the last 24 hours, the last call time, and the last error (failure reason and HTTP status, if any) — so you can see whether Jev is actually doing anything without reading logs (PAN-4508). That readout is built from a plain-text usage log: every real (non-memo) Jev request appends one JSON line to ~/.overdeck/jev/usage/<UTC date>.jsonl, with the time, feature, outcome (answered or failed), failure reason and HTTP status (on a failure), model, and request duration. The log never records the API key, the text sent to Jev, the answer, or an error message. A repeat served from the in-process memo is not counted — it made no request.