Claude SDK Integration Patterns
Production-ready patterns for integrating Claude API and TypeScript SDK into applications. Master streaming responses, tool execution, error handling, and optimization strategies for AI-powered features.
When to Use This Skill
Use this skill when you need to:
-
Integrate Claude API into Node.js/TypeScript applications
-
Implement streaming conversations with real-time responses
-
Build applications with Claude tool use (function calling)
-
Handle API errors gracefully with retry logic
-
Optimize token usage and manage costs
-
Deploy Claude-powered features to production
-
Build multi-turn conversations with context management
-
Implement message batching for high-volume processing
Core Concepts
Messages API Fundamentals
The Claude Messages API is the primary interface for conversational AI:
Key Components:
-
Model Selection: Choose appropriate model (Opus, Sonnet, Haiku)
-
Messages Array: Conversation history with user/assistant roles
-
Max Tokens: Control response length
-
System Prompts: Guide model behavior
-
Streaming: Real-time response generation
SDK Architecture
The TypeScript SDK provides:
-
Type-safe API client
-
Streaming helpers for real-time responses
-
Tool execution framework
-
Error handling utilities
-
Message batch processing
-
Event-driven architecture
Installation and Setup
Install the SDK
npm install @anthropic-ai/sdk
Or with yarn
yarn add @anthropic-ai/sdk
import Anthropic from '@anthropic-ai/sdk';
// Initialize client const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY, });
Messages API Patterns
Pattern 1: Basic Message Creation
const message = await anthropic.messages.create({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, messages: [ { role: 'user', content: 'Hello, Claude!' } ], });
console.log(message.content);
When to use:
-
Simple question-answer interactions
-
One-off API calls
-
Synchronous workflows
Pattern 2: Multi-Turn Conversations
const messages = [ { role: 'user', content: 'What is TypeScript?' }, { role: 'assistant', content: 'TypeScript is a typed superset of JavaScript...' }, { role: 'user', content: 'Give me an example' }, ];
const response = await anthropic.messages.create({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, messages, });
When to use:
-
Chatbots and conversational UIs
-
Multi-step workflows
-
Context-dependent interactions
Pattern 3: System Prompts
const response = await anthropic.messages.create({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, system: 'You are a helpful Python programming assistant. Provide concise, tested code examples.', messages: [ { role: 'user', content: 'How do I read a CSV file?' } ], });
When to use:
-
Specialized assistants
-
Role-playing scenarios
-
Consistent behavior across conversations
Streaming Patterns
Pattern 4: Basic Streaming
const stream = await anthropic.messages.create({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, messages: [{ role: 'user', content: 'Write a story' }], stream: true, });
for await (const event of stream) { if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') { process.stdout.write(event.delta.text); } }
When to use:
-
Real-time user interfaces
-
Long-form content generation
-
Interactive experiences
Pattern 5: Streaming with Event Handlers
const stream = anthropic.messages.stream({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, messages: [{ role: 'user', content: 'Explain quantum computing' }], }) .on('text', (text) => { console.log(text); }) .on('message', (message) => { console.log('Complete message:', message); }) .on('error', (error) => { console.error('Stream error:', error); });
const finalMessage = await stream.finalMessage();
When to use:
-
Real-time UIs (chatbots, live editors)
-
Progress indicators
-
Partial result processing
Pattern 6: Streaming with Abort Control
const stream = anthropic.messages.stream({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, messages: [{ role: 'user', content: 'Long task...' }], });
// Abort after timeout setTimeout(() => stream.abort(), 5000);
try { await stream.done(); } catch (error) { if (error instanceof Anthropic.APIUserAbortError) { console.log('Stream aborted by user'); } }
When to use:
-
User-cancellable operations
-
Timeout handling
-
Resource management
Tool Use Patterns
Pattern 7: Tool Definition with Zod
import { betaZodTool } from '@anthropic-ai/sdk/helpers/zod'; import { z } from 'zod';
const weatherTool = betaZodTool({
name: 'get_weather',
inputSchema: z.object({
location: z.string(),
unit: z.enum(['celsius', 'fahrenheit']).default('fahrenheit'),
}),
description: 'Get current weather for a location',
run: async (input) => {
// Call weather API
return Weather in ${input.location}: 72°F, sunny;
},
});
When to use:
-
Type-safe tool definitions
-
Input validation
-
Clear tool contracts
Pattern 8: Tool Runner for Automatic Execution
const finalMessage = await anthropic.beta.messages.toolRunner({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1000, messages: [ { role: 'user', content: 'What's the weather in San Francisco?' } ], tools: [weatherTool], });
console.log(finalMessage.content);
When to use:
-
Automated tool execution
-
AI agents with function calling
-
Complex multi-step workflows
Pattern 9: Streaming Tool Execution
const runner = anthropic.beta.messages.toolRunner({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1000, messages: [{ role: 'user', content: 'Check weather and calculate travel time' }], tools: [weatherTool, travelTimeTool], stream: true, });
for await (const messageStream of runner) { for await (const event of messageStream) { console.log('Event:', event); } console.log('Message:', await messageStream.finalMessage()); }
When to use:
-
Real-time tool execution feedback
-
Multi-tool workflows
-
Interactive AI agents
Error Handling Patterns
Pattern 10: Comprehensive Error Handling
async function createMessage(prompt: string) { try { const message = await anthropic.messages.create({ model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, messages: [{ role: 'user', content: prompt }], });
return message;
} catch (error) { if (error instanceof Anthropic.APIError) { console.error('API Error:', { status: error.status, name: error.name, message: error.message, headers: error.headers, });
// Handle specific errors
if (error.status === 429) {
// Rate limit - implement backoff
console.log('Rate limited, waiting...');
await new Promise(resolve => setTimeout(resolve, 60000));
return createMessage(prompt); // Retry
} else if (error.status === 401) {
throw new Error('Invalid API key');
} else if (error.status === 400) {
throw new Error(`Bad request: ${error.message}`);
}
}
throw error;
} }
When to use:
-
Production applications
-
Robust error recovery
-
User-facing applications
Pattern 11: Exponential Backoff Retry
async function createWithRetry(
params: Anthropic.MessageCreateParams,
maxRetries = 3,
baseDelay = 1000
): Promise<Anthropic.Message> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await anthropic.messages.create(params);
} catch (error) {
if (error instanceof Anthropic.APIError && error.status === 429) {
// Rate limit - exponential backoff
const delay = baseDelay * Math.pow(2, attempt);
console.log(Retry attempt ${attempt + 1} after ${delay}ms);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
throw new Error('Max retries exceeded'); }
When to use:
-
High-volume applications
-
Rate limit handling
-
Network reliability
Token Optimization Patterns
Pattern 12: Token Counting
import { encode } from 'gpt-tokenizer';
function estimateTokens(text: string): number { // Approximate token count (Claude uses similar tokenization to GPT) return encode(text).length; }
function optimizePrompt(userMessage: string, maxTokens: number = 1024): string { const tokens = estimateTokens(userMessage);
if (tokens > maxTokens) { // Truncate or summarize return userMessage.slice(0, maxTokens * 4); // Rough char estimate }
return userMessage; }
When to use:
-
Cost optimization
-
Token budget management
-
Large input handling
Pattern 13: Context Window Management
interface ConversationMessage { role: 'user' | 'assistant'; content: string; tokens?: number; }
class ConversationManager { private messages: ConversationMessage[] = []; private maxContextTokens = 100000;
addMessage(role: 'user' | 'assistant', content: string) { const tokens = estimateTokens(content); this.messages.push({ role, content, tokens }); this.pruneIfNeeded(); }
private pruneIfNeeded() { const totalTokens = this.messages.reduce((sum, msg) => sum + (msg.tokens || 0), 0);
if (totalTokens > this.maxContextTokens) {
// Remove oldest messages (keep system prompt if present)
this.messages = this.messages.slice(-10); // Keep last 10 messages
}
}
getMessages() { return this.messages.map(({ role, content }) => ({ role, content })); } }
When to use:
-
Long conversations
-
Context management
-
Cost control
Message Batching Patterns
Pattern 14: Batch Processing
const batchResult = await anthropic.messages.batches.create({ requests: [ { custom_id: 'request-1', params: { model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, messages: [{ role: 'user', content: 'Summarize this article...' }], }, }, { custom_id: 'request-2', params: { model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, messages: [{ role: 'user', content: 'Translate this text...' }], }, }, ], });
// Poll for results const batch = await anthropic.messages.batches.retrieve(batchResult.id);
When to use:
-
Bulk processing
-
Offline workflows
-
Cost optimization (lower batch pricing)
Production Patterns
Pattern 15: Request Timeout Configuration
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY, timeout: 60000, // 60 seconds maxRetries: 3, });
When to use:
-
Production deployments
-
Network reliability
-
Resource management
Pattern 16: Custom Headers and Metadata
const message = await anthropic.messages.create( { model: 'claude-sonnet-4-5-20250929', max_tokens: 1024, messages: [{ role: 'user', content: 'Hello' }], }, { headers: { 'anthropic-beta': 'max-tokens-3-5-sonnet-2024-07-15', }, } );
When to use:
-
Beta features
-
Custom tracking
-
A/B testing
Best Practices
API Key Management
Never hardcode API keys
// ❌ Bad const anthropic = new Anthropic({ apiKey: 'sk-ant-...' });
// ✅ Good const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
Use environment variables
.env file
ANTHROPIC_API_KEY=sk-ant-your-key-here
Model Selection
Choose appropriate model for task:
-
Opus: Most capable, complex reasoning
-
Sonnet: Balanced performance/speed
-
Haiku: Fastest, simple tasks
Use latest model versions:
model: 'claude-sonnet-4-5-20250929' // Latest
Streaming Considerations
Always use streaming for:
-
User-facing applications
-
Long-form content (>500 tokens)
-
Real-time interactions
Avoid streaming for:
-
Backend batch processing
-
Deterministic outputs needed upfront
-
Simple API integrations
Error Handling
-
Always catch API errors
-
Implement retry logic for transient failures
-
Log errors for debugging
-
Provide user-friendly error messages
Token Management
-
Estimate tokens before API calls
-
Set appropriate max_tokens
-
Monitor token usage
-
Implement context pruning for long conversations
Troubleshooting
Issue: Rate Limit Errors (429)
Solution:
-
Implement exponential backoff
-
Use message batching for bulk operations
-
Upgrade to higher rate limit tier
Issue: Timeout Errors
Solution:
-
Use streaming for long responses
-
Increase timeout configuration
-
Reduce max_tokens
Issue: Invalid API Key (401)
Solution:
-
Verify environment variable is set
-
Check API key format (starts with sk-ant- )
-
Ensure key hasn't been rotated
Issue: Context Length Exceeded
Solution:
-
Implement conversation pruning
-
Summarize older messages
-
Use appropriate context window limits
Resources
-
Anthropic API Documentation
-
TypeScript SDK GitHub
-
Claude API Pricing
-
Model Comparison
Skill Version: 1.0.0 Last Updated: October 2025 Compatibility: @anthropic-ai/sdk 0.30.0+ Research Source: Context7 - Anthropic TypeScript SDK (106 code snippets, Trust Score 8.8)