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.1

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.1
File Size Uploaded
jevkit-0.1.1.tar.gz 6.5 kB Details

Built distribution (wheel)

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

Total release size: 14.9 kB

Release files / jevkit-0.1.1.tar.gz

Download URL jevkit-0.1.1.tar.gz
Size 6.5 kB
Tags Source
SHA-256 checksum
How to use checksums
d6fcb9eaa37a33eeeaa39e398a5a4e040640953a0894316dbd52e9c32b958be8
BLAKE2b-256 checksum
How to use checksums
367daa1903b006a703214d8adf030a6e33b9bf5985136dafcb18caf758c6ceaf
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.1-py3-none-any.whl

Download URL jevkit-0.1.1-py3-none-any.whl
Size 8.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a930999d4cd4d2f1594e6b47103219f692400bbbf6b4c722d26054a5bfd4c950
BLAKE2b-256 checksum
How to use checksums
232fed218dd58f2ee954d5ad5f788d4c8385aeb32da46f3026c5af345e871b84
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

This release

0.1.1 This release

2 release files

0.1.0

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