Meet enso
Hanzo's own model family — enso, enso-flash, and enso-ultra. What each one is for, and how to pick.
Meet enso
After this page you can pick the right enso model for a job, switch between them with a one-string change, and work out what a request will cost before you send it.
enso is Hanzo's own model family. There are three of them. They share one
endpoint, one key, and one request shape — the only thing that changes between
them is the model string.
See them for yourself
The model catalog is what the gateway answers from, and reading it needs no key — you can run this line right now, before you have one:
curl -s https://api.hanzo.ai/v1/models \
| jq '.data[] | select(.id | startswith("enso"))'Each entry carries the id you pass as model, the owned_by that trained it,
a premium flag, pricing.input / pricing.output, and — for the enso tiers —
context_window. The gateway is the source of truth for all of it, so if this
page and that command ever disagree, believe the command. Current rates are on
Pricing, which is generated from the gateway rather than typed
by hand.
Which one
Start with enso-flash.
It is the cheapest tier, and most work never needs more than it. Reach for a bigger model when flash actually disappoints you, not before.
| Model | Context | In / Out (per 1M tokens) | Reach for it when |
|---|---|---|---|
enso-flash | 262,144 | 4 | Default. High volume, everyday work, anything you send a lot of. |
enso | 1,000,000 | 20 | The answer's quality matters more than its cost — hard reasoning, long documents, code that has to be right. |
enso-ultra | 1,000,000 | 25 | Being right matters more than being cheap. |
Those figures are the gateway's own, read from /v1/models. Across the range
that is 2.5x on input and about 6x on output — a narrower spread than the tier
names suggest, so trading up costs less than it sounds like it should. On the
mixed request priced at the bottom of this page, the three come to 0.018 and $0.0225: 1x, 3x and 3.75x, not the order of magnitude "ultra"
implies.
enso-flash is also the one tier that does not carry the million-token
window. If your input is large, that — not price — is the reason to move up.
Note that the columns above are about cost, not speed. Price and latency are independent here, and not in the direction the names suggest — measure before you assume, using the next section.
What makes enso-ultra different
enso is a model. enso-ultra is a strategy. Instead of answering directly,
it probes with a model sized to the task, escalates to a panel of models only
when the task turns out to be hard, then verifies the candidate answers and
selects the best one.
You pay for that in money rather than in context: ultra carries the same
million-token window enso does, so moving up from enso costs you nothing in
input size. The tier that cannot take your whole codebase in one prompt is
enso-flash, at 262,144 tokens. The panel is billed by the token like anything
else, which puts ultra a quarter above enso per million — 25 against
20, not a different order of cost.
Measure them yourself
Do not take anyone's word for which tier is fast — including this page's. Send one prompt to all three and time it. This is the whole experiment:
for m in enso enso-flash enso-ultra; do
printf '%-11s ' "$m"
curl -s -o /dev/null -w '%{http_code} %{time_total}s\n' \
https://api.hanzo.ai/v1/chat/completions \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d "{\"model\":\"$m\",\"messages\":[{\"role\":\"user\",\"content\":\"In two sentences, explain what an API key is to someone who has never used one.\"}]}"
done-o /dev/null throws the answer away and -w prints only the status code and
the wall-clock time, so you are timing the request and nothing else. One run:
enso 200 18.481812s
enso-flash 200 9.737156s
enso-ultra 200 4.755649sRun it a few times and the spread matters more than any single number. Over five rounds of that same prompt:
| Model | Fastest | Median | Slowest |
|---|---|---|---|
enso-ultra | 4.49s | 4.85s | 5.21s |
enso-flash | 8.21s | 14.91s | 33.13s |
enso | 19.15s | 20.26s | 20.69s |
Two things there are worth internalising, because neither is what the names
imply. enso-ultra was the fastest of the three on this prompt, not the
slowest — consistent with its design: it sizes a model to the task, and an easy
question never reaches the panel. And enso-flash was the least consistent —
its slowest round was four times its fastest, so a single timing tells you very
little about the next one.
Take that as a method, not as a league table. The prompt above is an easy one,
and these numbers describe that prompt in that moment — a harder question can
reorder them, because difficulty is what decides how much work enso-ultra does.
Time the tiers on your prompt, on the kind of question you actually plan to
ask, and re-time them when that changes.
What an answer looks like
Same prompt, sent to enso-ultra, printed exactly as it came back:
An API key is a unique string of characters that acts like a password, allowing a program to access a specific service or application programming interface (API). It identifies the user or application to the service, ensuring that only authorized users can make requests and helping track usage for billing or rate-limiting purposes.
That request billed 275 input tokens and 70 output tokens — the usage object
in the response says so, and at ultra's 25 per million that is about
$0.003. The same traffic through enso-flash would cost under a tenth of a
cent. Read usage rather than estimating: it is the number you are actually
charged for.
Switching between them
One string. Everything else about the request is identical.
curl https://api.hanzo.ai/v1/chat/completions \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "enso-flash",
"messages": [{ "role": "user", "content": "Name three uses for a paperclip." }]
}'import os
from hanzoai import Hanzo
client = Hanzo(api_key=os.environ["HANZO_API_KEY"])
answer = client.chat.completions.create(
model="enso-flash", # -> "enso" or "enso-ultra"
messages=[{"role": "user", "content": "Name three uses for a paperclip."}],
)
print(answer.choices[0].message.content)import Hanzo from '@hanzo/ai';
const client = new Hanzo({ apiKey: process.env.HANZO_API_KEY });
const answer = await client.chat.completions.create({
model: 'enso-flash', // -> 'enso' or 'enso-ultra'
messages: [{ role: 'user', content: 'Name three uses for a paperclip.' }],
});
console.log(answer.choices[0].message.content);That is the whole migration path between tiers. It is also why you should start cheap: moving up costs you one word of a diff, so there is no reason to pay for a bigger model until a smaller one has actually failed you. Every model in our catalog answers on that one path.
If you already have an HTTP client
/v1/chat/completions takes and returns the same JSON shapes as the
widely-implemented chat-completions format — an interchange format we do not own
and had no reason to re-invent. A client written against it works here once its
base URL points at https://api.hanzo.ai/v1 and it sends a Hanzo key. The ids
do not travel, though: enso is ours and resolves only here.
What a request costs
Prices are per million tokens, so divide. A 2,000-token prompt with a 500-token answer:
| Model | Input | Output | Total |
|---|---|---|---|
enso-flash | 2,000 x 0.004 | 500 x 0.002 | $0.006 |
enso | 2,000 x 0.008 | 500 x 0.010 | $0.018 |
enso-ultra | 2,000 x 0.010 | 500 x 0.0125 | $0.0225 |
A token is roughly three quarters of a word, so "2,000 tokens" is about three
pages. The response you get back reports exactly what you were charged for in
its usage field — trust that over any estimate, including this one.
Next
- All models — the full live catalog. enso is our own family; the gateway serves many more on the same key.
- API keys — what a key is, and where yours comes from.
- Build a game — enso doing something you can play, in three different ways.
How is this guide?