Hanzo AI

Enso

Enso routes: a learned router picks the model for every request, bills the model that served, and learns from your feedback. The enso-* family serves that choice under one name.

After this page you know how Enso picks a model, how to bound and steer the pick, how to teach it, and which Enso id to send.

Enso is the router. Every request it sees is classified, priced against what your org can serve, and sent to the model that should answer it — a Zen model, another provider's, or one you host. The decision runs on a CPU: HIP-0510 measures 300 ns for the rule router and 12 µs for the learned one, before a model call that takes seconds.

Two ways in

SendWhat happensPick it when
model: "auto"Enso routes across the models your org can serve and bills the one that answeredyou want the choice made per request, over your own pool
an enso-* idone managed name; Hanzo picks the serving path behind ityou want one id, one rate, and no pool to manage
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."}]}'

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.

How it picks

  1. Classify. Media, length and keywords put the request in one task class: code, reasoning, math, creative, vision, long_context, cheap_chat or general.
  2. Narrow. Only models your org can actually serve are eligible — a route exists and your tier or grant admits it — then only the ones your org enabled, then only the ones under your cost ceiling. A narrower scope can only narrow; it never reaches a model another scope could not.
  3. Choose, in this order, first answer wins:
    • an override your org pinned for that task class;
    • the learned policy: a bilinear utility xᵀW p over request features and per-model profiles, fit by ridge regression and adapted per user with LinUCB; it defers when it is unsure;
    • an optional exploration share that samples a non-champion model, so every model in the pool keeps earning feedback;
    • the rule table: an ordered list of models per task class, Zen first; the first servable one wins.

With routing on for your org, auto always resolves: when the learned policy is unreachable or unsure, the rule table answers.

Bound it

Two optional headers set a ceiling per request without touching the body:

HeaderMeaning
X-Max-Costthe most you will pay, in USD per 1,000 tokens
X-Max-Latency-Msthe slowest model you will accept, in milliseconds

An org can also set, once: a cost ceiling that fills an unset X-Max-Cost, per-task overrides, the enabled-model list, and the strategy — enso (the learned policy leads; the default) or heuristic (rules only, for routing you can audit line by line). An explicit 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 you already hold (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"}'
signalReward
up, accept1
regenerate0.25
down, switch, abandon, revert0
rating with rating 1, 2 or 30, 0.5, 1
dismissnothing recorded

The ledger holds features and a reward, never prompt text. A reward can land only on your own org's requests, and an org that turns training contribution off records none. Each cycle fits a candidate, deploys it only if it beats the incumbent on held-out reward, and otherwise keeps the incumbent: a regression cannot ship. Your org's own policy trains on your org's rewards alone.

The Enso family

The managed ids, from the gateway:

curl -s https://api.hanzo.ai/v1/models \
  | jq -r '.data[] | select(.id | startswith("enso")) | "\(.id)\t\(.context_window)\t\(.pricing.input)/\(.pricing.output)"'
IdReasoningNote
enso-automediumthe default: Hanzo Dev sends it when you name no model
enso-flashofffast, for volume
enso-ultramaximumthe most compute per request
enso-promediumserved on the same path as enso
ensomediumthe earlier name of enso-auto, kept while clients move
enso-free—the no-charge tier

Reasoning is the serving catalogue's setting today. Rates and windows are the command's, not this page's: the gateway is the source of truth, and Pricing is generated from it.

Kai inside Enso

Routing is one bounded decision; an agent loop makes many more — how much context, which tool, how much reasoning, whether the step made progress, whether the task is done, whether a command may run. Kai is being built into Enso as the in-process controller for those, one Decision Program each, starting in shadow. Status: in progress.

Also named Enso

NameWhat it isStatus
Enso Diffusiona sparse mixture-of-experts diffusion transformer with rectified-flow training, forked from DiT-MoE: zenlm/ensoresearch code, no released weights
Enso Browsera Firefox-based desktop browsernot released

Source

The router and learned policy: hanzoai/engine (enso, hanzo-router). The family: hanzoai/enso.

Specification: HIP-0510.

Measurements and economics: the Enso paper.

How is this guide?

Last updated on