Hanzo AI
Hanzo decision model · 0 output tokens

How to Use Kai

Send a state and typed questions to POST /v1/decisions with model: "kai". Kai answers each question with a probability for every answer it allows, and writes no text.

Questions

Three question types

Name each question; its answer comes back under the same name.

choiceSend criteria: option → description, or a list of options.Get choice, probabilities (one per option, summing to 1), confidence.
scoreSend criteria: the levels, lowest first.Get score (the expected level index), legend, probabilities by level index.
noulSend instructions: a yes/no question.Get noul: P(true). kai-1.3, the default, does not read a noul’s criteria.

Call it

One request, three questions

Every response also carries id, model, usage (output_tokens is 0), routing (the checkpoint that answered: kai-1.3 for the model id kai), state_hash and latency_ms.

curl -sS --fail-with-body https://api.hanzo.ai/v1/decisions \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kai",
    "state": "Customer email: Cancel my plan immediately. Your service was down during our product launch.",
    "questions": {
      "department": {
        "type": "choice",
        "instructions": "Route ticket to appropriate team",
        "criteria": {
          "executive_escalations": "high-value customer cancellation threats",
          "support": "general technical inquiries",
          "billing": "standard invoice updates"
        }
      },
      "urgency": {
        "type": "score",
        "instructions": "Rate ticket urgency",
        "criteria": ["low", "normal", "high", "critical"]
      },
      "churn_risk": {
        "type": "noul",
        "instructions": "Is this account at risk of churning?"
      }
    }
  }'
# pip install hanzoai
import os

from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import AiApi
from hanzoai.cloud.models.ai_decisions_request import AiDecisionsRequest

ai = AiApi(ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"])))
decision = ai.post_decisions(AiDecisionsRequest.from_dict({
    "model": "kai",
    "state": {"ticket_id": 4821, "text": "Can I get an extension on my payment due date?"},
    "questions": {
        "team": {
            "type": "choice",
            "instructions": "Which team handles this?",
            "criteria": {"billing": "invoices and payments", "support": "technical issues"},
        },
        "is_churn_risk": {"type": "noul", "instructions": "Is the user churning?"},
    },
}))

print(decision.answers["team"].choice, decision.answers["team"].probabilities)
print(decision.answers["is_churn_risk"].noul)
// npm install hanzoai
import { AiApi, Configuration } from 'hanzoai'

const ai = new AiApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }))
const { data: decision } = await ai.postDecisions({
  aiDecisionsRequest: {
    model: 'kai',
    state: { pull_request: 104, diff_lines: 480, files: ['auth.ts', 'token.go'] },
    questions: {
      risk: {
        type: 'score',
        instructions: 'Rate security risk of code change',
        criteria: ['low: documentation or cosmetic', 'medium: internal logic', 'high: security or auth paths'],
      },
    },
  },
})

console.log(decision.answers.risk.score, decision.answers.risk.probabilities)

Limits

What a request may hold

ModelThe model id kai answers from kai-1.3, the default. Ask for kai-1.4 by id for the unified version: one encoder and one head, trained on long states. Ask for kai-1.5 by id for the agentic preview: whether a tool fits a request, and whether to call one at all.
QuestionsUp to 100 a request; 101 is refused with 422.
Statekai-1.3, the default, was trained on 1,024 tokens of state beside each question. Up to 32,768 is answered with routing.extrapolated: true and is unreliable: a fact at the end of a 3,982-token state read 0.507. kai-1.4 was trained on long states and marks no read up to 32,768 extrapolated. Past 32,768 the answer is 422 state_too_long.
TimeOne yes/no question takes <1 ms of server time at p50 in production on GPU (0.27 ms cached in process). Every response reports its own latency_ms.
Price$0.021 per million input tokens; output is free. Jev costs $0.042.

Recipes & Blueprints

Composable Decision Recipes

Modular Rust structs and TypeScript workflows that sit inside your pipelines: retail triage, industrial diagnostics, confidence routing, and agent loops.

recipes::retailShelf inventory triage, return fraud checks, and corporate pricing safety guardrails.
recipes::industrialMulti-criteria powertrain trade studies and telemetry equipment readiness gating.
recipes::routingConfidence margin gates that stand on high-certainty decisions and escalate low-confidence queries to Zen.
recipes::zenOpenAI-compatible request builders and SSE stream accumulators for reasoning thought tokens.
recipes::kataAutonomous test-and-repair agent state machine gating code patch generation vs human review.
recipes::genConversational assistant harness managing multi-turn history and Model Context Protocol (MCP) dispatch.

Coming from Jev

Change the URL, the key and the model

Kai takes the request body Jev takes. The same endpoint also serves typesafe/jev-1.13 with a Hanzo key, at Jev’s price.

# Jev on OpenRouter
curl https://openrouter.ai/api/alpha/decisions \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "typesafe/jev-1.13", "state": "…", "questions": {…}}'
# Kai on Hanzo: the same body
curl https://api.hanzo.ai/v1/decisions \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "kai", "state": "…", "questions": {…}}'
What differs: Kai answers at most 100 questions a request, refuses a state past 32,768 tokens with 422, and kai-1.3, the default, ignores a noul’s criteria. OpenAI’s Decisions body (input and a list of questions) is refused.On the frozen harness, kai-1.4 averaged 84.4% accuracy against Jev’s 76.6% across the 11 suites it leads, both models on the same questions.