The Claude TypeScript and JavaScript SDKs are designed to make it easy to integrate Claude’s powerful language model into your applications. They handle the complexities of API communication, allowing you to focus on building innovative features.
Here’s a look at how you might use the SDK to send a message to Claude and get a response:
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY, // Ensure your API key is set as an environment variable
});
async function sendMessageToClaude() {
try {
const message = await anthropic.messages.create({
model: "claude-3-opus-20240229", // Or another Claude model like "claude-3-sonnet-20240229" or "claude-3-haiku-20240307"
max_tokens: 1000,
messages: [
{
role: "user",
content: "Hello, Claude! Can you tell me a fun fact about the ocean?",
},
],
});
console.log("Claude's response:", message.content[0].text);
} catch (error) {
console.error("Error sending message to Claude:", error);
}
}
sendMessageToClaude();
This code snippet demonstrates a basic interaction. You initialize the SDK with your API key, then call the messages.create method. You specify the model you want to use, the maximum number of tokens for the response, and an array of messages representing the conversation history. The role can be user or assistant, and content is the text of the message. The response object contains Claude’s reply, which you can access through message.content[0].text.
The SDK abstracts away the HTTP requests, request signing, and JSON serialization/deserialization. It also provides type safety for TypeScript users, meaning you get autocompletion and compile-time checks for API parameters and response structures. This significantly reduces the boilerplate code you’d otherwise need to write.
When you’re building more complex conversational agents, you’ll want to manage the conversation history. The SDK makes this straightforward by allowing you to pass an array of previous user and assistant messages to the messages.create method.
Consider this example of a multi-turn conversation:
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
async function chatWithClaude() {
const conversationHistory = [
{
role: "user",
content: "What is the capital of France?",
},
{
role: "assistant",
content: "The capital of France is Paris.",
},
];
const newUserMessage = "And what is its population?";
try {
const message = await anthropic.messages.create({
model: "claude-3-sonnet-20240229",
max_tokens: 150,
messages: [
...conversationHistory, // Spread the existing history
{
role: "user",
content: newUserMessage,
},
],
});
console.log("Claude's response:", message.content[0].text);
// To continue the conversation, you'd add Claude's response to the history
conversationHistory.push({ role: "assistant", content: message.content[0].text });
conversationHistory.push({ role: "user", content: "Tell me more about its history." });
const nextMessage = await anthropic.messages.create({
model: "claude-3-sonnet-20240229",
max_tokens: 300,
messages: conversationHistory,
});
console.log("Claude's next response:", nextMessage.content[0].text);
} catch (error) {
console.error("Error during chat:", error);
}
}
chatWithClaude();
This example illustrates how to maintain and append to a conversationHistory array. By including previous turns, you provide context to Claude, enabling it to understand follow-up questions and maintain a coherent dialogue. The SDK itself doesn’t store state; it’s up to your application to manage the conversation history.
The SDK also supports streaming responses, which is crucial for interactive applications where you want to display text as it’s generated, rather than waiting for the entire response.
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
async function streamResponse() {
try {
const stream = anthropic.messages.create({
model: "claude-3-haiku-20240307",
max_tokens: 500,
messages: [
{
role: "user",
content: "Write a short poem about the stars.",
},
],
stream: true,
});
let fullResponse = "";
for await (const event of stream) {
if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
process.stdout.write(event.delta.text); // Write chunks as they arrive
fullResponse += event.delta.text;
}
}
console.log("\n--- End of stream ---");
// fullResponse now contains the complete text
} catch (error) {
console.error("Error streaming response:", error);
}
}
streamResponse();
When stream is set to true, the messages.create method returns an async iterator. You can then loop through this iterator, processing event objects as they arrive. The most common event type for text generation is content_block_delta with a text_delta. This allows for a more dynamic user experience, making your application feel more responsive.
Beyond basic text generation, the SDK also allows you to leverage Claude’s tool-use capabilities. You can define tools (functions) that Claude can choose to "call" by returning a specific JSON structure. Your application then executes the tool and sends the result back to Claude.
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
async function toolUseExample() {
const tools = [
{
name: "getCurrentWeather",
description: "Get the current weather in a given location",
input_schema: {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "The temperature unit to use",
"default": "celsius",
},
},
"required": ["location"],
},
},
];
try {
const message = await anthropic.messages.create({
model: "claude-3-opus-20240229",
max_tokens: 1000,
tools: tools,
messages: [
{
role: "user",
content: "What's the weather like in Boston, MA?",
},
],
});
if (message.content[0].type === "tool_use") {
console.log("Claude wants to use a tool:", message.content[0].name);
console.log("Tool input:", message.content[0].input);
// In a real application, you would now call your actual getCurrentWeather function
// For demonstration, let's simulate a response
const toolResult = {
location: "Boston, MA",
temperature: "22",
unit: "celsius",
weather: "Sunny",
};
const messageWithToolResult = await anthropic.messages.create({
model: "claude-3-opus-20240229",
max_tokens: 1000,
tools: tools, // Tools need to be re-sent
messages: [
{
role: "user",
content: "What's the weather like in Boston, MA?",
},
{
role: "assistant",
content: null, // Assistant content is null when it's a tool_use
tool_use: message.content[0], // This is the tool_use object from the previous response
},
{
role: "user",
content: null, // User content is null when it's a tool_result
tool_result: {
tool_use_id: message.content[0].id, // Link to the tool_use
content: JSON.stringify(toolResult),
},
},
],
});
console.log("Claude's final response:", messageWithToolResult.content[0].text);
} else {
console.log("Claude's response:", message.content[0].text);
}
} catch (error) {
console.error("Error during tool use example:", error);
}
}
toolUseExample();
In this tool-use scenario, you define tools with their names, descriptions, and input schemas. Claude analyzes the user’s prompt and, if it determines a tool can answer the question, it will output a tool_use block. Your application then needs to interpret this block, execute the corresponding function (e.g., a getCurrentWeather API call), and send the result back to Claude in a subsequent messages.create call, using the tool_result role. This allows Claude to integrate with external data sources and perform actions. The tool_use_id is crucial for linking the result back to the original tool call.
The SDK also provides methods for managing fine-tuning jobs, listing models, and accessing other Anthropic API features. You can explore the full capabilities by referring to the official documentation and the SDK’s source code. The underlying mechanism for all these operations is the HTTP API, and the SDK is simply a convenient wrapper around it, providing a more idiomatic and type-safe interface for developers. The most common pitfall is not handling API rate limits, which can lead to 429 Too Many Requests errors that the SDK will surface.