Anthropic SDK

The official Anthropic SDKs work against Nimbus with one env var changed. Same /v1/messages wire format, same streaming events, same tool-use shape.

Nimbus exposes an Anthropic-compatible endpoint at /v1/messages. The official @anthropic-ai/sdk (Node) and anthropic (Python) packages talk to it directly — just override the base URL. Any library that wraps the Anthropic SDK (LangChain ChatAnthropic, LlamaIndex, DSPy) works for free.

Prerequisites

  • A Nimbus API key (starts with sk-nim-).
  • Node.js 18+ or Python 3.9+ for the official SDKs.
  • Fully-qualified model IDs — Anthropic's SDK does not prefix them for you. Use anthropic/claude-opus-4.7, not claude-opus-4.7.

Install

Node:

bash
npm i @anthropic-ai/sdk

Python:

bash
pip install anthropic

Configure

Note the base URL has no /v1 suffix — the Anthropic SDK appends /v1/messages internally. Pass the Nimbus key as authToken (Node) or auth_token (Python) so the SDK sends it as Authorization: Bearer instead of the Anthropic-specific x-api-key header.

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

const client = new Anthropic({
  baseURL: "https://llm.nimbusapi.net",
  authToken: process.env.NIMBUS_API_KEY,
});
python
import os
from anthropic import Anthropic

client = Anthropic(
    base_url="https://llm.nimbusapi.net",
    auth_token=os.environ["NIMBUS_API_KEY"],
)

First call

A full working example — one system prompt, one user turn, one tool. The response shape is byte-for-byte the Anthropic Message object.

typescript
const msg = await client.messages.create({
  model: "anthropic/claude-opus-4.7",
  max_tokens: 1024,
  system: "You are a build assistant. Prefer tools over guessing.",
  tools: [
    {
      name: "get_price",
      description: "Look up the current spot price for a ticker.",
      input_schema: {
        type: "object",
        properties: { ticker: { type: "string" } },
        required: ["ticker"],
      },
    },
  ],
  messages: [
    { role: "user", content: "What is the current price of BTC in USD?" },
  ],
});

console.log(msg.content);
python
msg = client.messages.create(
    model="anthropic/claude-opus-4.7",
    max_tokens=1024,
    system="You are a build assistant. Prefer tools over guessing.",
    tools=[
        {
            "name": "get_price",
            "description": "Look up the current spot price for a ticker.",
            "input_schema": {
                "type": "object",
                "properties": {"ticker": {"type": "string"}},
                "required": ["ticker"],
            },
        }
    ],
    messages=[{"role": "user", "content": "What is BTC in USD?"}],
)

print(msg.content)

Streaming

Nimbus streams the exact Anthropic SSE event stream — message_start, content_block_delta, message_stop — so the SDK's stream() helper works unchanged.

typescript
const stream = client.messages.stream({
  model: "anthropic/claude-opus-4.7",
  max_tokens: 512,
  messages: [{ role: "user", content: "Write a haiku about Ohio." }],
});

for await (const event of stream) {
  if (event.type === "content_block_delta") {
    process.stdout.write(event.delta.text ?? "");
  }
}

Troubleshooting

  • 401 Unauthorized: you passed the key as apiKey instead of authToken. The Anthropic SDK sends apiKey as x-api-key; Nimbus expects Authorization: Bearer.
  • 404 Not Found on /v1/v1/messages: you added /v1 to the base URL. The Anthropic SDK appends it — set base URL to https://llm.nimbusapi.net with no suffix.
  • 400 "model not found": use the fully-qualified name (anthropic/claude-opus-4.7). See Models.
  • Missing max_tokens: the Anthropic wire format requires max_tokens on every call. Nimbus does not silently default it.
  • Streaming stalls: a proxy is buffering SSE. Confirm the request hits llm.nimbusapi.net directly, and that you're iterating the stream — not awaiting the whole thing.