If you’re trying to integrate OpenClaw with Discord to automate tasks or provide AI assistance, and you’ve found that generic “Discord bot” tutorials don’t quite cut it, you’re not alone. The challenge with OpenClaw isn’t just sending messages; it’s about context, managing rate limits, and ensuring your bot doesn’t become a spam factory. We’re going to set up a server bot that uses OpenClaw to answer specific questions, summarize channel activity, or even generate creative content on demand, all while being mindful of resource usage and API costs.
Looking to get a VPS for your project? Vultr offers reliable VPS hosting starting at $5/month with global data centers. Many OpenClaw users self-host on Vultr for consistent uptime and affordable pricing.
\n\n
Prerequisites and Initial Setup
\n
Before we dive into the Discord-specific bits, ensure you have a working OpenClaw instance. For this setup, I’m assuming you’re running OpenClaw on a Linux server, perhaps a DigitalOcean Droplet or an AWS EC2 instance. You’ll need Node.js (v18 or higher) and npm installed. Our bot will be written in JavaScript, primarily because the Discord.js library is robust and well-maintained. Make sure your OpenClaw API key is configured correctly in ~/.openclaw/config.json under the "api_key" field, and that OpenClaw itself is accessible, ideally running as a service or via pm2.
\n
\n# Check Node.js version\nnode -v\n\n# If not installed, or old, install nvm and then Node.js\ncurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash\nsource ~/.bashrc\nnvm install 18\nnvm use 18\n\n# Verify OpenClaw API key\ncat ~/.openclaw/config.json\n# Ensure it contains: "api_key": "oc_your_api_key_here"\n\n# Install pm2 if you haven't already\nnpm install -g pm2\n
\n
For the Discord bot, create a new directory, navigate into it, and initialize a new Node.js project:
\n
\nmkdir openclaw-discord-bot\ncd openclaw-discord-bot\nnpm init -y\nnpm install discord.js openclaw-sdk dotenv\n
\n
The openclaw-sdk is crucial here, as it provides a convenient interface to your OpenClaw instance. dotenv will help us manage sensitive environment variables like your Discord bot token.
\n\n
Discord Bot Creation and Permissions
\n
Go to the Discord Developer Portal. Click “New Application,” give it a name (e.g., “ClawAssistant”), and click “Create.” Navigate to the “Bot” tab on the left, then click “Add Bot.” Copy your bot’s token – keep this secret! We’ll store it in a .env file. Under “Privileged Gateway Intents,” enable “MESSAGE CONTENT INTENT.” This is critical; without it, your bot won’t be able to read message content, effectively rendering it useless for our purposes. Make sure to save changes.
\n
Now, generate an invite link for your bot. Go to “OAuth2” > “URL Generator.” Select “bot” under “SCOPES.” Under “BOT PERMISSIONS,” select “Read Message History” and “Send Messages.” You might also want “Manage Messages” if you plan to have the bot delete its own responses or user prompts. Copy the generated URL and paste it into your browser to invite the bot to your Discord server.
\n\n
Building the Bot’s Logic
\n
Create a .env file in your openclaw-discord-bot directory:
\n
\nDISCORD_TOKEN=YOUR_BOT_TOKEN_HERE\nOPENCLAW_API_BASE_URL=http://localhost:8000 # Or wherever your OpenClaw instance is\nOPENCLAW_API_KEY=oc_your_api_key_here # Only if not in ~/.openclaw/config.json\n
\n
Next, create an index.js file:
\n
\nrequire('dotenv').config();\nconst { Client, GatewayIntentBits } = require('discord.js');\nconst { OpenClaw } = require('openclaw-sdk');\n\nconst client = new Client({\n intents: [\n GatewayIntentBits.Guilds,\n GatewayIntentBits.GuildMessages,\n GatewayIntentBits.MessageContent\n ]\n});\n\nconst openclaw = new OpenClaw({\n baseURL: process.env.OPENCLAW_API_BASE_URL,\n apiKey: process.env.OPENCLAW_API_KEY\n});\n\nconst PREFIX = '!claw'; // Our command prefix\n\nclient.once('ready', () => {\n console.log(`Logged in as ${client.user.tag}!`);\n});\n\nclient.on('messageCreate', async message => {\n if (message.author.bot) return; // Ignore messages from other bots\n if (!message.content.startsWith(PREFIX)) return; // Only respond to our prefix\n\n const args = message.content.slice(PREFIX.length).trim().split(/ +/);\n const command = args.shift().toLowerCase();\n const prompt = args.join(' ');\n\n if (command === 'ask') {\n if (!prompt) {\n return message.reply('Please provide a prompt after !claw ask.');\n }\n\n try {\n await message.channel.send('Thinking...'); // Acknowledge the request\n\n const response = await openclaw.completion.create({\n model: "claude-haiku-4-5", // Non-obvious insight: haiku is usually enough and much cheaper\n prompt: prompt,\n maxTokens: 500,\n temperature: 0.7\n });\n\n // Split long responses to avoid Discord's 2000 character limit\n const fullResponse = response.choices[0].message.content;\n if (fullResponse.length > 2000) {\n const chunks = fullResponse.match(/[\\s\\S]{1,1900}/g) || [];\n for (const chunk of chunks) {\n await message.channel.send(chunk);\n }\n } else {\n await message.channel.send(fullResponse);\n }\n\n } catch (error) {\n console.error('Error calling OpenClaw:', error);\n message.reply('Sorry, I encountered an error. Please try again later.');\n }\n } else if (command === 'summarize') {\n if (!message.reference) {\n return message.reply('Please reply to a message or provide a message link to summarize.');\n }\n let targetMessage;\n try {\n targetMessage = await message.channel.messages.fetch(message.reference.messageId);\n } catch (error) {\n return message.reply('Could not find the message to summarize. Is it in this channel?');\n }\n\n const summaryPrompt = `Summarize the following Discord message concisely:\\n\\n"${targetMessage.content}"`;\n\n try {\n await message.channel.send('Summarizing...');\n const summaryResponse = await openclaw.completion.create({\n model: "claude-haiku-4-5",\n prompt: summaryPrompt,\n maxTokens: 200,\n temperature: 0.5\n });\n await message.reply(`Summary: ${summaryResponse.choices[0].message.content}`);\n } catch (error) {\n console.error('Error summarizing with OpenClaw:', error);\n message.reply('Failed to summarize the message.');\n }\n }\n});\n\nclient.login(process.env.DISCORD_TOKEN);\n
\n
A non-obvious insight here: while the OpenClaw documentation might suggest using the default model (often a more powerful, expensive one), for most Discord interactions like answering questions or summarizing, claude-haiku-4-5 is incredibly capable. It’s also significantly cheaper (often 10x or more per token) and faster, which is crucial for a responsive bot. Unless you’re doing complex code generation or in-depth analysis, Haiku is your friend for cost-effectiveness.
\n\n
Running and Managing the Bot
\n
To start your bot, simply run node index.js. However, for a production environment, you should use pm2 to keep it running reliably and automatically restart it if it crashes:
\n
\npm2 start index.js --name openclaw-discord-bot\npm2 save\n
\n
You can check its status with pm2 status and view logs with pm2 logs openclaw-discord-bot. This ensures your bot is resilient and doesn’t go offline just because of an unhandled error or server restart.
\n\n
Instant download — no subscription needed
Looking for weekend projects? 9 OpenClaw projects you can build this weekend →
Related: OpenClaw Review: AI-Powered Home Automation That Actually Works
Related: OpenClaw Gateway Real Server Screenshots 2026
Related: OpenClaw Review: AI-Powered Home Automation That Actually Works
Related: OpenClaw Gateway Real Server Screenshots 2026
Related: OpenClaw Review: AI-Powered Home Automation That Actually Works
Related: OpenClaw Gateway Real Server Screenshots 2026
Related: OpenClaw Review: AI-Powered Home Automation That Actually Works
Leave a Reply