Create a Discord bot
Build Discord bots powered by Letta agents with persistent memory and intelligent conversation capabilities.
Create a Discord bot powered by a Letta agent with persistent memory, streaming responses, and thread support.
Prerequisites
Section titled “Prerequisites”- Node.js and npm
- A Discord application
- A Letta agent (Letta Developer Platform or self-hosted)
Quick start
Section titled “Quick start”1. Clone and install
Section titled “1. Clone and install”git clone https://github.com/letta-ai/letta-discord-bot-example.gitcd letta-discord-bot-examplenpm install2. Set up Discord
Section titled “2. Set up Discord”- Create an application in the Discord Developer Portal
- Under Bot, copy your token and enable Message Content Intent
- Under Installation, set scopes to
bot,applications.commandswith permissions: Read Messages, Send Messages, Create Public Threads, Send Messages in Threads, Read Message History - Add the bot to your server using the installation link
3. Configure environment
Section titled “3. Configure environment”cp .env.template .envEdit .env:
# LettaLETTA_API_KEY=your_letta_api_keyLETTA_BASE_URL=https://api.letta.com # or http://localhost:8283 for self-hostedLETTA_AGENT_ID=your_agent_id
# DiscordAPP_ID=your_discord_app_idDISCORD_TOKEN=your_discord_bot_tokenPUBLIC_KEY=your_discord_public_key
# BehaviorRESPOND_TO_DMS=trueRESPOND_TO_MENTIONS=trueRESPOND_TO_BOTS=falseRESPOND_TO_GENERIC=false4. Run
Section titled “4. Run”npm run build && npm startHow it works
Section titled “How it works”- Discord message received and filtered by type
- Recent conversation history fetched for context
- Message formatted with sender info and channel name
- Streamed to your Letta agent
- Response streamed back to Discord (auto-split if over 2000 chars)
Message types
Section titled “Message types”| Type | Trigger | Format |
|---|---|---|
| DM | Direct message | [user (id=123) sent you a DM] message |
| MENTION | @bot | [user (id=123) mentioned you in #channel] message |
| REPLY | Reply to bot | [user (id=123) replied to you in #channel] message |
| GENERIC | Any message | [user (id=123) in #channel] message |
Configuration
Section titled “Configuration”Context and history
Section titled “Context and history”LETTA_CONTEXT_MESSAGE_COUNT=5 # Recent messages to include (0 to disable)LETTA_THREAD_CONTEXT_ENABLED=true # Fetch full thread contextLETTA_THREAD_MESSAGE_LIMIT=50 # Max thread messagesChannel filtering
Section titled “Channel filtering”DISCORD_CHANNEL_ID=123 # Only listen to this channelDISCORD_RESPONSE_CHANNEL_ID=456 # Only respond in this channelThreads and batching
Section titled “Threads and batching”REPLY_IN_THREADS=true # Create threads for responses
MESSAGE_BATCH_ENABLED=true # Batch messages before sendingMESSAGE_BATCH_SIZE=10 # Max messages per batchMESSAGE_BATCH_TIMEOUT_MS=30000 # Auto-send after 30sAutonomous behavior
Section titled “Autonomous behavior”ENABLE_TIMER=true # Allow agent-initiated messagesTIMER_INTERVAL_MINUTES=15 # Max intervalFIRING_PROBABILITY=0.1 # 10% chance per intervalRequires DISCORD_CHANNEL_ID to be set.
Agent configuration
Section titled “Agent configuration”Add Discord context to your agent’s human block:
I am connected to a Discord server.I see messages when users mention me or reply to me.To mention a user, use <@discord-id> format.Add an ignore() tool to let your agent skip messages:
def ignore(): """Call this to skip responding to a message.""" returnDeployment
Section titled “Deployment”Railway (one-click)
Section titled “Railway (one-click)”Self-hosted
Section titled “Self-hosted”See the self-hosting guide for running your own Letta server. Once running, set LETTA_BASE_URL=http://localhost:8283 in your .env.
Run the bot with PM2, systemd, or Docker to keep it running:
npm run build && npm startTroubleshooting
Section titled “Troubleshooting”Bot doesn’t respond: Check Message Content Intent is enabled, RESPOND_TO_MENTIONS=true, and bot has channel permissions.
Agent doesn’t remember context: Verify LETTA_CONTEXT_MESSAGE_COUNT > 0 and thread context is enabled if using threads.
Errors in Discord: Set SURFACE_ERRORS=true to see errors in chat (default: logged only).