Bun's internal typed decision capability bun:yolo adapts application-supplied judgments into
Noul booleans, named Choice keys and finite Score values. Rust validates the
request, provider response and primitive conversion. A judgment is a proposal;
application permission rules still authorize any subsequent operation.
import { decide, noul, choice, score, type Provider } from "bun:yolo";
export async function selectSource(provider: Provider) {
return await decide(
{
state: { query: "How do Bun.Video frames become images?", passage: "A curated source excerpt." },
questions: {
relevant: noul("Does `passage` help answer `query`?"),
route: choice("Which source fits?", { docs: "API documentation", graph: "Source relationships" }),
support: score("How directly does `passage` support `query`?", ["None", "Partial", "Direct"]),
},
},
{ provider, timeout: 10000, maxRetries: 0 },
);
}
// relevant: boolean; route: "docs" | "graph"; support: number in 0..2
One named batch shares one provider request. inspect, also exported as
systemOne, retains validated probabilities, model and usage. decide
returns primitives. A Noul becomes true only when its probability is greater
than threshold, which defaults to 0.5; equality returns false. Score can
be fractional. Clients must not rebuild these conversions or silently accept
unknown answers, enum keys, distributions or legends.
Choice abstention is a separate native operation. Validate the minimum with
confidenceThreshold(minimum) before starting the provider, then call
selections(request, result, minimum) on an inspected response. It returns
only Choice entries: the winning key at or above the minimum confidence,
otherwise null. Answers, distributions, model and usage stay unchanged.
This confidence minimum is distinct from the strict Noul probability threshold.
Providers and boundaries
Supply an application-owned Provider, or use the default remote() provider
with server-side TYPESAFE_API_KEY configuration. Private transport and
model configuration stay with the application owner. The client does not
become the validator. code adapts deterministic or asynchronous callbacks
through the same native validation; local borrows a caller-owned bun-llama
context without downloading weights. Local outputs are model judgments;
calibration, accuracy and trained weights require separate evidence.
The native API and exact interfaces are in packages/bun-types/yolo.d.ts.
Batches contain 1–64 questions; Choice has 2–255 options, Score has 2–10
criteria. Request and response JSON are each bounded to 1 MiB. timeout
bounds the complete operation, including retries, to 1–120000 ms.
maxRetries is 0–3, default zero. A caller AbortSignal cancels pending work.
Typed judgments do not generate an explanatory answer: an application may
separately generate text and then check its grounding against cited evidence.
Python SDK
The existing runtime SDK provides bun_yolo.Yolo, noul, choice and score
from packages/bun-runtime-sdk/python/ctypes. It has no Python HTTP or model
engine. Each call sends a private JSON envelope over stdin to a Bun worker,
which calls bun:yolo.inspect, decide or value. Structured descriptions
are preserved. Converted values return as Python bool, str or float.
client.inspect/system_one(..., minimum_confidence=0.8) returns the same raw
model, answers and usage, plus Rust-computed selections. Python never
compares the confidence itself. inspect_async provides the same cancellation
and lifetime behavior as decide_async.
import os
from pathlib import Path
from bun_yolo import Yolo, noul
from yolo_runtime import Runtime
# The release owner provisions a verified SDK manifest and qualified Bun.
with Runtime() as runtime:
client = Yolo(runtime, Path(os.environ["BUN_EXECUTABLE"]))
result = client.value({"type": "noul", "noul": 0.8}, noul("Fixture answer"))
assert result is True
This example validates a supplied answer without model inference. Provider
configuration for inference comes from the caller's protected configuration;
no key is embedded in source. Yolo borrows the Runtime, accepts one active
call per instance and never closes that borrowed handle. Each child has at
most 1 MiB of input and captured output. transport_timeout_ms bounds the
supervised wait (default 130000 ms); native options.timeout still bounds
inference. cancel() cancels the native completion operation, stops the owned
child and releases its handles. await client.decide_async(...) uses the
same call and joins native cleanup when the Python task is cancelled.
The supervisor must advertise process.stdin and process.wait, added in
C ABI 1.6. A legacy ABI 1.4/1.5 installation is refused before private process
creation. No state, token or provider body is put in argv, a temporary file
or diagnostics. No polling fallback is used. Native errors return bounded
names/codes; raw messages are deliberately not transported.
Python transport fixtures do not qualify native execution. The native SDK and the Bun binary need separate per-target gates. Optional official Python provider-client compatibility, local-model execution, live provider accuracy and a published release remain separate qualifications. Existing application decision workflows and curated evals are retained until their consumer import switch passes; source migration alone does not authorize their removal.