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 anthropicuv add anthropicnpm install @anthropic-ai/sdkpnpm add @anthropic-ai/sdkbun add @anthropic-ai/sdkConfigure API keys
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_tokensis required in Messages format.- The SDK also reads
ANTHROPIC_BASE_URLfrom the environment, so you can setANTHROPIC_BASE_URL=https://test-demo.pinerouter.aiinstead 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
- Claude messages: every field
- Streaming: events and errors mid-stream
- Claude Code: Anthropic's coding agent on this API