The decide Primitive

decide(state, questions) asks a decision model to evaluate bounded questions against application state. It is separate from infer because generation and judgment have different contracts.

  • Use infer Type { ... } for plans, explanations, code, and other open-ended synthesis.
  • Use decide(state, questions) for classification, scoring, routing, and yes/no probabilities.

Both operations are Turn effect boundaries. The VM suspends, persists the continuation, invokes the selected provider, and resumes with a structured result.


Choice, Score, and Noul

triage.tn
let decision = decide(ticket, {
"department": {
  "type": "choice",
  "instructions": "Which team should handle this?",
  "criteria": {
    "billing": "Charges and refunds",
    "technical": "Bugs and integrations"
  }
},
"severity": {
  "type": "score",
  "instructions": "How severe is this issue?",
  "criteria": ["Cosmetic", "Degraded", "Blocking"]
},
"is_urgent": {
  "type": "noul",
  "instructions": "Does this need urgent attention?"
}
});

let route = decision["answers"]["department"];
if route["confidence"] < 0.8 {
call("echo", "Manual review");
} else {
call("echo", "Route: " + route["choice"]);
}

A Choice answer contains the selected option, its full probability distribution, and confidence. A Score answer contains a probability-weighted score, level legend, distribution, and confidence. A Noul answer is the probability that a yes/no statement is true.

NOTE

decide currently has static type Any because one request may contain heterogeneous answer types. Access answer fields through map indexing. Statically derived decision result types remain future work.


Providers

Turn uses a separate provider setting for decisions:

deterministic local mock
export TURN_DECISION_PROVIDER=mock
turn run examples/jev_triage.tn

The mock returns valid deterministic Choice, Score, and Noul shapes without an API key. It is for development and demonstrations, not model-quality evaluation.

TypeSafe Jev
export TURN_DECISION_PROVIDER=typesafe
export TYPESAFE_API_KEY=your-key
export TYPESAFE_MODEL=jev-latest   # optional

turn doctor
turn run examples/jev_triage.tn

The TypeSafe adapter maps Turn's provider-neutral request to the System One API. It preserves the model name, answer payloads, probability distributions, confidence values, and token usage.


Durable execution

Before calling a decision provider, Turn checkpoints both the continuation and pending request. If execution restarts while the request is pending, Turn replays it and resumes with the result.

WARNING

Effect delivery is at-least-once. Decision requests are normally read-only, but any non-idempotent external tool used before or after them should accept an idempotency key.

Completed and failed runs remove their checkpoints. Explicitly suspended runs remain available to turn inspect and later resumption.


Why the distinction matters

Decision models do not replace LLMs, and Turn does not hide either behind one vague AI call. A program can use a generative model to create a plan, a decision model to score or route it, deterministic code to enforce policy, and an actor or human to handle low-confidence cases.

The provider can change without changing the Turn control flow. TypeSafe Jev is the first decision backend; decide is the language contract.