Skip to main content

jevkit — Python client for the Jev decision model

⚠️ Disclaimer: This is a third-party, unofficial wrapper around OpenRouter's Decisions API — not affiliated with, endorsed by, or maintained by OpenRouter or TypeSafe. The API is in alpha and may change without notice.

The first open-source third-party client for OpenRouter's Decisions API (Jev, by TypeSafe) — a calibrated-probability decision model, not a chat model.

Jev answers typed questions with calibrated probabilities — zero text generation. Three primitives: noul (yes/no calibrated probability), choice (pick one), score (scale rating). 70-500ms latency, output tokens free.

Why

Chat models guess; Jev calibrates. If you need routing, classification, or gating decisions ("is this worth doing?"), a chat model wrapped in JSON is slower, uncalibrated, and costs more. Jev is the ultimate classifier:

  • Calibrated probabilities — real confidence, not vibes
  • 70-500ms — System-1 speed for gating decisions
  • $0.042/M input, output free — 14 questions ≈ $0.00004
  • Typed questions — noul / choice / score, with explicit criteria

Install

pip install jevkit   # (after publish — for now: copy the jevkit/ directory)
export OPENROUTER_API_KEY=<your key>   # free from openrouter.ai

Quickstart

from jevkit import Client, gate

client = Client()  # reads OPENROUTER_API_KEY

# noul — yes/no calibrated probability
p = client.noul(
    name="worth_outreach",
    instructions="Is this lead worth cold outreach?",
    criteria={
        "false": "No budget, or the poster is promoting themselves.",
        "true": "Explicit budget + concrete need, reachable for a pitch.",
    },
    state="HN post: [Hiring] N8n automation expert, $2k budget, urgent",
)
# → 0.63

# gate — confidence-gated decision (act / confirm / escalate)
action = gate(p)   # confirm (borderline — flips, don't auto-send)

# choice — pick one from options
r = client.decide({
    "category": {
        "type": "choice",
        "instructions": "What does the customer need?",
        "options": ["coding", "design", "content", "infra"],
    }
}, state="I need someone to build a checkout flow")
# → {"choice": "coding", "confidence": 0.8, ...}

score — scale rating

r = client.decide({ "urgency": { "type": "score", "instructions": "How urgent is this?", "legend": { "0": "Can wait", "1": "This week", "2": "Blocking revenue now", }, } }, state="Payments are failing for customers right now")

→ {"confidence": 0.99, "legend": {...}, ...}

CLI

jevkit noul "worth outreach?" --state "lead: ..."      # → 0.61
jevkit gate 0.63                                        # → confirm
jevkit decide questions.json --state "..."              # → full answers

Gotchas (learned the hard way)

  1. questions expects a record ({name: {...}}), not an array
  2. noul's criteria is {"true": str, "false": str} — descriptions, not options
  3. The response is answers.{name}.noul — not a top-level probability
  4. Borderline probabilities flip — never auto-act on 0.5-0.7, gate them
  5. noul(false) + noul(true) don't have to sum to 1

The gate pattern

from jevkit import gate

p = client.noul(...)          # System 1: calibrated fast decision
action = gate(p)              # act(>=0.7) / confirm(0.5-0.7) / escalate(<0.5)
if action == "act":           # only auto-act on high confidence
    do_the_thing()
elif action == "confirm":
    queue_for_review()        # borderline → human or System 2 (LLM review)

Default thresholds: act >= 0.7, confirm >= 0.5 — tuned for the "borderline flips" property (never auto-act in 0.5-0.7). Override per use case:

gate(p, act=0.8, confirm=0.6)   # stricter gate

System 1 (Jev) decides who/what to act on; System 2 (a chat model) handles the acting itself (writing, reasoning). This division keeps costs low and decisions calibrated.

Status

  • ✅ Client + CLI + gate pattern (validated with real API calls, R3 read-back)
  • ✅ Error handling: RuntimeError on HTTP errors (fallback-friendly)
  • 🚧 Tests + CI (in progress)

License

MIT

Metadata

Release files for jevkit 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jevkit 0.1.0
File Size Uploaded
jevkit-0.1.0.tar.gz 7.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jevkit 0.1.0
File Interpreter ABI Platform
jevkit-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 15.6 kB

Release files / jevkit-0.1.0.tar.gz

Download URL jevkit-0.1.0.tar.gz
Size 7.2 kB
Tags Source
SHA-256 checksum
How to use checksums
f1521378fa42a1f9dbe85bca96539e4b97c8e9b2557e1e025558ee910240d3fb
BLAKE2b-256 checksum
How to use checksums
866a8db6268319192c60cdbb3cedca2fefc9d22b9c1e2fe5189f181a93ef6014
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / jevkit-0.1.0-py3-none-any.whl

Download URL jevkit-0.1.0-py3-none-any.whl
Size 8.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6c1f9af79514074a25317e0a53fc49c9eab3b563020c88f1f9803096fd7853c7
BLAKE2b-256 checksum
How to use checksums
bcd0dfbe42f83688726a8e3a496e1164be2c5d9c1b5db71de4f99889ad7a7503
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release history Release notifications | RSS feed

0.1.1

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page