---
title: Typed decision boundaries
description: Confidence, abstention, provider limits and the Python SDK for bun:yolo typed decisions.
---

[`bun:yolo`](/docs/runtime/yolo) adapts application-supplied judgments into
Noul booleans, named Choice keys and finite Score values. Bun validates the
request, provider response and primitive conversion natively. A judgment is a
proposal; application permission rules still authorize any subsequent operation.

```ts
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`, keeps the 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. Unknown answers, choice keys, distributions or legends are
rejected.

## Confidence and abstention

Choice abstention is a separate operation. Validate the minimum with
`confidenceThreshold(minimum)` before calling the provider, then call
`selections(request, result, minimum)` on an inspected response. It returns
only Choice entries: the winning key when its confidence is at or above the
minimum, otherwise `null`. Answers, distributions, model and usage stay
unchanged. This confidence minimum is distinct from the Noul probability
threshold.

## Providers and limits

Supply your own `Provider`, or use the default `remote()` provider configured
with the server-side `TYPESAFE_API_KEY` environment variable. `code` adapts
deterministic or asynchronous callbacks through the same validation; `local`
borrows a caller-owned `bun-llama` context without downloading weights. Local
outputs are raw model judgments and are not calibrated. The full type
definitions are in
[`packages/bun-types/yolo.d.ts`](https://github.com/aphrody-labs/bun/blob/main/packages/bun-types/yolo.d.ts).

Batches contain 1–64 questions; Choice has 2–255 options and Score has 2–10
criteria. Request and response JSON are each limited to 1 MiB. `timeout`
bounds the complete operation, including retries, to 1–120000 ms.
`maxRetries` is 0–3, default 0. A caller `AbortSignal` cancels pending work.
Typed judgments do not generate an explanatory answer: an application may
generate text separately and then check its grounding against cited evidence.

## Python SDK

The runtime SDK in
[`packages/bun-runtime-sdk/python/ctypes`](https://github.com/aphrody-labs/bun/tree/main/packages/bun-runtime-sdk/python/ctypes)
provides `bun_yolo.Yolo`, `noul`, `choice` and `score`. It has no Python HTTP
client or model engine. Each call sends a JSON envelope over stdin to a Bun
worker, which calls `inspect`, `decide` or `value` from `bun:yolo`. Converted
values return as Python `bool`, `str` or `float`.
`client.inspect(..., minimum_confidence=0.8)` (alias `system_one`) returns the
raw `model`, `answers` and `usage`, plus the computed `selections`.
`inspect_async` and `decide_async` are the asynchronous variants.

```python
import os
from pathlib import Path
from bun_yolo import Yolo, noul
from yolo_runtime import Runtime

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
credentials come from the caller's configuration; no key is embedded in
source. `Yolo` borrows the `Runtime`, accepts one active call per instance and
never closes the borrowed handle. Each child process has at most 1 MiB of
input and captured output. `transport_timeout_ms` bounds the wait for the
worker (1–130000 ms, default 130000); `options.timeout` still bounds
inference. `cancel()` cancels the pending operation, stops the child process
and releases its handles. When the Python task running
`await client.decide_async(...)` is cancelled, the call waits for native
cleanup.

The runtime library must support the `process.stdin` and `process.wait`
capabilities (C ABI 1.6 or later); older installations are refused before a
process is created. State, tokens and provider bodies are never passed in
argv, temporary files or diagnostics. Native errors return bounded names and
codes without raw messages.
