Channels
Connect your AI to multiple platforms simultaneously. Web Chat, Telegram, Discord, and Slack all share the same personality, memory, and context.
6 min read
Channels
Channels are the communication endpoints that connect your Chvor instance to the outside world. Every message β whether it comes from the built-in Web Chat, a Telegram bot, a Discord server, or a Slack workspace β flows through the same processing pipeline. The AI maintains one unified personality, one shared memory, and one context across all channels.
Architecture
Every incoming message follows the same path regardless of which channel it arrives from:
ββββββββββββ ββββββββββββ ββββββββββββββββ βββββββ
β Telegram ββββββΆβ β β β β β
ββββββββββββ€ β Gateway ββββββΆβ Orchestrator ββββββΆβ LLM β
β Discord ββββββΆβ β β β β β
ββββββββββββ€ β β β β β β
β Slack ββββββΆβ β β - Skills βββββββ β
ββββββββββββ€ β β β - Tools β β β
β Web Chat ββββββΆβ β β - Memory β β β
ββββββββββββ ββββββββββββ ββββββββββββββββ βββββββ
Gateway
The gateway normalizes messages from different platforms into a common format. Regardless of whether a message is a Telegram update, a Discord interaction, or a Slack event, the gateway produces the same internal structure:
interface ChannelMessage {
channelType: "web" | "telegram" | "discord" | "slack";
channelId: string; // Platform-specific channel/chat ID
userId: string; // Platform-specific user ID
userName: string; // Display name
content: string; // Message text
attachments: Attachment[]; // Images, files, etc.
replyTo?: string; // Message ID being replied to
timestamp: number;
}
Orchestrator
The orchestrator receives the normalized message and:
- Loads relevant memories from the vector store
- Selects the appropriate skill (Constellation mode) or follows the pipeline
- Injects directives and conversation history
- Sends the composed prompt to the LLM
- Processes tool calls if needed
- Returns the response to the gateway for delivery
Response delivery
The gateway formats the response for the target platform β Markdown for Web Chat and Discord, HTML for Telegram, Block Kit for Slack β and sends it back through the platformβs API.
Web Chat (built-in)
Web Chat is Chvorβs built-in channel. It is always available and requires no configuration.
# config.yaml β Web Chat is enabled by default
channels:
web:
enabled: true
The Web Chat interface is part of the React client and connects to the server via WebSocket. It supports:
- Streaming responses (token by token)
- File uploads (images, documents)
- Markdown rendering with syntax highlighting
- Message history with search
- Real-time Brain Canvas sync
Telegram
Connect a Telegram bot to Chvor so users can interact with your AI from any Telegram client.
Setup
- Create a bot through @BotFather on Telegram
- Copy the bot token
- Add the configuration to
config.yaml:
channels:
telegram:
enabled: true
token: "7123456789:AAH..."
# Optional: restrict to specific chat IDs
allowed_chats:
- 123456789 # Your personal chat ID
- -100987654321 # A group chat ID
# Optional: webhook mode (default is polling)
webhook:
url: "https://your-domain.com/api/channels/telegram/webhook"
secret: "your-webhook-secret"
Features
- Supports text, images, and document attachments
- Group chat support (mention the bot or reply to its messages)
- Inline commands map to skill triggers (
/plan,/code,/research) - Long responses are automatically split into multiple messages
Discord
Add your AI as a Discord bot that responds in any channel it has access to.
Setup
- Create a Discord application at the Discord Developer Portal
- Create a bot user and copy the token
- Invite the bot to your server with the appropriate permissions (Send Messages, Read Message History, Attach Files)
- Add the configuration:
channels:
discord:
enabled: true
token: "MTIz..."
# Optional: restrict to specific guild/channel IDs
allowed_guilds:
- "1234567890123456789"
allowed_channels:
- "9876543210987654321"
Features
- Responds to mentions and direct messages
- Thread support β the bot can maintain separate conversation contexts per thread
- Embeds for structured responses (code blocks, tables)
- Slash command registration for skill triggers
- File and image attachment support
Slack
Integrate with Slack workspaces using the Slack Events API.
Setup
- Create a Slack app at api.slack.com/apps
- Enable Event Subscriptions and subscribe to
message.imandapp_mentionevents - Install the app to your workspace
- Add the configuration:
channels:
slack:
enabled: true
bot_token: "xoxb-..."
app_token: "xapp-..." # For Socket Mode
signing_secret: "abc..."
# Optional: Socket Mode (no public URL needed)
socket_mode: true
Features
- Socket Mode for deployments without a public URL
- Responds to DMs and @mentions in channels
- Block Kit formatting for rich responses
- Thread support with context preservation
- Slash commands map to skill triggers
Shared personality, memory, and context
The key design principle of Chvorβs channel system is convergence. All channels connect to the same AI instance:
- Same personality: The AI uses the same skills, directives, and rules regardless of where the message comes from
- Same memory: A conversation on Telegram is recalled when chatting on Discord. Memory is not siloed by channel
- Same tools: All channels have access to the same skill and tool graph
- Per-channel history: Conversation threads are tracked per-channel so the AI can maintain separate conversational contexts while sharing long-term memory
This means you can start a research task on your phone via Telegram, continue refining it on Discord from your desktop, and review the final output in Web Chat β the AI remembers all of it.
User (Telegram): Research the top 5 Rust web frameworks
AI: [researches and responds with findings]
User (Discord, 2 hours later): Which of those frameworks did you recommend?
AI: Based on my earlier research, I recommended Axum for its...
Adding new channels
Chvorβs channel system is designed to be extensible. Each channel is a module that implements the Channel interface:
interface Channel {
// Unique identifier for this channel type
type: string;
// Initialize the channel (connect to platform APIs, set up webhooks)
start(config: ChannelConfig): Promise<void>;
// Stop the channel gracefully
stop(): Promise<void>;
// Send a response back to the platform
send(channelId: string, response: AIResponse): Promise<void>;
// Event emitter for incoming messages
on(event: "message", handler: (msg: ChannelMessage) => void): void;
}
To add a new channel:
- Create a new module in
apps/server/src/channels/ - Implement the
Channelinterface - Register it in
apps/server/src/channels/index.ts - Add the configuration schema to the config loader
The gateway and orchestrator handle everything else β normalization, skill routing, memory retrieval, and response formatting are all channel-agnostic.