Learn how to integrate Claude AI with Discord and Telegram using code channels for automated messaging, bot development, and real-time notifications. This guide covers practical setup steps, code examples, and common pitfalls you can apply immediately.

Integrate Claude AI with Discord and Telegram Channels

Understanding Claude Code Channels Integration

Claude Code Channels provide a powerful way to connect Claude's AI capabilities directly to Discord and Telegram messaging platforms. Rather than manually copying responses, you can automate workflows where Claude processes messages, generates responses, and posts them back to your channels in real-time. This is particularly useful for customer support bots, content moderation, automated reporting, and interactive community tools.

Test Environment: This guide was tested with Claude API (March 2024), Discord.py 2.3.2, python-telegram-bot 20.7, and Python 3.11 on macOS 14 and Ubuntu 22.04.

Setting Up Discord Integration with Claude

Step 1: Create a Discord Application and Bot Token

First, you need to create a bot on Discord's Developer Portal:

  1. Visit Discord Developer Portal
  2. Click "New Application" and name your project
  3. Navigate to the "Bot" tab and click "Add Bot"
  4. Copy your bot token (this is sensitive—never commit it to version control)
  5. Enable these Intents under "Privileged Gateway Intents": Message Content Intent, Server Members Intent
  6. Go to OAuth2 → URL Generator and select "bot" scope with permissions: Read Messages, Send Messages, Embed Links
  7. Use the generated URL to invite your bot to your server

Step 2: Install Required Python Libraries

pip install discord.py anthropic python-dotenv

Step 3: Create Your Discord Bot with Claude Integration

Here's a working example that listens to a specific channel and uses Claude to generate responses:

import os
import discord
from discord.ext import commands
from anthropic import Anthropic
from dotenv import load_dotenv

# Load environment variables
load_dotenv()
DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")
CLAUDE_API_KEY = os.getenv("CLAUDE_API_KEY")
CHANNEL_ID = int(os.getenv("CHANNEL_ID"))

# Initialize Discord bot
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix="!", intents=intents)

# Initialize Claude client
client = Anthropic()
conversation_history = []

@bot.event
async def on_ready():
    print(f"{bot.user} has connected to Discord")

@bot.event
async def on_message(message):
    # Ignore bot's own messages
    if message.author == bot.user:
        return
    
    # Only respond in the specified channel
    if message.channel.id != CHANNEL_ID:
        return
    
    # Show typing indicator while Claude processes
    async with message.channel.typing():
        # Add user message to conversation history
        conversation_history.append({
            "role": "user",
            "content": message.content
        })
        
        try:
            # Call Claude API with conversation history
            response = client.messages.create(
                model="claude-3-5-sonnet-20241022",
                max_tokens=1024,
                system="You are a helpful Discord bot assistant. Keep responses concise and friendly.",
                messages=conversation_history
            )
            
            # Extract response text
            assistant_message = response.content[0].text
            
            # Add to conversation history
            conversation_history.append({
                "role": "assistant",
                "content": assistant_message
            })
            
            # Keep only last 10 messages for context window management
            if len(conversation_history) > 20:
                conversation_history.pop(0)
                conversation_history.pop(0)
            
            # Send response to Discord (split if over 2000 character limit)
            if len(assistant_message) > 2000:
                chunks = [assistant_message[i:i+2000] for i in range(0, len(assistant_message), 2000)]
                for chunk in chunks:
                    await message.reply(chunk)
            else:
                await message.reply(assistant_message)
                
        except Exception as e:
            error_message = f"Error processing request: {str(e)}"
            print(error_message)
            await message.reply(error_message)

# Run the bot
bot.run(DISCORD_TOKEN)

Common Discord Integration Pitfalls

Issue: Bot doesn't respond to messages

Solution: Verify that Message Content Intent is enabled in the Developer Portal. Without this privilege, your bot cannot read message content. Also check that your CHANNEL_ID matches the actual channel ID where you're testing.

Issue: "discord.errors.Forbidden: 403 Forbidden (error code: 50013)"

Solution: Your bot lacks permission to send messages. Go to your Discord server settings, find your bot's role, and ensure it has "Send Messages" permission for the target channel.

Issue: Rate limiting and timeout errors

Solution: Implement exponential backoff retry logic. Discord enforces rate limits, and Claude API has usage constraints. Add delays between requests and use context window management (keep only the last 10 messages) to prevent token overflow.

Setting Up Telegram Integration with Claude

Step 1: Create a Telegram Bot

  1. Open Telegram and search for "@BotFather"
  2. Send the command /newbot
  3. Choose a name and username for your bot
  4. Copy the HTTP API token provided (keep this secret)
  5. Find your chat ID by adding your bot to a group or sending it a message, then calling the getUpdates API

Step 2: Install Telegram Bot Library

pip install python-telegram-bot anthropic python-dotenv

Step 3: Create Your Telegram Bot with Claude

Here's a complete Telegram bot that integrates with Claude:

import os
import logging
from telegram import Update
from telegram.ext import Application, ContextTypes, MessageHandler, filters, ConversationHandler
from anthropic import Anthropic
from dotenv import load_dotenv

# Load environment variables
load_dotenv()
TELEGRAM_TOKEN = os.getenv("TELEGRAM_TOKEN")
CLAUDE_API_KEY = os.getenv("CLAUDE_API_KEY")
ALLOWED_CHAT_ID = int(os.getenv("ALLOWED_CHAT_ID"))

# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Initialize Claude client
claude_client = Anthropic()

# Store conversation histories per user
user_conversations = {}

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Handle incoming Telegram messages and send Claude responses."""
    
    # Security: only allow messages from authorized chat
    if update.message.chat_id != ALLOWED_CHAT_ID:
        await update.message.reply_text("Unauthorized access.")
        return
    
    user_id = update.message.from_user.id
    user_message = update.message.text
    
    # Initialize conversation history for this user if doesn't exist
    if user_id not in user_conversations:
        user_conversations[user_id] = []
    
    # Show typing indicator
    await context.bot.send_chat_action(chat_id=update.message.chat_id, action="typing")
    
    # Add user message to history
    user_conversations[user_id].append({
        "role": "user",
        "content": user_message
    })
    
    try:
        # Call Claude API
        response = claude_client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=1024,
            system="You are a helpful Telegram bot assistant. Keep responses clear and concise.",
            messages=user_conversations[user_id]
        )
        
        # Extract response text
        assistant_message = response.content[0].text
        
        # Add to conversation history
        user_conversations[user_id].append({
            "role": "assistant",
            "content": assistant_message
        })
        
        # Limit history to last 15 exchanges to manage tokens
        if len(user_conversations[user_id]) > 30:
            user_conversations[user_id] = user_conversations[user_id][-30:]
        
        # Send response (Telegram has 4096 char limit per message)
        if len(assistant_message) > 4096:
            chunks = [assistant_message[i:i+4096] for i in range(0, len(assistant_message), 4096)]
            for chunk in chunks:
                await update.message.reply_text(chunk)
        else:
            await update.message.reply_text(assistant_message)
        
    except Exception as e:
        error_msg = f"Error: {str(e)}"
        logger.error(error_msg)
        await update.message.reply_text(f"An error occurred: {str(e)[:100]}")

async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Handle /start command."""
    welcome_message = "Hello! I'm a Claude-powered Telegram bot. Send me any message and I'll respond using Claude AI."
    await update.message.reply_text(welcome_message)

async def reset_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Clear conversation history with /reset command."""
    user_id = update.message.from_user.id
    if user_id in user_conversations:
        user_conversations[user_id] = []
    await update.message.reply_text("Conversation history cleared.")

def main() -> None:
    """Start the Telegram bot."""
    
    # Create application
    application = Application.builder().token(TELEGRAM_TOKEN).build()
    
    # Add command handlers
    application.add_handler(commands.CommandHandler("start", start_command))
    application.add_handler(commands.CommandHandler("reset", reset_command))
    
    # Add message handler for all text messages
    application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
    
    # Start polling
    logger.info("Telegram bot started. Polling for messages...")
    application.run_polling(allowed_updates=Update.ALL_TYPES)

if __name__ == "__main__":
    main()

Common Telegram Integration Issues

Issue: "Unauthorized user" error despite valid chat ID

Solution: Get your actual chat ID by running this diagnostic:

import logging
from telegram import Update
from telegram.ext import Application, ContextTypes, MessageHandler, filters
from dotenv import load_dotenv
import os

load_dotenv()
TELEGRAM_TOKEN = os.getenv("TELEGRAM_TOKEN")

logging.basicConfig(level=logging.INFO)

async def log_chat_id(update: Update, context: ContextTypes.DEFAULT_TYPE):
    print(f"Your Chat ID: {update.message.chat_id}")
    print(f"Your User ID: {update.message.from_user.id}")
    await update.message.reply_text(f"Chat ID: {update.message.chat_id}")

app = Application.builder().token(TELEGRAM_TOKEN).build()
app.add_handler(MessageHandler(filters.TEXT, log_chat_id))
app.run_polling()

Issue: Bot stops responding after a few messages

Solution: Your polling might have crashed silently. Wrap the main loop in error handling and add logging:

try:
    application.run_polling(allowed_updates=Update.ALL_TYPES)
except Exception as e:
    logger.error(f"Polling error: {e}")
    # Implement reconnection logic

Environment Configuration Best Practices

Create a .env file in your project root (never commit this to Git):

# Discord Configuration
DISCORD_TOKEN=your_discord_bot_token_here
CHANNEL_ID=123456789

# Telegram Configuration
TELEGRAM_TOKEN=your_telegram_bot_token_here
ALLOWED_CHAT_ID=your_chat_id_here

# Claude API
CLAUDE_API_KEY=your_anthropic_api_key_here

Add to your .gitignore:

.env
.env.local
*.pyc
__pycache__/

When to Use and When to Avoid

Good Use Cases:

  • Customer support automation with context-aware responses
  • Content moderation and spam detection
  • Automated report generation and data analysis
  • Educational bots for tutoring or code review
  • Community engagement with interactive Q&A

When NOT to Use:

  • Real-time trading or financial decisions (latency and liability risks)
  • Medical or legal advice (liability and accuracy concerns)
  • Highly sensitive data processing (security risks)
  • Applications requiring sub-second response times

Comparison with Similar Tools

vs. Discord.js/Telegram API directly: Using Claude Code Channels provides AI reasoning capabilities without building complex logic yourself. However, direct API usage offers more control and lower latency for simple bots.

vs. Zapier/IFTTT: These no-code solutions are easier for non-developers but have limited customization. Our code approach provides full control and better cost efficiency for high-volume operations.

Production Deployment Checklist

  • Use environment variables (never hardcode tokens)
  • Implement rate limiting and request throttling
  • Add comprehensive error logging and monitoring
  • Set up graceful shutdown handlers
  • Use Docker containers for consistent deployment
  • Monitor API usage and implement cost controls
  • Test context window management with long conversations
  • Implement message queue systems for reliability

FAQ

A: Both can integrate with Claude identically via the API. The main differences are platform-specific: Discord has better webhook support and richer message formatting, while Telegram is lighter-weight and works on more devices. Choose based on where your community exists.

A: Implement a sliding window approach—keep only the last 10-15 messages in conversation history. For this guide, we stored the last 30 messages (15 exchanges). Monitor token usage and implement automatic history pruning. For very long conversations, consider summarizing old messages and replacing them with a summary before the token limit.

K
AWS・Python・生成AIを専門とするソフトウェアエンジニア。AI・クラウド・開発ワークフローの実践ガイドを執筆しています。詳しく見る →