# SDK recipes

> Calling the gateway from every client worth naming, including the agent runtimes.

Every snippet below uses `anthropic/claude-opus-5`. Swap in any id from the
[model list](/docs/resources/ai-gateway/models) — the
[sample browser](/docs/resources/ai-gateway/models#try-one) does it for you.

Two variables are already in your `.env`:

```dotenv title=".env"
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
OPENROUTER_API_KEY=sk-or-v1-9c4e17b2…
```

## Which client reaches which model

The gateway exposes three surfaces, and that decides what each client can call.

| Surface | Base URL | Reaches |
| --- | --- | --- |
| OpenAI-compatible | `https://openrouter.ai/api/v1` | Every model |
| Anthropic Messages | `https://openrouter.ai/api` | Every model |
| Native | via `@openrouter/ai-sdk-provider` | Every model, plus routing controls |

All three reach the whole catalogue, so **the OpenAI SDK calls a Claude model and
the Anthropic SDK calls a Gemini one**. The gateway maps the model id and
forwards to whichever provider actually serves it; the protocol you speak to it
in is your choice, not the model's.

The exception is a provider SDK whose protocol the gateway does not speak at all
— Google's, Cohere's, Amazon's. Those reach nothing here, whatever key they hold.
Use one of the three surfaces above instead.

What each recipe below *does* care about is which variables it reads.
`OPENROUTER_*` is written by every one of these commands; the `OPENAI_*` and
`ANTHROPIC_*` pairs are written when you ask for that provider by name.

<Callout title="Model ids need the author prefix">
`gpt-5.2` is not a model id here; `openai/gpt-5.2` is. This is the one edit a
project usually has to make after switching, and it is the same edit whichever
client you use.
</Callout>

## The recipes

_The recipes render here. They are generated from one catalog, so the code is the same in every client._

## Streaming and tool use

Both survive the round trip on every surface. The Anthropic Messages surface
passes extended thinking blocks and native tool use through unchanged, which is
what lets an agent runtime like Claude Code work against it rather than merely
connect to it.

## Provider routing

The native provider accepts OpenRouter's routing controls — pinning a provider,
ordering fallbacks, requiring a data policy:

```ts title="routing.ts"
const result = streamText({
  model: openrouter("anthropic/claude-opus-5"),
  prompt: "Draft a status report from these logs.",
  providerOptions: {
    openrouter: {
      provider: { order: ["anthropic", "google-vertex"], allow_fallbacks: true },
    },
  },
});
```

The same object works over the OpenAI-compatible surface as an extra body field,
which most SDKs expose as `extraBody` or `extra_body`.

## Next

- [Models](/docs/resources/ai-gateway/models) — the full list, with prices
- [Providers and keys](/docs/resources/ai-gateway/providers) — what the CLI writes for each

---

More for agents: [Docs index](https://extraorbital.dev/sitemap.md) · [llms.txt](https://extraorbital.dev/llms.txt) · [agents.md](https://extraorbital.dev/agents.md)
