Home
/
Blog
/
How to Build an iMessage AI Agent with Claude + Sendblue
March 29, 2026
12 min read
Nikita Jerschow

How to Build an iMessage AI Agent with Claude + Sendblue

AI agents that communicate over iMessage are one of the fastest-growing use cases for the Sendblue API. In this tutorial, you'll build a complete AI agent that receives iMessages, processes them with Claude, and responds intelligently — all through blue bubble messages that recipients trust and engage with.

Architecture Overview

The architecture is straightforward:

  1. User sends an iMessage to your Sendblue phone number
  2. Sendblue forwards it via webhook to your server
  3. Your server sends it to Claude (Anthropic API) with conversation context
  4. Claude generates a response
  5. Your server sends the response back via Sendblue as an iMessage

The user has a natural iMessage conversation. They never know they're talking to an AI (unless you tell them). Messages appear as blue bubbles from a real phone number.

Why iMessage for AI agents? SMS gets filtered by carriers. Email goes to spam. iMessage gets 98% open rates and feels like a personal conversation. Your AI agent reaches people in the most trusted channel on their phone.

Setup and Dependencies

mkdir imessage-agent && cd imessage-agent npm init -y npm install express sendblue @anthropic-ai/sdk

You'll need:

Build the Agent

import express from 'express'; import Sendblue from 'sendblue'; import Anthropic from '@anthropic-ai/sdk'; const app = express(); app.use(express.json()); const sendblue = new Sendblue( process.env.SENDBLUE_API_KEY, process.env.SENDBLUE_API_SECRET ); const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY, }); // Store conversation history per phone number const conversations = new Map(); const SYSTEM_PROMPT = `You are a helpful business assistant for Acme Corp. You help customers with questions about products, pricing, and support. Keep responses concise — under 300 characters when possible. Be friendly and professional.`; app.post('/webhook/receive', async (req, res) => { const { from_number, content } = req.body; // Get or create conversation history if (!conversations.has(from_number)) { conversations.set(from_number, []); } const history = conversations.get(from_number); // Add user message to history history.push({ role: 'user', content }); // Keep last 20 messages for context if (history.length > 20) history.splice(0, history.length - 20); try { // Send typing indicator while processing await sendblue.sendTypingIndicator({ number: from_number }); // Get Claude's response const response = await anthropic.messages.create({ model: 'claude-sonnet-4-20250514', max_tokens: 500, system: SYSTEM_PROMPT, messages: history, }); const reply = response.content[0].text; // Add assistant response to history history.push({ role: 'assistant', content: reply }); // Send the response via iMessage await sendblue.sendMessage({ number: from_number, content: reply, }); } catch (error) { console.error('Error:', error); await sendblue.sendMessage({ number: from_number, content: "Sorry, I'm having trouble right now. A human will follow up shortly.", }); } res.status(200).json({ status: 'ok' }); }); app.listen(3000);

Key Design Decisions

Typing indicators: The sendTypingIndicator call shows the "..." bubble while Claude processes. This makes the conversation feel natural — the user sees your agent is "typing" rather than wondering if the message was received.

Conversation history: We store the last 20 messages per phone number so Claude has context for multi-turn conversations. In production, you'd use Redis or a database instead of an in-memory Map.

Error handling: If Claude fails, we send a friendly fallback message rather than leaving the user hanging. In production, you'd also alert a human agent.

Message length: iMessage supports up to 18,996 characters, but shorter messages feel more natural in a text conversation. The system prompt instructs Claude to keep responses concise.

Deploy and Configure

1. Deploy to your server (Railway, Render, AWS, or any Node.js host).

2. Set your webhook URL in the Sendblue dashboard → Settings → Webhooks → Receive webhook.

3. Test it by sending an iMessage to your Sendblue phone number.

For production, consider:

  • Persistent storage: Use Redis or PostgreSQL for conversation history
  • Rate limiting: Prevent abuse from individual numbers
  • Human handoff: Detect when the AI can't help and route to a human agent
  • Monitoring: Log all conversations for quality assurance

The AI Agents use case page has more patterns and examples for production deployments.

Ready to send your first iMessage?

Get API access in minutes. Free sandbox, no credit card required.

Get API Access