# TypeScript

URL: https://docs.hanzo.ai/docs/sdks/typescript

> Four npm packages, and which one to install — hanzoai for the whole /v1 surface, @hanzo/ai for inference and agents, @hanzo/sdk per service, @hanzo/iam for identity.

TypeScript has more than one Hanzo package because it has more than one job to
do, and the packages are not versions of each other. Pick by what you are
building; installing two is normal.

| Package      | Install            | What it gives you                                                                                                     |
| ------------ | ------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `hanzoai`    | `npm i hanzoai`    | The generated client for **every** `/v1` capability. One `*Api` class per product, typed request and response models. |
| `@hanzo/ai`  | `npm i @hanzo/ai`  | The AI client — chat, messages, models, agents, sandboxes, tools, sessions. Hand-written, browser-safe.               |
| `@hanzo/sdk` | `npm i @hanzo/sdk` | One client per service — IAM, KMS, Commerce, Billing, MPC, PaaS, Team — with subpath imports.                         |
| `@hanzo/iam` | `npm i @hanzo/iam` | [Identity](https://docs.hanzo.ai/docs/sdks/iam) alone: OIDC, JWT validation, browser PKCE, React bindings.            |

There is also `hanzo` on npm, which is [the CLI](https://docs.hanzo.ai/docs/cli). Its library export
re-exports `hanzoai`, so `npm i -g hanzo` gives you the command and `npm i
hanzoai` gives you the client; you do not need both for the client.

Set the key once:

```bash
export HANZO_API_KEY="sk-..."   # from platform.hanzo.ai
```

## `@hanzo/ai` — inference and agents

The one to reach for when the job is a model call. It runs on Node, Deno, Bun
and the browser, and it names the key field after the key type, so a mistake is
a type error rather than a leak:

```typescript
import { Hanzo } from '@hanzo/ai'

// On a server. An `sk-` resolves to you, so it never goes in a bundle.
const hanzo = new Hanzo({ secretKey: process.env.HANZO_API_KEY })

const answer = await hanzo.chat.completions.create({
  model: 'zen6',
  messages: [{ role: 'user', content: 'Explain quantum computing' }],
})

console.log(answer.choices[0].message.content)
```

In a browser, pass the publishable key instead — it names the tenant and cannot
read, which is what makes it safe to ship:

```typescript
const hanzo = new Hanzo({ publishableKey: 'pk-...' })
```

[Authentication](https://docs.hanzo.ai/docs/api-keys) is the whole rule for which key goes where.

### Streaming

`stream: true` changes the return type to an async generator of OpenAI-shaped
chunks:

```typescript
const stream = await hanzo.chat.completions.create({
  model: 'zen6',
  messages: [{ role: 'user', content: 'Write a haiku about AI' }],
  stream: true,
})

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? '')
}
```

### The rest of it

The same client carries the surfaces an agent needs — `hanzo.models.list()`,
`hanzo.agents`, `hanzo.sandboxes`, `hanzo.tools`, `hanzo.sessions`,
`hanzo.threads` — plus `hanzo.messages.create()` for the Anthropic-shaped
request, and `hanzo.search()` for a source-cited answer.

## `hanzoai` — the whole `/v1` surface

Generated from the API's own document, so every capability is present whether or
not anyone wrote a page about it. The shape is one `Configuration` and one class
per product:

```typescript
import { AiApi, BillingApi, Configuration } from 'hanzoai'

const config = new Configuration({ accessToken: process.env.HANZO_API_KEY })

const { data: models } = await new AiApi(config).getModels()
const balance = await new BillingApi(config).getBillingBalance()
```

Method names come from the operation, so the [reference](https://docs.hanzo.ai/docs/openapi) is the
index: each operation page prints the call for this client next to the raw HTTP.

## `@hanzo/sdk` — one client per service

For a backend that talks to a few named services rather than to the API at
large. Subpath imports keep a bundle to what it uses:

```typescript
import { IAMClient } from '@hanzo/sdk/iam'
import { KMSClient } from '@hanzo/sdk/kms'
```

> **Any OpenAI-shaped client also works**
>
> `https://api.hanzo.ai/v1` speaks the OpenAI and Anthropic wire formats, so the
> `openai` package with `baseURL` pointed there and a Hanzo key sends the same
> body it sends today. The packages above add the rest of `/v1` on top of that —
> see [Migrate from OpenAI](https://docs.hanzo.ai/docs/guides/migrate/openai).

## Resources

- [`hanzoai`](https://www.npmjs.com/package/hanzoai) ·
  [`@hanzo/ai`](https://www.npmjs.com/package/@hanzo/ai) ·
  [`@hanzo/sdk`](https://www.npmjs.com/package/@hanzo/sdk) ·
  [`@hanzo/iam`](https://www.npmjs.com/package/@hanzo/iam)
- Source — [hanzo-js](https://github.com/hanzo-js)
- [Every `/v1` operation →](https://docs.hanzo.ai/docs/openapi)
