Colloq GitHub

Jev as a choice chooser

Status: v0 experiment. One binding file, one choice state, one decision per call.

The gap it fills

A choice state names the role that selects a branch:

{ "kind": "choice", "id": "route", "chooser": "router",
  "branches": { "cached": "reply-cached", "infer": "reply-infer", "review": "reply-review" } }

Colloq checks that the chooser emits a declared label (EndpointMachine::emit_select), but Colloq does not decide which label. Today that is hand-written code in the chooser. A Jev binding lets TypeSafe's Jev System One model make that selection as a typed Choice judgment.

Colloq keeps the protocol. Jev only proposes one of the declared labels. It never writes to the wire, never adds a branch, and never changes the conversation identity.

The binding

A binding is a separate file, so the conversation schema and its content identity do not change. See examples/route.colloqjev.json and the schema.

{
  "colloq_jev": "0.1.0",
  "conversation": "example.route",
  "state": "route",
  "model": "jev-latest",
  "instructions": "How should the router handle this incoming request?",
  "criteria": {
    "cached": "A common question with a fixed answer ...",
    "infer": "A new question that needs a model to write a specific answer",
    "review": "A request a person must handle ..."
  },
  "threshold": 0.95,
  "escalate": "review"
}

Fail-closed validation

jev::bind validates the conversation first, then the binding. Nothing is sent to Jev unless every check passes.

Code Rule
CLQJ001 Unsupported binding format.
CLQJ002 The binding names a different conversation module.
CLQJ003 model is empty.
CLQJ004 threshold is not within 0..=1. There is no default.
CLQJ005 Fewer than two criteria.
CLQJ006 The state is not a choice.
CLQJ007 The state does not exist.
CLQJ008 A criterion is not a branch of the state.
CLQJ009 A branch other than escalate has no criterion, so Jev could never select it.
CLQJ010 escalate is not a branch of the state.

Decision rule

Jev answer Label emitted
confidence >= threshold Jev's choice
confidence < threshold the escalate branch
choice outside the criteria, or confidence outside 0..=1 typed failure jev.invalid_answer
missing key, transport error, non-2xx response typed failure jev.unavailable

Colloq never picks a branch silently when Jev fails. The caller decides what a Jev failure means for the session, for example by observing a declared failure. 429 and 529 responses are retried twice with backoff, as the TypeSafe API reference asks.

Every decision returns the evidence behind it: label, Jev's choice, confidence, threshold, escalated, the full probabilities, and the model.

Try it

# Validate only. No network call.
cargo run -- jev-check examples/route.colloqconv.json examples/route.colloqjev.json

# One live decision. The key stays in the environment and is never logged.
export TYPESAFE_API_KEY=...
cargo run -- jev-decide --state-json '{"text": "I want my money back for last month."}'

From Rust, implement or use a jev::Decider and pass the decision's label to emit_select:

let bound = colloq::jev::bind(&conversation, binding)?;
let client = colloq::jev::TypeSafeClient::from_env(Duration::from_secs(10))?;
let decision = bound.decide(&client, &state)?;
machine.emit_select(&decision.label)?;

Observed smoke run

Three live calls to jev-latest on 2026-09-19 with the example binding (threshold 0.95). This is a smoke test of the integration, not an accuracy measurement.

Request Jev choice Confidence Label emitted
"What are your opening hours on Saturday?" cached 0.99 cached
"Can you explain how Colloq projects a conversation into endpoint machines?" infer 0.94 review (escalated)
"I was charged twice and I want a refund now or I will contact my lawyer." review 1.00 review

The second row is the threshold doing its job: a correct but less certain answer takes the declared escalation branch instead of advancing on its own.

What this does not claim

  • Typed output guarantees the interface, not the truth of the judgment.
  • Confidence is a property of Jev's distribution, not of the workflow. The right threshold depends on the workload and the cost of a wrong branch. Measure it on representative data before relying on it. With a high threshold and an unfamiliar domain, most traffic will take the escalation branch; that is the intended safe behavior, not a success metric.
  • The call is a blocking HTTPS request to a hosted service. Its latency is outside Colloq's microsecond transition measurements and is not included in any benchmark.

Deferred

  • Declaring Jev bindings inside the conversation (changes the schema and content identity).
  • Recording Jev decisions in Colloq semantic traces and evidence reports.
  • Jev inside the runtime demos, batching several choice states into one request, and a private or self-hosted model endpoint.

Edit this page on GitHub