jev-gate

Jev (TypeSafe) decisions for n8n with a confidence gate: act on sure answers, send the rest to review, and calibrate the threshold on your own data.

Package Information

Released: this month
Downloads: 0 weekly / 0 monthly
Latest Version: 0.1.0
Author: Perseo

Documentation

n8n-nodes-jev-gate

An n8n community node for Jev, TypeSafe's decision model. Jev answers typed questions about your data with a probability for every option. This node acts on the answers Jev is sure about and sends the rest to a Review output, so a person or a larger model handles only the uncertain part.

Community node, maintained by Perseo. Not made or supported by TypeSafe.

What is different here

Confidence gate on by default Every item leaves through Confident or Review. Default threshold 0.95.
Fails closed A missing answer, an answer of the wrong type or a label outside your options goes to Review with the reason. It is never read as zero.
"None of these" added for you Every choice gets a none_of_these option, so off-topic text is not forced into the closest label.
Send only what the question needs State comes from the fields you pick. Sending the whole item shows a warning (see What we measured).
Several items per request Packs items into one call, bounded by item count and an input token budget.
Pinned model Defaults to jev-1.13, not an alias that moves. The model that answered is in the output.
Cost in the output Tokens and provider-reported cost per request and per item.
Calibrate Run your labeled examples through the same question and get accuracy and coverage per threshold, with a recommended one.
OpenRouter or TypeSafe One credential, either provider.

Installation

Self-hosted n8n: Settings → Community Nodes → Install, then enter n8n-nodes-jev-gate. See the community nodes guide.

n8n Cloud only lists nodes n8n has verified. This one is not verified.

Credentials

Create a Jev Gate API credential:

Field Notes
Provider OpenRouter (key from openrouter.ai) or TypeSafe (key from the TypeSafe console)
API Key Sent as Authorization: Bearer
Base URL Leave empty. Change only for a proxy.

The Test button checks the key (/v1/key on OpenRouter, /v1/models on TypeSafe).

Operations

All operations share State Source: Selected Fields (default), Text, JSON or Whole Item.

Decide

Ask one or more questions about each item, in one request. Question types:

Type You give You get
Choice Options, one per line, label: description the label, its confidence and every option's probability
Score Levels, lowest first the weighted score, the most likely level and a confidence
Yes/No Optional meaning of yes and no the probability of yes

Outputs: Confident and Review. Each question can use the default threshold, its own threshold, or stay out of the gate.

Real output from examples/triage-with-review.json:

{
  "message": "I was charged twice for my March invoice. Please refund the duplicate charge.",
  "jev": {
    "team": {
      "value": "billing",
      "confidence": 1,
      "probabilities": { "sales": 0, "technical": 0, "billing": 1, "none_of_these": 0 }
    },
    "urgent": { "value": 0.08, "confidence": 0.92 },
    "frustration": {
      "value": 0.22,
      "confidence": 0.68,
      "probabilities": { "0": 0.78, "1": 0.22, "2": 0 },
      "level": "Calm"
    },
    "review": { "needed": false, "reasons": [] },
    "meta": {
      "model": "typesafe/jev-1.13-20260917",
      "items_in_request": 1,
      "request_input_tokens": 456,
      "request_cost": 0.000019152,
      "cost_per_item": 0.000019152
    }
  }
}

In that same run, "Can you tell me a good recipe for banana bread?" and "Hi" left through Review, both answered none_of_these.

Questions can also be written as JSON, in the shape of the API's questions map, plus two optional keys the node reads and does not send: threshold and gate: false.

Route

One choice. Each route is an output, plus Review for answers below the threshold and for none_of_these.

Calibrate

Give items with a label field (the right answer, set by a person) and one question. The node returns one report:

Real output from examples/calibrate-threshold.json, 12 labeled messages in one request:

{
  "question": "team",
  "labeled": 12,
  "accuracyWithoutGate": 0.9166666666666666,
  "thresholds": [
    { "threshold": 0.5, "confident": 11, "coverage": 0.9166666666666666, "confidentAccuracy": 1, "errorsPassed": 0 },
    { "threshold": 0.95, "confident": 10, "coverage": 0.8333333333333334, "confidentAccuracy": 1, "errorsPassed": 0 },
    { "threshold": 0.99, "confident": 8, "coverage": 0.6666666666666666, "confidentAccuracy": 1, "errorsPassed": 0 }
  ],
  "recommendedThreshold": 0.5,
  "totalCost": 0.00008904,
  "model": "typesafe/jev-1.13-20260917"
}

The one item Jev got wrong ("The app is slow and I was also billed wrong", labeled technical, answered billing) came back with confidence 0.49, under every threshold, so no gate let it through. Twelve items cost $0.000089 and 410 ms in total.

The recommended threshold is the lowest one whose error rate among passed items is within Max Error Rate (default 0).

How the gate works

  • Choice and score use Jev's confidence. Yes/No uses the larger of p and 1 − p, so 0.02 and 0.98 are both confident and 0.4 is not.
  • An item goes to Review if any gated question is below its threshold, or if any answer does not match the question.
  • API errors fail the node. With Continue On Fail, the item goes to Review with the error.

What we measured

Numbers from our own tests on jev-1.13 through OpenRouter, September 2026. The test set was small and easy (48 short messages, 94 extraction checks). Treat them as behavior notes, not accuracy claims for your data.

  • Probabilities vary between identical calls; confident decisions did not. Across three runs, 33% of responses were identical to the digit. No decision above 0.95 changed. The few that flipped between runs had confidence under 0.8. The variation sits in the middle: up to 0.22 when p was between 0.3 and 0.7, almost nothing below 0.1 or above 0.7. Put thresholds outside that band.
  • Packing kept the answers. 6, 12, 24 and 48 messages per request gave the same confident decisions as one per request. With 24 per request, cost per decision halved and time per item dropped from about 470 ms to about 20 ms.
  • Size alone did not hurt. Look-alike content did. Filling the state with up to 28k tokens of unrelated prose left accuracy unchanged. A product catalog of 2k tokens flipped two answers, because one option was defined as "vendor pitch". When that happened, confidence dropped (median 0.53 on the wrong answers), and a 0.95 gate held back every error. Hence Selected Fields as the default.

Writing good questions

  • Name the field Jev should read: "the message in the field message", not "this message". Jev reads literally.
  • One decision per question. Several questions in one request cost little.
  • Keep counts, numbers and dates in code; ask Jev to classify, not to calculate.
  • Put borderline cases in the option descriptions.
  • Run Calibrate on 50 or more labeled items from your own traffic before trusting a threshold.

Limits

  • Text only. Convert images, audio and files to text first.
  • Up to 64k tokens per request, 32k for the state plus the longest question.
  • English is where Jev is strongest. Test other languages on your own data.
  • Jev does not write text. Keep an LLM for steps that need prose.

Development

npm install
npm test        # builds, then runs the unit tests (no network, no key)
npm run lint
npm run dev     # starts n8n with this node loaded

npm run dev loads the node as CUSTOM.jevGate. Import the workflows in examples/dev/ there; the ones in examples/ use the npm name. Regenerate both with node scripts/build-examples.mjs.

Credits

Patterns adapted, with thanks, from other MIT-licensed Jev nodes: answer validation against the question (n8n-nodes-typesafe), outputs per route (n8n-nodes-jev), items per request (n8n-nodes-jev-classification) and an API verification checklist (n8n-nodes-typesafe-jev).

License

MIT

Discussion