Integrating Claude AI with Node: A Practical Guide

by Evgenii Studitskikh
4 minutes read

In today’s world of AI-powered applications, integrating large language models into your backend services has become increasingly important. Let’s explore how to integrate Claude, Anthropic’s advanced AI model, with a Node.js application. I’ll share what I learned while implementing this integration in a production environment.

The Context

The integration uses Node.js, so we’ll stick to the JavaScript/TypeScript ecosystem. After researching various approaches, I found that Anthropic provides an official Node.js client library that makes the integration straightforward. The library handles authentication, rate limiting, and proper formatting of requests to Claude’s API.

First, let’s install the necessary dependency:

npm install @anthropic-ai/sdk
# or if you're using yarn
yarn add @anthropic-ai/sdk
Bash

Getting Started

I like to approach development incrementally. Here’s how to set up a basic integration with Claude:

const { Anthropic } = require('@anthropic-ai/sdk');

// Initialize the client with your API key
const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

async function askClaude(prompt) {
  try {
    const message = await anthropic.messages.create({
      model: 'claude-3-sonnet-20240229',
      max_tokens: 1024,
      messages: [{
        role: 'user',
        content: prompt
      }]
    });
    
    return message.content[0].text;
  } catch (error) {
    console.error('Error calling Claude:', error);
    throw error;
  }
}
JavaScript

Let’s break down the key components:

  1. We import the Anthropic SDK and initialize it with our API key.
  2. The askClaude function creates a new message using Claude’s chat API.
  3. We specify the model (in this case, Claude 3 Sonnet) and set a max token limit.
  4. The response includes the AI’s reply in the content field.

Building a Simple Express API

Let’s create a simple REST API that uses Claude:

const express = require('express');
const { Anthropic } = require('@anthropic-ai/sdk');

const app = express();
app.use(express.json());

const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

app.post('/api/chat', async (req, res) => {
  try {
    const { prompt } = req.body;
    
    const message = await anthropic.messages.create({
      model: 'claude-3-sonnet-20240229',
      max_tokens: 1024,
      messages: [{
        role: 'user',
        content: prompt
      }]
    });

    res.json({
      response: message.content[0].text
    });
  } catch (error) {
    console.error('Error:', error);
    res.status(500).json({
      error: 'Failed to process request'
    });
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
JavaScript

Handling Multi-Turn Conversations

One of Claude’s powerful features is its ability to maintain context in conversations. Here’s how to implement a stateful chat:

class ConversationManager {
  constructor() {
    this.anthropic = new Anthropic({
      apiKey: process.env.ANTHROPIC_API_KEY,
    });
    this.conversations = new Map();
  }

  async continueConversation(sessionId, userMessage) {
    let conversation = this.conversations.get(sessionId) || [];
    
    // Add user's message to the conversation history
    conversation.push({
      role: 'user',
      content: userMessage
    });

    try {
      const response = await this.anthropic.messages.create({
        model: 'claude-3-sonnet-20240229',
        max_tokens: 1024,
        messages: conversation
      });

      // Add Claude's response to the conversation history
      conversation.push({
        role: 'assistant',
        content: response.content[0].text
      });

      // Update the conversation in our store
      this.conversations.set(sessionId, conversation);

      return response.content[0].text;
    } catch (error) {
      console.error('Error in conversation:', error);
      throw error;
    }
  }
}
JavaScript

Best Practices and Error Handling

When working with Claude in production, consider these best practices:

  1. Rate Limiting: Implement rate limiting to avoid hitting API limits:

const rateLimit = require('express-rate-limit');

const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100 // limit each IP to 100 requests per windowMs
});

app.use('/api/', apiLimiter);
JavaScript

2. Environment Variables: Keep your API key secure using environment variables:

require('dotenv').config();

if (!process.env.ANTHROPIC_API_KEY) {
  throw new Error('ANTHROPIC_API_KEY is required');
}
JavaScript

3. Timeout Handling: Add timeouts to prevent hanging requests:

const timeout = require('connect-timeout');

app.use(timeout('30s'));
app.use(haltOnTimedout);

function haltOnTimedout(req, res, next) {
  if (!req.timedout) next();
}
JavaScript

Conclusion

Integrating Claude with Node.js opens up powerful possibilities for building AI-enhanced applications. The official SDK makes it straightforward to get started, while proper error handling and best practices ensure your integration is production-ready.

Remember to:

  • Keep your API keys secure
  • Implement proper error handling
  • Consider rate limiting for production use
  • Handle conversation state appropriately
  • Monitor API usage and costs

The code examples provided here should give you a solid foundation for building your own Claude-powered applications with Node.js.

Useful Resources

Claude System Prompt Guide

Anthropic API Documentation

Claude TypeScript SDK

Express.js Documentation

Node.js Best Practices

You may also like