The official Anthropic SDK supports Node.js and TypeScript out of the box. This guide covers everything from installation to streaming, tool use, and production best practices.
Installation
npm install @anthropic-ai/sdk
export ANTHROPIC_API_KEY="your-key-here"
First Message
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const response = await client.messages.create({ model: "claude-sonnet-4-6", max_tokens: 1024, messages: [{ role: "user", content: "Explain async/await in JavaScript in 3 sentences." }], });
console.log(response.content[0].text);
CommonJS:
const Anthropic = require("@anthropic-ai/sdk"); const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
Streaming
For long responses, stream tokens as they arrive:
const stream = client.messages.stream({
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages: [{ role: "user", content: "Write a short story about a developer." }],
});
for await (const event of stream) { if (event.type === "content_block_delta" && event.delta.type === "text_delta") { process.stdout.write(event.delta.text); } }
const finalMessage = await stream.finalMessage(); console.log("\nTotal tokens:", finalMessage.usage);
Conversation History
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic(); const history: Anthropic.MessageParam[] = [];
async function chat(userMessage: string): Promise { history.push({ role: "user", content: userMessage });
const response = await client.messages.create({ model: "claude-sonnet-4-6", max_tokens: 1024, system: "You are a helpful coding assistant.", messages: history, });
const reply = response.content[0].text; history.push({ role: "assistant", content: reply }); return reply; }
console.log(await chat("What is a closure?")); console.log(await chat("Show me an example."));
Tool Use (Function Calling)
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const tools: Anthropic.Tool[] = [ { name: "get_weather", description: "Get the current weather for a city", input_schema: { type: "object", properties: { city: { type: "string", description: "City name" }, }, required: ["city"], }, }, ];
async function getWeather(city: string): Promise { const res = await fetch(https://wttr.in/${city}?format=3); return res.text(); }
async function runWithTools(question: string): Promise { const messages: Anthropic.MessageParam[] = [{ role: "user", content: question }];
while (true) { const response = await client.messages.create({ model: "claude-sonnet-4-6", max_tokens: 1024, tools, messages, });
if (response.stop_reason === "end_turn") { const textBlock = response.content.find((b) => b.type === "text"); return textBlock?.text ?? ""; }
if (response.stop_reason === "tool_use") { messages.push({ role: "assistant", content: response.content });
const toolResults: Anthropic.ToolResultBlockParam[] = []; for (const block of response.content) { if (block.type === "tool_use") { const input = block.input as { city: string }; const result = await getWeather(input.city); toolResults.push({ type: "tool_result", tool_use_id: block.id, content: result }); } } messages.push({ role: "user", content: toolResults }); } } }
console.log(await runWithTools("What's the weather in Kyiv?"));
Prompt Caching
Cache long system prompts to cut costs up to 90%:
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
system: [
{
type: "text",
text: "You are an expert TypeScript developer with deep knowledge of Node.js...",
cache_control: { type: "ephemeral" },
},
],
messages: [{ role: "user", content: "How do I handle backpressure in streams?" }],
});
console.log("Cache read tokens:", response.usage.cache_read_input_tokens);
Error Handling
import { APIError, RateLimitError, APIConnectionError } from "@anthropic-ai/sdk";
async function safeCreate(content: string): Promise { try { const response = await client.messages.create({ model: "claude-sonnet-4-6", max_tokens: 512, messages: [{ role: "user", content }], }); return response.content[0].text; } catch (err) { if (err instanceof RateLimitError) { console.error("Rate limited — back off and retry"); } else if (err instanceof APIConnectionError) { console.error("Network error:", err.message); } else if (err instanceof APIError) { console.error(API error ${err.status}:, err.message); } return null; } }
Express.js Integration
import express from "express";
import Anthropic from "@anthropic-ai/sdk";
const app = express(); app.use(express.json()); const client = new Anthropic();
app.post("/chat", async (req, res) => { const { message } = req.body; if (!message) return res.status(400).json({ error: "message required" });
const response = await client.messages.create({ model: "claude-sonnet-4-6", max_tokens: 1024, messages: [{ role: "user", content: message }], });
res.json({ reply: response.content[0].text }); });
app.listen(3000, () => console.log("Server running on :3000"));
Originally published at kalyna.pro