cd /news/ai-tools/show-hn-ephemeral-runner-for-jev-sty… · home › topics › ai-tools › article
[ARTICLE · art-140159] src=github.com ↗ pub= topic=ai-tools verified=true sentiment=· neutral

Show HN: Ephemeral runner for JEV-style models

Developer zatsepin released jigor, a Rust-based zero-shot classifier runner that executes JEV-style decision models locally via ONNX or remotely through OpenRouter's Decisions API. The tool installs via npm (@zatsepin/jigor), pip (jigor), or cargo (jigor-cli) and supports ephemeral execution through npx or uvx, with local backends von (sevenreasons/von-onnx-fp16, 759M model.onnx) and laya (Mattepiu/laya-onnx, fp32 and int8 variants) plus remote models typesafe/jev-1.13 and jaredpalmer/kev-4b. A sample remote call to typesafe/jev-1.13 returned a noul probability of 0.92 at a billed cost of $0.000012306 for 293 input tokens and 24 output tokens.

read7 min views1 publishedSep 26, 2026
Show HN: Ephemeral runner for JEV-style models
Image: Michielbdejong (auto-discovered)

This is a zero-shot classifier models gateway or runner.

Or, if you prefer marketing terms, "System one decision" models.

This is written in Rust (blazing fast as it should be), one wire protocol across backends: von and laya run locally as ONNX (via ort); jev runs remotely on OpenRouter's Decisions API.

  • HF sevenreasons/von-onnx-fp16 (model.onnx 759M,tokenizer/tokenizer.json 3.5M)
  • HF Mattepiu/laya-onnx (laya.onnx fp32 — matches the python reference bit-for-bit;int8/laya_int8.onnx viaLAYA_ONNX_FILE )
  • OpenRouter Decisions (typesafe/jev-1.13 ,jaredpalmer/kev-4b )

You can install it via npm, pip, or cargo. Is it enough? If not -> subscribe

npm install --global @zatsepin/jigor
pip install jigor
cargo install jigor-cli --locked
cargo bininstall jigor-cli

You can use ephemeral execution with npx or uvx.

npx @zatsepin/jigor ask --model von <<'JSON'
{
  "state": { "error": "Disk volume /var/log at 98% capacity." },
  "questions": {
    "requires_intervention": {
      "type": "noul",
      "instructions": "Does this disk space condition require operational intervention?"
    }
  }
}
JSON
{"answers":{"requires_intervention":{"noul":0.7822,"type":"noul"}},"backend":"local","model":"von-1.0.0"}

If you have OPENROUTER_API_KEY in your env, you can easily run this from your terminal and get a quick response.

npx @zatsepin/jigor ask --model jev <<'JSON'
{
  "state": { "error": "Disk volume /var/log at 98% capacity." },
  "questions": {
    "requires_intervention": {
      "type": "noul",
      "instructions": "Does this disk space condition require operational intervention?"
    }
  }
}
JSON
{"answers":{"requires_intervention":{"noul":0.92,"type":"noul"}},"backend":"openrouter","model":"typesafe/jev-1.13","usage":{"cost":0.000012306,"input_tokens":293,"output_tokens":24}}

Feel free to use it with your agents. This README.md is enough to teach them how to use it.

One dependency, one entry per backend — noul/ choice/ score questions in, typed answers out. Identical on von, laya and any OpenRouter model.

[dependencies]
jigor = { path = "../jigor" }                             # local checkout
serde_json = { version = "1.0" }                          # Value, json!
use jigor::{Answer, Question, Backend, Result, VonBackend, choice, noul, score};
use serde_json::json;

fn main() -> Result<()> {
    let mut von = VonBackend::new()?;   // VonBackend::new, LayaBackend::new,
                                        // OpenRouterBackend::for_model(...):
                                        // the same answers() call on all three
    let questions = vec![
        noul("churn", "Is the customer likely to churn?"),
        choice(
            "want",
            "What does the customer want?",
            &["refund", "order status", "technical help"],
        ),
        score("urgency", "How urgent is this?", &["calm", "annoyed", "angry"]),
    ];
    let asks = von.answers(
        &json!("Customer: I was charged twice for order #4471."),
        &questions,
        None,
    )?;

    match asks.get("churn").unwrap() {
        Answer::Noul { probability } => println!("churn: {:.4}", *probability),
        _ => {},
    }
    Ok(())
}

Only have a model id? jigor::ask resolves aliases and the provider for you:

let asks = jigor::ask("jev", &state, &questions, None)?;  // OpenRouter jev
let asks = jigor::ask("laya", &state, &questions, None)?; // local laya
// Asks { model, backend, answers, usage }
// usage: tokens + billed cost (USD) on remote asks, None for local backends

Errors are one type — jigor::Error (carried by jigor::Result<T>): UnknownModel/ MissingApiKey/ Remote for routing and OpenRouter responses, Wire/ MissingAnswer/ MissingAnswers for malformed question/answer payloads, Serialization for JSON text, External/ Internal for everything else. No foreign error type ever leaks out of the library.

use jigor::{Error, Result};

match von.answers(&state, &questions, None) {
    Ok(asks) => { /* typed answers */ }
    Err(Error::Remote { status, message }) => { /* upstream 4xx/5xx */ }
    Err(e) => println!("{e}"),
}

The local ONNX models (von, laya) download to ~/.cache/huggingface on first use.

Set OPENROUTER_API_KEY for the remote jev backend.

cargo run -p jigor --example decide
cargo run -p jigor --release --example bench
cargo run -p jigor --example decide --offline

Expected decide:

infrastructure
0.428
{'infrastructure': 0.6203, 'billing': 0.1873, 'feature_request': 0.1924}
judge: 0.3586
rate score: 1.02 conf: 0.707 probs: {"1": 0.8109, "2": 0.1036, "0": 0.0855}
fan-out intent: payment_failure 0.539

Set JIGOR_DEVICE=cuda to try CUDA EP (ort cuda feature, falls back to CPU if unavailable).

jigor serve --host 0.0.0.0 --port 8000   # HTTP gateway

The gateway mirrors the library: noul/choice/score questions in, typed answers out — von/ laya locally, anything else routed to the OpenRouter backend selected by the model field:

curl -X POST http://localhost:8000/v1/systemone \
  -H "Content-Type: application/json" \
  -d '{
    "model": "von-1.0.0",
    "state": { "error": "Disk volume /var/log at 98% capacity." },
    "questions": {
      "requires_intervention": {
        "type": "noul",
        "instructions": "Does this disk space condition require operational intervention?"
      }
    }
  }'

Route by provider + model pair — typesafe/jev-1.13 (alias jev) and jaredpalmer/kev-4b (alias kev) go to OpenRouter, von-1.0.0 (alias von) stays local; unknown pairs are rejected. Responses from the OpenRouter backend add usage (tokens + cost in USD) next to answers, so each /v1/systemone call reports what it cost.

Also: GET /healthz returns {"status":"ok"}.

examples/tweet.rs is a complete Tweet Tester written only against the lib API — it demonstrates how to build a Jev-style tool on top of noul/ choice/ score questions through one answers interface. All tweet-specific code lives in the example:

  • the 61-question viral-score bank (question set v1.1 , 8 families EMO/CNV/SHR/TIM/CRF/IDN/FMT/ANTI);
  • a transparent 0-100 aggregation (0.65 * content mean + 0.35 * clean anti-signal ) — scoring semantics: 50 = your account's normal post, above 50 beats it, below 50 does worse;
  • per-family "fired % of N questions" radar stats, top helped/hurt, and engagement counters (a wire JSON shape mirroring the viral-score API).
cargo run -p jigor --example tweet -- "We just crossed 10,000 paying customers. Thank you."
cargo run -p jigor --example tweet -- --json "We just crossed 10,000 paying customers."

The example resolves the backend by model, exactly like jigor ask: --model von (default, local ONNX), --model jev (OpenRouter) or any other alias. The 61-question bank, score, radar and counters are identical across backends, so you can compare the same tweet side by side:

cargo run -p jigor --example tweet -- --model von "We just crossed 10,000 paying customers. Thank you."
cargo run -p jigor --example tweet -- --model jev "We just crossed 10,000 paying customers. Thank you."
cargo run -p jigor --example tweet -- --model jev --json "Hot take." > jev.json

For the milestone tweet the outputs line up: von gives 53/100 (conservative, CRAFT 35%), jev gives 63/100 (CRAFT 73%). Scores across backends are not calibrated to each other, but the shape is directly comparable.

Family fired is the "X% of its questions fired" radar value. The engagement counters (multiples, p75/p90, probabilities) and the effect coefficients are transparent placeholders for a fitted engagement model — tune the weights in the example's counter_json/ counter_multiple once you have paired data. Von is a general decision model, so scores are a signal, not a forecast; fitting an engagement model on the same answers is the calibration step.

Question builders: choice takes plain option strings (each is both key and description), choice_pairs takes (key, description) pairs, score takes ordered level texts, noul a plain instruction — and all three kinds mix freely in one answers call.

examples/tagger.rs shows a choice workflow: given a note and a list of existing tags, one question — "Which tag best matches the content of this note?" — picks the best tag (or the None of these fit well fallback) with a probability distribution. Also runs on either backend via --model/--provider.

cargo run -p jigor --example tagger -- --title "Hiring notes" --tags "work, ideas, personal" "Budget approved for two engineers."
cargo run -p jigor --example tagger -- --model jev --tags "bugs, docs, ship" "Fixed the retry loop that dropped webhook events."
cargo run -p jigor --example tagger -- --json --tags "a, b" "note text"   # wire JSON out

Requires hurl and the local ONNX model (downloaded on first run). Wire fixtures live in tests/fixtures/ (the OpenRouter Decisions request/response payloads are the reference for the wire format).

make test        # unit tests + hurl suite + CLI tests
bash tests/hurl/run.sh   # jigor serve: /v1/systemone (health, noul, choice,
bash tests/cli/ask.sh    # jigor ask / jigor models over stdin fixtures
hurl --test --variable BASE_URL=http://localhost:8000 tests/hurl/*.hurl

You can subscribe. I will not spam you, but 100% will share my work with you sometimes. I am lazy, don't worry too much.

Or try one of my apps:

── more in #ai-tools 4 stories · sorted by recency
── more on @jigor 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/show-hn-ephemeral-ru…] indexed:0 read:7min 2026-09-26 · —