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
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:
export TURN_DECISION_PROVIDER=mock
turn run examples/jev_triage.tnThe mock returns valid deterministic Choice, Score, and Noul shapes without an API key. It is for development and demonstrations, not model-quality evaluation.
export TURN_DECISION_PROVIDER=typesafe
export TYPESAFE_API_KEY=your-key
export TYPESAFE_MODEL=jev-latest # optional
turn doctor
turn run examples/jev_triage.tnThe 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.