Skip to content
extraorbital
Documentation ExtraOrbital
Browse documentation

AI & speech

SDK recipes

Connect a supported SDK to the AI Gateway.

Examples use anthropic/claude-opus-5. Choose an available model from the catalog or sample browser.

Two variables are already in your .env:

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

Which client reaches which model

Supported interfaces:

SurfaceBase URLReaches
OpenAI-compatiblehttps://openrouter.ai/api/v1Every model
Anthropic Messageshttps://openrouter.ai/apiEvery model
Nativevia @openrouter/ai-sdk-providerEvery model, plus routing controls

Model access is independent of client choice. For example, the OpenAI SDK can request a Claude model.

Native Google, Cohere, and Amazon clients use unsupported protocols. Use one of the interfaces above.

Every gateway resource writes OPENROUTER_*. Asking for openai or anthropic also writes that client’s compatibility variables.

The recipes

OpenAI SDK (Node)

npm i openai

import OpenAI from "openai";

// Both variables are in .env already — the SDK reads them itself.
const client = new OpenAI();

const response = await client.chat.completions.create({
  model: "anthropic/claude-opus-5",
  messages: [{ role: "user", content: "Draft a status report from these logs." }],
});

console.log(response.choices[0]?.message.content);

OpenAI SDK (Python)

pip install openai

from openai import OpenAI

# Reads OPENAI_API_KEY and OPENAI_BASE_URL from the environment.
client = OpenAI()

response = client.chat.completions.create(
    model="anthropic/claude-opus-5",
    messages=[{"role": "user", "content": "Draft a status report from these logs."}],
)

print(response.choices[0].message.content)

Anthropic SDK (Node)

npm i @anthropic-ai/sdk

import Anthropic from "@anthropic-ai/sdk";

// ANTHROPIC_BASE_URL points at the gateway's Anthropic-compatible surface,
// which is https://openrouter.ai/api — the SDK appends /v1/messages itself.
const anthropic = new Anthropic();

const message = await anthropic.messages.create({
  model: "anthropic/claude-opus-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Draft a status report from these logs." }],
});

console.log(message.content);

Anthropic SDK (Python)

pip install anthropic

import anthropic

client = anthropic.Anthropic()

message = client.messages.create(
    model="anthropic/claude-opus-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Draft a status report from these logs."}],
)

print(message.content)

Vercel AI SDK v7

npm i ai @openrouter/ai-sdk-provider

import { streamText } from "ai";
import { createOpenRouter } from "@openrouter/ai-sdk-provider";

const openrouter = createOpenRouter({
  apiKey: process.env.OPENROUTER_API_KEY,
});

const result = streamText({
  model: openrouter("anthropic/claude-opus-5"),
  prompt: "Draft a status report from these logs.",
});

for await (const chunk of result.textStream) process.stdout.write(chunk);

The dedicated provider reaches every model on the gateway, including ones no OpenAI-shaped client can call.

fetch (no SDK)

const response = await fetch(
  `${process.env.OPENROUTER_BASE_URL}/chat/completions`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "anthropic/claude-opus-5",
      messages: [{ role: "user", content: "Draft a status report from these logs." }],
    }),
  },
);

const body = await response.json();
console.log(body.choices[0].message.content);

curl

curl "$OPENROUTER_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-opus-5",
    "messages": [{ "role": "user", "content": "Draft a status report from these logs." }]
  }'

LangChain

npm i @langchain/openai

import { ChatOpenAI } from "@langchain/openai";

const model = new ChatOpenAI({
  model: "anthropic/claude-opus-5",
  apiKey: process.env.OPENROUTER_API_KEY,
  configuration: { baseURL: "https://openrouter.ai/api/v1" },
});

const response = await model.invoke("Draft a status report from these logs.");
console.log(response.content);

Claude Code

export OPENROUTER_API_KEY="sk-or-v1-…"        # from your .env
export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
export ANTHROPIC_AUTH_TOKEN="$OPENROUTER_API_KEY"
export ANTHROPIC_API_KEY=""                    # explicitly blank
export CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1

export ANTHROPIC_DEFAULT_SONNET_MODEL="anthropic/claude-opus-5"

claude

Claude Code does not read .env — the fenced block will not reach it. Export these in your shell, or put them under `env` in .claude/settings.local.json. Run /logout first if you were signed in with Anthropic credentials.

Hermes agent

# ~/.hermes/config.yaml
model:
  provider: openrouter
  default: anthropic/claude-opus-5

# ~/.hermes/.env
#   OPENROUTER_API_KEY=sk-or-v1-…

Hermes knows OpenRouter's endpoint from the provider name, so it needs no base URL. `hermes model` does this interactively.

Streaming and tool use

Streaming and tool use are supported. The Anthropic Messages interface also forwards extended thinking blocks.

Provider routing

Set routing options to select providers, order fallbacks, or require a data policy:

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 },
    },
  },
});

For the OpenAI-compatible interface, pass the object as an extra request-body field (extraBody or extra_body, depending on the SDK).

Next