Enso
Enso is Hanzo's own model family: five models, Enso Auto as the default and four paid tiers, Flash, Pro, Max and Ultra, each under one id and one price. Which one for which job, what it costs, fast mode, and who serves a request.
After this page you know which Enso id to send for a job, what a call costs,
which models answer it, and how enso-auto picks a tier for you.
Enso is Hanzo's own family on api.hanzo.ai: five models, and all five read
images. enso-auto is the default for everyone, the Free plan included: it
picks a tier per request and bills at the tier that answers. The four tiers,
enso-flash, enso-pro, enso-max and enso-ultra, each run an ordered
chain of frontier models under one id and one price, so when one vendor is down
the next rung answers and the bill does not change. Enso is also the router
behind model: "auto".
Pick a tier
| Send | For |
|---|---|
enso-auto | any job, when you would rather not choose; the default. It picks the tier |
enso-flash | volume: reads, searches, small edits, extraction, an agent's routine turns |
enso-pro | everyday coding and analysis |
enso-max | turns that need more than Pro, at less than Ultra's price |
enso-ultra | the hardest turns: a refactor across many files, a bug the other tiers missed, a plan the rest of a run depends on |
Prices
Per million tokens, in US dollars. A call bills its tier's price whichever model in the chain answered it.
| Id | Input | Output | Cache read | Cache write |
|---|---|---|---|---|
enso-flash | 0.33 | 1.65 | 0.033 | 0.4125 |
enso-pro | 3.30 | 16.50 | 0.165 | 4.125 |
enso-max | 4.30 | 21.50 | 0.215 | 5.375 |
enso-ultra | 5.236 | 26.18 | 0.2618 | 6.545 |
enso-auto bills the price of the tier that answers. The gateway is the
authority on what a call costs, and answers with every id's input and output
rate, no key needed:
curl -s https://api.hanzo.ai/v1/models \
| jq -r '.data[] | select(.id | test("^enso-")) | "\(.id)\t\(.pricing.input_per_million)\t\(.pricing.output_per_million)"'Against api.hanzo.ai's own list for the models the tiers stand in for:
| Model | Input | Output | Cache read | Cache write |
|---|---|---|---|---|
| Claude Sonnet 5.5 | 2.11 | 10.55 | 0.1055 | 2.6375 |
enso-pro | 3.30 | 16.50 | 0.165 | 4.125 |
| Claude Opus 5.5 | 4.22 | 21.10 | 0.211 | 5.275 |
enso-max | 4.30 | 21.50 | 0.215 | 5.375 |
enso-ultra | 5.236 | 26.18 | 0.2618 | 6.545 |
| Claude Fable 5.1 | 10.55 | 52.75 | 0.26375 | 13.1875 |
| GPT-6 Astra | 10.55 | 52.75 | 1.055 | 13.1875 |
enso-pro costs more than Sonnet 5.5 and less than Opus 5.5 in every class.
enso-max costs a little more than Opus 5.5 and less than enso-ultra in
every class. enso-ultra costs less than Fable 5.1 and GPT-6 Astra in every
class.
Fast mode
All five models have a fast mode. Ask for it per request with "fast": true
in the JSON body, or with the header X-Fast: 1:
curl https://api.hanzo.ai/v1/chat/completions \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "enso-pro", "fast": true, "messages": [{"role": "user", "content": "Explain this stack trace."}]}'| Model | Fast price |
|---|---|
enso-auto, enso-flash | 2x |
enso-pro, enso-max | 3x |
enso-ultra | 4x |
A fast enso-auto call bills twice the price of the tier that answers. Fast
mode is always extra: it is billed from prepaid balance on every plan,
Unlimited included. Without prepaid balance, a fast request is served at the
normal speed and price.
Who serves a request
Where a request is served depends on who pays for it.
- Paying callers, with an active paid plan or a prepaid top-up, are served on Hanzo's NVIDIA lane first, then by paid providers, then by a no-cost fallback pool.
- Free-plan callers, and callers with no funds, are served by the fallback pool first, then by the NVIDIA lane.
What the NVIDIA lane serves counts against your plan's usage; Unlimited has no usage cap. What a paid provider serves is billed at list price from prepaid balance, on every plan.
What answers each tier
On a paid provider, each tier is an ordered chain. A rung is asked only when the one before it fails — an outage, a rate limit, a refusal — and never raced against another.
| Tier | Thinks | Window | Chain, in order |
|---|---|---|---|
enso-flash | low | 900,000 | GPT-6 Luna → Claude Haiku 5.5 → DeepSeek V4.1 Flash → GPT-6 Luna Pro |
enso-pro | medium | 1,000,000 | GPT-6.1 Sol, for prompts up to 272,000 tokens → Claude Sonnet 5.5 → Gemini 4 Argon |
enso-max | high | 1,000,000 | Claude Opus 5.5 → Claude Sonnet 5.5 → Claude Sonnet 5 → Gemini 4 Argon |
enso-ultra | max | 1,000,000 | Claude Sonnet 5.5 → Claude Opus 5.5 → Claude Sonnet 5 → Gemini 4 Argon |
Thinks is the reasoning depth a tier uses when the request names none; a request that names one is served at it, or at the nearest the model takes (Reasoning effort). Window is the longest prompt the tier's chain holds, in tokens.
A prompt over 272,000 tokens on enso-pro starts at Claude Sonnet 5.5. The
X-Hanzo-Served response header names the Enso id that answered: the tier you
sent, or the one enso-auto chose. If every rung fails, the fallback pool
answers.
Gemini 4 Argon also answers under its own id, google/gemini-4-argon, at 2.11
input, 10.55 output and 0.1055 cache read per million tokens.
Why these models
The chains follow a third-party ranking: the Artificial Analysis Coding Agent Index (v1.5), which runs each model in its own agent at the effort named. The scores were read from the benchlm.ai capture of 2026-10-15; Hanzo did not measure them.
| Model | Effort | Index |
|---|---|---|
| Claude Sonnet 5.5 | max | 68.4 |
| Claude Opus 5.5 | max | 66.0 |
| Gemini 4 Argon | high | 63.8 |
| GPT-6.1 Sol | xhigh | 62.9 |
| GPT-6.1 Sol | medium | 61.4 |
| GPT-6 Luna | max | 41.1 |
enso-ultra leads with the top score and keeps the next two behind it.
enso-max leads with Claude Opus 5.5, which sets its price. enso-pro leads
with GPT-6.1 Sol at medium effort, 2.4 points under Gemini 4 Argon at the same
price a token. enso-flash leads with GPT-6 Luna, for turns that do not need
the frontier; Luna Pro stands last, because it billed 3.2 times the prompt
tokens for the same request. Hanzo's own runs are published at
hanzo.ai/benchmarks.
Reasoning effort
Every Enso model takes a reasoning effort: reasoning_effort on
/v1/chat/completions, reasoning.effort on /v1/responses. On enso-auto
it picks the tier; on a named tier it sets only how hard that tier thinks.
| Effort | enso-auto serves | A named tier (enso-pro …) thinks |
|---|---|---|
omitted, or auto | the tier the router picks: it starts at low or medium and escalates only when the router or Kai judges the request needs more | at its own depth (Thinks, above) |
instant, or minimal, none | enso-flash, no reasoning | not at all: thinking off |
low | enso-flash, light reasoning | low |
medium | enso-pro | medium |
high | enso-max | high |
max, or xhigh | enso-ultra | max |
none means instant, so a client that wants the router sends no effort, or
auto. Fast mode is a separate switch. enso-auto is the default
for every caller, the Free plan included. Its answer carries a routing object
naming the tier it chose and why, the X-Routed-Model response header names
the same tier, and the call bills that tier's price.
Caching
Caching works through every tier. Put the long, stable part of a prompt first
and send it unchanged; from the second call on, the model behind the tier reads
it from cache, and those tokens bill at the tier's cache-read rate.
usage.prompt_tokens_details.cached_tokens counts them.
Measured through api.hanzo.ai on 2026-10-15, with the prefix marked
cache_control: a repeated prompt read 8,429 of 10,483 tokens from cache on
Gemini 4 Argon, and 14,810 of 14,828 on Claude Sonnet 5.5.
What a turn costs
One turn of a coding agent: a 100,000-token prompt, of which 92,000 tokens are read from cache, 6,000 are new and written to it for the next turn, and 2,000 are plain input; then 2,000 tokens of answer.
| Tokens | Class | enso-flash | enso-pro | enso-max | enso-ultra |
|---|---|---|---|---|---|
| 92,000 | cache read | $0.00304 | $0.01518 | $0.01978 | $0.02409 |
| 6,000 | cache write | $0.00248 | $0.02475 | $0.03225 | $0.03927 |
| 2,000 | input | $0.00066 | $0.00660 | $0.00860 | $0.01047 |
| 2,000 | output | $0.00330 | $0.03300 | $0.04300 | $0.05236 |
| the turn | $0.0095 | $0.0795 | $0.1036 | $0.1262 |
Without the cache, enso-pro bills all 100,000 prompt tokens as input, and the
same turn costs $0.363: 4.6 times as much.
Claude Code
hanzo --claude --cloud runs Claude Code on Hanzo and fills its model slots
with Enso, one tier per slot, each thinking at its own depth:
| Claude Code slot | Served as | Thinks |
|---|---|---|
| Haiku: background work and routine turns | enso-flash | low |
| Sonnet | enso-pro | medium |
| Opus | enso-max | high |
| Fable | enso-ultra | max |
The wrapper sets no session effort; Claude Code's /effort overrides the
depth for the session.
The session's main model is enso-auto unless you pass --model.
--model zen6 runs Zen 6, the open-weights model.
Claude Code has the rest.
The auto router
model: "auto" routes across the models your org can serve and bills the one
that answered. That model is in the X-Routed-Model response header and the
body's model field. zen-router is an alias for auto.
curl -si https://api.hanzo.ai/v1/chat/completions \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "auto", "messages": [{"role": "user", "content": "Summarize this changelog in one line."}]}'From the Java and C# clients; the
reply's model names the one that answered:
import ai.hanzo.Hanzo;
import ai.hanzo.api.AiApi;
import ai.hanzo.model.*;
import java.util.List;
PostChat200Response reply = new AiApi(Hanzo.client()).postChatCompletions(
new OpenaiChatCompletionRequest()
.model("auto")
.messages(List.of(new OpenaiChatCompletionMessage()
.role("user")
.content("Summarize this changelog in one line."))),
null, null);
System.out.println(reply.getModel());using Hanzo.AI;
using Hanzo.AI.Api;
using Hanzo.AI.Model;
var reply = new AiApi(Gateway.Configuration()).PostChatCompletions(new OpenaiChatCompletionRequest(
model: "auto",
messages: new() { new OpenaiChatCompletionMessage(role: "user", content: "Summarize this changelog in one line.") }));
Console.WriteLine(reply.Model);The rewrite happens before provider, pricing and billing are resolved, so the
request is priced, metered and reported as exactly the model that served it.
That model is in the X-Routed-Model response header and in the body's
model field; the two always match. zen-router is accepted as an alias for
auto.
An enso-* id is not rewritten: the answer keeps the id you sent in its
model field, and the X-Hanzo-Served response header names the Hanzo model
that answered it. X-Routed-Model is set when auto or enso-auto was resolved.
How it picks
- Classify. Media, length and keywords put the request in one task class:
code,reasoning,math,creative,vision,long_context,cheap_chatorgeneral. - Narrow. Only models your org can serve are eligible, then only the ones your org enabled, then only the ones under your cost ceiling.
- Choose, first answer wins: an override your org pinned for the task class; the learned policy, a bilinear utility over request features and per-model profiles that defers when it is unsure; an optional exploration share that samples a non-champion model; the rule table, an ordered list per task class whose first servable model wins.
The decision runs on a CPU: HIP-0510 measures 300 ns for the rule router and 12 µs for the learned one.
Bound it
| Header | Meaning |
|---|---|
X-Max-Cost | the most you will pay, in USD per 1,000 tokens |
X-Max-Latency-Ms | the slowest model you will accept, in milliseconds |
An org can set a default cost ceiling, per-task overrides, the enabled-model
list, and the strategy: enso (the learned policy leads; the default) or
heuristic (rules only). A header always wins when it is lower.
Smart routing covers where those switches live.
Teach it
Tell Enso how a routed answer went. The request_id is the response id
(chatcmpl-…):
curl https://api.hanzo.ai/v1/ai/feedback \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"request_id": "chatcmpl-…", "signal": "accept"}'signal | Reward |
|---|---|
up, accept | 1 |
regenerate | 0.25 |
down, switch, abandon, revert | 0 |
rating with rating 1, 2 or 3 | 0, 0.5, 1 |
dismiss | nothing recorded |
The ledger holds features and a reward, never prompt text, and only for your own org's requests. Each cycle fits a candidate and deploys it only if it beats the incumbent on held-out reward. Kai is being built into Enso for the decisions an agent loop makes beyond the model.
Also named Enso
| Name | What it is | Status |
|---|---|---|
| Enso Diffusion | a sparse mixture-of-experts diffusion transformer with rectified-flow training, forked from DiT-MoE: zenlm/enso | research code, no released weights |
| Enso Browser | a Firefox-based desktop browser | not released |
SDK Examples & Recipes
- Open Source Repository on GitHub (
hanzoai/enso): Canonical repository for Enso router examples, client bindings, and recipes. - Multi-Language Examples:
- Python Client (
examples/python/client_enso.py): Multi-tier routing across the Enso tiers with latency and cost control headers. - Go Client (
examples/go/main.go): Idiomatic Go router client with custom HTTP transport and latency caps. - Rust Client (
examples/rust/src/main.rs): Async client usingreqwestand serde JSON.
- Python Client (
- Modular Rust Recipes Crate (
enso-recipes): High-level primitives includingModelSuitabilityRecipeandConfidenceGate.
Source
The tiers are served by the enso service on the Hanzo engine. The router and
learned policy: hanzoai/engine. The
family: hanzoai/enso. Specification:
HIP-0510. The
learned policy and its measurements: the
Hanzo Router paper.