Test DemoDocs
GuidesModelsAPI referenceApps
SDKs and frameworks

Anthropic SDK

Use the official Anthropic SDK for Python and TypeScript with this API, through the Messages format.

The official Anthropic SDK works with this API through POST /v1/messages. Set the base URL to https://test-demo.pinerouter.ai, without /v1: the SDK adds it. Any text model on Models answers in Messages format. Claude models themselves are not on the list today.

Install

pip install anthropic
uv add anthropic
npm install @anthropic-ai/sdk
pnpm add @anthropic-ai/sdk
bun add @anthropic-ai/sdk

Configure API keys

.env
API_KEY=sk-...

Load it into the environment before you run the code (for example with python-dotenv, or node --env-file=.env). Keep the key out of your code.

Run

Text

import os
import anthropic

client = anthropic.Anthropic(base_url="https://test-demo.pinerouter.ai", api_key=os.environ["API_KEY"])

msg = client.messages.create(
    model="gpt-6-luna",
    max_tokens=500,
    messages=[{"role": "user", "content": "Name three rivers in Europe."}],
)
print(msg.content[0].text)
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({ baseURL: "https://test-demo.pinerouter.ai", apiKey: process.env.API_KEY });

const msg = await client.messages.create({
  model: "gpt-6-luna",
  max_tokens: 500,
  messages: [{ role: "user", content: "Name three rivers in Europe." }],
});
console.log(msg.content[0].type === "text" ? msg.content[0].text : msg.content[0]);

Stream

with client.messages.stream(
    model="gpt-6-luna",
    max_tokens=300,
    messages=[{"role": "user", "content": "Write a haiku about rivers."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
const stream = client.messages
  .stream({
    model: "gpt-6-luna",
    max_tokens: 300,
    messages: [{ role: "user", content: "Write a haiku about rivers." }],
  })
  .on("text", (text) => process.stdout.write(text));

await stream.finalMessage();

The events are Anthropic's: message_start, content_block_delta, message_delta with the final usage, and message_stop. More in Streaming.

Tool calling

Tools use Anthropic's format (input_schema). When the model wants a tool, the answer has a tool_use block and stop_reason is tool_use.

tools = [{
    "name": "get_weather",
    "description": "Current weather for a city",
    "input_schema": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]},
}]
messages = [{"role": "user", "content": "What is the weather in Paris?"}]

msg = client.messages.create(model="gpt-6-luna", max_tokens=500, tools=tools, messages=messages)
if msg.stop_reason == "tool_use":
    messages.append({"role": "assistant", "content": msg.content})
    results = [
        {"type": "tool_result", "tool_use_id": b.id, "content": f"Sunny, 21 C in {b.input['city']}"}
        for b in msg.content if b.type == "tool_use"
    ]
    messages.append({"role": "user", "content": results})
    msg = client.messages.create(model="gpt-6-luna", max_tokens=500, tools=tools, messages=messages)
print("".join(b.text for b in msg.content if b.type == "text"))
const tools: Anthropic.Tool[] = [{
  name: "get_weather",
  description: "Current weather for a city",
  input_schema: { type: "object", properties: { city: { type: "string" } }, required: ["city"] },
}];
const messages: Anthropic.MessageParam[] = [{ role: "user", content: "What is the weather in Paris?" }];

let msg = await client.messages.create({ model: "gpt-6-luna", max_tokens: 500, tools, messages });
if (msg.stop_reason === "tool_use") {
  messages.push({ role: "assistant", content: msg.content });
  const results: Anthropic.ToolResultBlockParam[] = [];
  for (const b of msg.content) {
    if (b.type !== "tool_use") continue;
    const { city } = b.input as { city: string };
    results.push({ type: "tool_result", tool_use_id: b.id, content: `Sunny, 21 C in ${city}` });
  }
  messages.push({ role: "user", content: results });
  msg = await client.messages.create({ model: "gpt-6-luna", max_tokens: 500, tools, messages });
}
console.log(msg.content);

Specifics

  • max_tokens is required in Messages format.
  • The SDK also reads ANTHROPIC_BASE_URL from the environment, so you can set ANTHROPIC_BASE_URL=https://test-demo.pinerouter.ai instead of passing it in code.
  • There is no images endpoint in Anthropic's format. For images, video and other media use Jobs with the HTTP helper, or the OpenAI SDK; the same key works.
  • Tool calling depends on the model. Test with the model you plan to use.

Next