discord-web-chat-server
v0.1.0
Published
Discord bridge server for the discord-web-chat widget: web chats become threads in #web-intake, answered by Claude, with human takeover from Discord.
Maintainers
Readme
discord-web-chat-server
Node backend for discord-web-chat-widget: every website chat becomes a thread in your Discord #web-intake channel, answered by Claude by default — until a team member replies in the thread and takes over.
How it works
- Web visitors connect over WebSocket with a persistent session id (stored in the browser). Each session maps to one Discord thread, so returning visitors continue the same conversation.
- Threads are created in
#web-intake(auto-created if missing — the bot needs the Manage Channels permission for that) and named by AI:HH:MM • <8-word intent summary>. - The AI answers every visitor message using your prompt/knowledge file.
- Human takeover: anyone who replies inside the thread pauses the AI; their messages are relayed to the visitor live. The AI resumes 10 minutes (configurable) after the last human message.
- Files/images uploaded from the widget are posted into the thread as attachments; image attachments are also shown to the AI (Anthropic provider).
Standalone
npm install -g discord-web-chat-server
WEB_DISCORD_BOT_TOKEN=... ANTHROPIC_API_KEY=... \
discord-web-chat-server --prompt-file ./prompt.md --port 3900Run discord-web-chat-server --help for all flags (--channel, --guild, --model, --human-idle-minutes, --data-dir, --env, …).
As a module
import { createDiscordWebChat } from 'discord-web-chat-server'
const bridge = createDiscordWebChat({
token: process.env.WEB_DISCORD_BOT_TOKEN,
port: 3900,
intakeChannelName: 'web-intake',
promptFile: './prompt.md', // hot-reloaded; or systemPrompt: '...'
humanIdleMinutes: 10,
ai: {
// provider auto-detects: 'anthropic' when ANTHROPIC_API_KEY is set,
// else 'claude-cli' (a locally authenticated Claude Code install).
model: 'claude-opus-4-8',
// or bring your own: respond: async ({ system, messages }) => '...'
},
})
await bridge.start()
// bridge.setSystemPrompt('...'), bridge.client (discord.js Client), bridge.stop()Discord bot setup
- Create a bot at https://discord.com/developers/applications, enable the Message Content intent.
- Invite it with permissions: View Channels, Manage Channels (for
#web-intakeauto-create), Send Messages, Create Public Threads, Send Messages in Threads, Attach Files, Read Message History. - Put the token in
WEB_DISCORD_BOT_TOKEN.
The prompt setting
--prompt-file prompt.md (or systemPrompt) is where you tell the bot how to behave and give it knowledge — products, policies, tone. The file is hot-reloaded on change, and bridge.setSystemPrompt() updates it at runtime.
Wire protocol (for custom clients)
Connect to ws(s)://host:port/ws?session=<8-64 char id>.
Client → server: {type:'message', text} · {type:'file', name, mime, data(base64), text?}
Server → client: {type:'ready', history, aiPaused} · {type:'message', role:'user'|'assistant'|'agent', text, attachments, ts, id, authorName?} · {type:'typing', on} · {type:'status', aiPaused} · {type:'error', message}
License
MIT
