Build on Kai, Hanzo's decision model: it answers typed questions about a state with calibrated probabilities over options you name, and generates no text (POST https://api.hanzo.ai/v1/decisions). Load when code needs a bounded judgment over known options, such as classify, route, gate an action, rank candidates, extract by picking one of the values code found, or verify a claim or field against its source, where the alternative is prompting an LLM and parsing its prose; when writing choice, score or noul questions, confidence thresholds or escalation; when calling Kai over HTTP, from the hanzo-kai (Python) or @hanzo/kai (TypeScript) SDK, or through the kai_* MCP tools; or when moving an integration off TypeSafe's Jev.
Kai decides; it does not write. Send a state (text or JSON) and named questions, and each answer comes back as a probability over options you wrote: which label, whether a statement holds, which level of a scale. No prose, no reasoning, usage.output_tokens is 0. Your code reads the numbers and decides what to do.
Kai is for bounded judgments inside a program. Writing text, open questions, arithmetic and fact lookup belong to code, search or a Zen model.
The docs outrank this skill: read the pages a task needs before writing code. llms.txt indexes every page, and each page's markdown is at https://docs.hanzo.ai/llms.mdx/docs/<path>/content.md. The /docs/kai section is new, and some of its pages may not be published yet. Decisions (the wire) and Kai (the model) are live; when a newer page is missing, say so and work from those two.
| Task | Read | |---|---| | The map of the section | overview | | First call: key, curl, Python, TypeScript, MCP | quickstart | | Request, response, limits, errors, price | decisions | | What a typed decision is | concepts | | What to put in state | state | | Choosing and wording questions | questions, then choice, score, noul, structure | | Thresholds and escalation | confidence | | Breaking a feature into decisions | build, patterns, use cases | | Worked recipes | cookbook, route, triage, gate, loop | | Where the model is weak, measured | limits | | SDKs | Python, TypeScript | | This skill and the MCP tools | agents | | Programs, caches, local runtime | programs | | Moving from Jev | migrate from Jev |
state_too_long, naming the tokens needed and the limit, and nothing is cut silently. Leave secrets and data you may not share out of it.instructions.criteria maps each label to a description of what sets it apart; keep the options mutually exclusive. /v1/decisions sets no label cap: a wide choice is narrowed by retrieval over every option, then scored. Each option is read whole up to 512 tokens; a longer one is a 422. Add an other or none label for cases yours do not cover; without one, Kai must choose among them.criteria lists the levels lowest first, every one described, none null. score is the expected level; the most probable level is the largest entry of probabilities.criteria (true and false), or better, ask a choice whose labels name the outcomes (refund, other), never yes and no. The current checkpoint answers some plain yes/no questions badly, so measure the form you pick.confidence on a choice or score is (n·p_max − 1)/(n − 1): 0 when every option is equally likely, 1 when one holds all the mass, so one threshold means the same over 3 options or 30. A noul's noul is P(true) and its confidence is |2p − 1|; read 0.5 as a coin flip.id, state_hash and routing.checkpoint beside the action taken.sk- key; a publishable pk- key gets 403. Never ship one to a browser.HTTP works today:
curl https://api.hanzo.ai/v1/decisions \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "kai",
"state": {"ticket": "The export button throws a 500 error since this morning."},
"questions": {"team": {"type": "choice",
"instructions": "Which team should handle this ticket?",
"criteria": {"billing": "charges, invoices, refunds",
"tech": "bugs, errors, outages",
"other": "anything else"}}}}'
Read answers.team.choice, its confidence, and probabilities over every label. Errors: 400 malformed JSON or unknown model, 401 bad key, 402 no plan or balance, 403 publishable key, 422 a malformed question or a state too long, 429 and 529 (wait Retry-After, then retry).
The SDKs and MCP tools are new. If a package or tool is not published where you are, use HTTP. Both SDKs read HANZO_API_KEY.
from hanzo_kai import Kai, Choice # uv add hanzo-kai
teams = {"billing": "charges, invoices, refunds", "tech": "bugs, errors, outages", "other": "anything else"}
with Kai() as kai:
d = kai.decide(state={"ticket": "The export button throws a 500 error."},
questions={"team": Choice(instructions="Which team should handle this ticket?", criteria=teams)})
print(d.choices["team"].choice)
import { Kai, choice } from "@hanzo/kai"; // npm i @hanzo/kai; server-side only
const teams = { billing: "charges, invoices, refunds", tech: "bugs, errors, outages", other: "anything else" };
const d = await new Kai().decide({
state: { ticket: "The export button throws a 500 error." },
questions: { team: choice("Which team should handle this ticket?", teams) },
});
console.log(d.answers.team.choice); // typed "billing" | "tech" | "other"
MCP: the Hanzo MCP tools kai_decide, kai_choice, kai_score and kai_noul.
A Jev integration keeps its state, its questions and the shape of its answers, and moves one of two ways:
TYPESAFE_BASE_URL=https://api.hanzo.ai and TYPESAFE_DEFAULT_MODEL=kai, with a Hanzo sk- key in TYPESAFE_API_KEY. Name kai: no Jev model id becomes Kai.hanzo-kai or @hanzo/kai, or call POST https://api.hanzo.ai/v1/decisions with "model": "kai".Either way, describe every score level (a null level is refused), then re-run the labeled cases on Kai and set thresholds again; Jev's do not carry over.
Price: 50% lower input-token list price ($0.021 vs $0.042 per 1M). On the frozen harness Kai a7 is more accurate than Jev on 11 of 12 suites, and Jev leads jailbreak 0.940 to 0.920 (results). The Jev guide has the field-by-field differences.
npx skills add https://hanzoskills.com/kai.md
With GitHub access to hanzoai/skills: npx skills add hanzoai/skills --skill kai, or in Claude Code claude plugin marketplace add hanzoai/skills, then claude plugin install kai@hanzoai-skills.