Developer — Message
One AI bot, eight messaging platforms, two markets. Streaming chat with per-conversation memory, in-chat media generation, rate limiting — and a single environment variable to switch between the Western and Chinese channel sets.
Requirements
- Node 22 (the codebase targets Node 20.19+; 22 is what the repo pins)
- An API key from at least one AI provider
- Bot credentials for whichever channels you want to run
- Redis — optional. Without it, session memory falls back to in-process storage, which is lost on restart.
Quickstart
npm install
cp .env.example .env.local
npm run dev
Markets — PROFILE=us or PROFILE=cn
This is the core design decision of the edition. One codebase serves both markets, and a single variable picks which channel set boots:
PROFILE | Channels that start |
|---|---|
us | Discord, Telegram, Slack, WhatsApp |
cn | WeCom (企业微信), Feishu (飞书), DingTalk (钉钉), WeChat Official Accounts |
Channels outside the active profile are never initialised, so you do not need their credentials. Set PROFILE in .env.local.
Configuration
Core
| Variable | Purpose |
|---|---|
PROFILE | us or cn — which market's channels to run |
AI_MODEL | Which chat model to use |
SYSTEM_PROMPT | Override the bot's system prompt |
BOT_PRESET | Load a preset persona (see examples/presets.ts) |
REDIS_URL | Session memory and rate limiting. Optional; falls back to in-process. |
AI providers
| Variable | Enables |
|---|---|
OPENAI_API_KEY | GPT models |
ANTHROPIC_API_KEY | Claude models |
GOOGLE_GENERATIVE_AI_API_KEY | Gemini models |
ZAI_API_KEY | GLM models |
Media
| Variable | Purpose |
|---|---|
FAL_KEY | fal.ai — image, video, speech |
REPLICATE_API_TOKEN | Replicate — the alternate provider |
MEDIA_PROVIDER | fal (default) or replicate |
Channel setup
Each channel needs its own credentials from that platform's developer console. Set only the ones you intend to run. Per-channel walkthroughs ship in the repo under docs/channels/.
Western channels (PROFILE=us)
| Channel | Variables | Where to get them |
|---|---|---|
| Discord | DISCORD_BOT_TOKENDISCORD_APP_ID | Discord Developer Portal → your application |
| Telegram | TELEGRAM_BOT_TOKEN | Talk to @BotFather |
| Slack | SLACK_BOT_TOKENSLACK_APP_TOKEN | Slack API → your app (Socket Mode) |
WHATSAPP_ACCESS_TOKENWHATSAPP_PHONE_NUMBER_IDWHATSAPP_VERIFY_TOKENWHATSAPP_APP_SECRET | Meta for Developers → WhatsApp Business API |
Chinese channels (PROFILE=cn)
| Channel | Variables | Where to get them |
|---|---|---|
| WeCom 企业微信 | WECOM_CORP_IDWECOM_CORP_SECRETWECOM_AGENT_IDWECOM_TOKENWECOM_ENCODING_AES_KEY | WeCom admin console → your app |
| Feishu / Lark 飞书 | FEISHU_APP_IDFEISHU_APP_SECRETFEISHU_VERIFICATION_TOKEN | Feishu Open Platform |
| DingTalk 钉钉 | DINGTALK_CLIENT_IDDINGTALK_CLIENT_SECRET | DingTalk Open Platform |
| WeChat OA 微信公众号 | Configured per the WeChat Official Account console | WeChat MP platform |
WECOM_TOKEN and WECOM_ENCODING_AES_KEY pair drives message signature verification and AES decryption — both are required, and the implementation is in src/adapters/wecom-crypto.ts. This is the fiddliest of the eight; the walkthrough in docs/channels/wecom.md covers the callback URL setup step by step.Webhook vs. socket channels
Discord, Telegram, and Slack connect outbound (long-poll or socket) and need no public URL. WhatsApp, WeCom, Feishu, DingTalk, and WeChat OA are webhook-based — the platform calls you, so they need a publicly reachable HTTPS endpoint. In local development, use a tunnel (ngrok, Cloudflare Tunnel) and register that URL in the platform's console.
Media commands
Media generation works in-chat, on every channel:
| Command | Produces |
|---|---|
/imagine <prompt> | An image |
/video <prompt> | A video |
/speak <text> | Speech audio |
Results are returned as native attachments where the platform supports it, and as links where it does not.
Sessions and rate limiting
Session memory is per-conversation: the bot remembers context within a thread or DM. Backed by Redis when REDIS_URL is set; otherwise held in process and lost on restart.
Rate limiting is applied per user to stop one person exhausting your API budget. Configure it in src/core/rate-limit.ts.
Examples
Runnable examples ship in examples/: a support bot, a daily digest bot, a media studio bot, and a community Q&A bot. Each is a working starting point rather than a snippet.
Deploying
Deploy configs are included for Fly (fly.toml) and Railway (railway.json), plus a Dockerfile for anywhere else.
npm run build
npm start
In production you will want:
- A managed Redis →
REDIS_URL, so sessions survive restarts - A public HTTPS URL, if you run any webhook channel
- The callback URL registered in each platform's console
Full detail is in docs/deploy.md in the repo.
What this edition does not include
No billing. Unmetered by design. To run a paid bot business — credits, payment rails, multi-tenancy — see Business.