Bot SDK Fundamentals
Learn the fundamentals of the Towns Protocol Bot SDK and set up your development environment. Understand what the Bot SDK is, how it works, and prepare your project for building and deploying a production-ready bot.
Learning Objectives
By the end of this module, you will be able to:
What is the Bot SDK?
Learn what the Towns Protocol Bot SDK is and how it helps you build bots.
The Towns Protocol Bot SDK (@towns-protocol/bot) is a framework that makes it easy to build interactive bots. It handles webhook communication, slash commands, and event processing so you can focus on your bot's functionality.
Critical: Stateless Architecture
Towns Protocol bots are completely stateless. Each event is processed in isolation with:
- • No message history - Cannot access previous messages in the conversation
- • No thread context - Cannot see what messages are replies to
- • No conversation memory - Each event handler starts fresh
- • No built-in state - Must use databases to persist any data
This is by design for scalability. You must handle each event independently and use databases (Module 5) for any persistence.
How It Works
Your bot runs as a web server that receives events from Towns via webhooks. When users interact with your bot (messages, commands, reactions), the SDK processes these events and provides simple handler functions to respond.
Key Features
- • Send messages to channels
- • Handle slash commands
- • React to user events
- • Secure webhook validation
Main Packages
- •
@towns-protocol/bot - •
@towns-protocol/sdk - •
hono(web server)
Initialize Your Bot
Use the official scaffolding tool to create your bot project with all necessary files.
Create Your Bot Project
Run this command to create a new bot project with the official scaffolding:
bunx towns-bot init my-towns-bot
cd my-towns-botGenerated Project Structure
The init command creates a complete bot project with this structure:
my-towns-bot/
├── src/
│ ├── index.ts # Main bot file with webhook setup
│ └── commands.ts # Slash command definitions
├── .env.sample # Environment variable template
├── .gitignore # Git ignore (protects secrets)
├── package.json # Dependencies and scripts
└── tsconfig.json # TypeScript configurationWhat You Get
- • Bot server setup with Hono and webhook handling
- • Example commands ready to customize
- • TypeScript configuration optimized for bot development
- • Build scripts for development and production
Install Dependencies
Install all required packages for your bot.
Install Packages
The generated project includes all necessary dependencies. Install them with:
bun installAvailable Scripts
Your package.json includes these useful scripts:
bun run devStart development server with hot reload (watches for file changes)
bun run startRun the production build (used by Render in Module 6)
Configure Environment
Set up environment variables for your bot.
Create .env File
Copy the sample environment file to create your .env:
cp .env.sample .envEnvironment Variables
Your .env file should contain:
# Bot Credentials (you'll get these in Module 6)
# IMPORTANT: APP_PRIVATE_DATA must be base64 encoded!
APP_PRIVATE_DATA=your_base64_encoded_private_data_here
JWT_SECRET=your_jwt_secret_here
MNEMONIC=your_twelve_word_recovery_phrase_here
# Server Port
PORT=5123Getting Your Credentials
You'll get your actual APP_PRIVATE_DATA, JWT_SECRET, and MNEMONIC from the Towns Developer Portal in Module 6: Deployment. For now, the placeholder values are fine for local development.
Understanding the Bot Code
Walk through the generated bot code to understand how it works.
Generated src/index.ts
The init command created a complete bot server. Here are the key parts:
import { Hono } from 'hono'
import { makeTownsBot } from '@towns-protocol/bot'
import commands from './commands.js'
// Initialize bot with credentials
// NOTE: APP_PRIVATE_DATA must be base64 encoded
const bot = makeTownsBot({
privateData: process.env.APP_PRIVATE_DATA!, // base64 encoded
webhookSecret: process.env.JWT_SECRET!,
mnemonic: process.env.MNEMONIC!, // 12-word recovery phrase
port: parseInt(process.env.PORT || '5123', 10)
})
// Register slash commands
bot.setSlashCommands(commands)
// Example message handler (stateless - no history access)
bot.onMessage(async (handler, event) => {
// Each event is isolated - no access to previous messages
if (event.message === 'GM') {
await handler.sendMessage(event.channelId, 'GM! 🌅')
}
})
// Start webhook server
bot.startWebhook()
console.log(`✅ Bot is running on port ${bot.port}`)
How It Works
1. Bot Initialization
makeTownsBot() creates your bot using base64-encoded credentials from .env and sets up the webhook server.
2. Bot Wallet Architecture
Your bot has two wallet addresses: bot.botId for signing transactions and bot.appAddress for receiving funds and executing actions.
3. Webhook Server
The bot starts an HTTP server that listens for webhook events from Towns Protocol. All events are validated with JWT for security.
Command Definitions src/commands.ts
The generated file includes example commands. We'll customize these in Module 2:
export default [
{
name: 'hello',
description: 'Say hello to the bot',
},
{
name: 'help',
description: 'Get help with bot commands',
},
]Module 1 Complete!
Excellent! You've initialized your bot project and installed dependencies. Your bot foundation is ready for adding commands and features in the next modules!