Channels
Connect your agent to any messaging platform with a unified adapter interface.
Table of Contents
- Overview
- All 37 Channels
- Setup Guides
- Custom Channel Adapter
- Message Routing
- Broadcast to Multiple Channels
Overview
The AgentOS Channel System normalizes every external messaging platform behind
a single IChannelAdapter interface. Your agent code never speaks platform
APIs directly — it emits and receives ChannelMessage objects, and the adapter
handles all platform-specific serialization, authentication, and reconnection.
User (Discord / Telegram / etc.)
↕ platform SDK
IChannelAdapter
↕ ChannelRouter
Your Agent (AgentOS)
Channels are registered as messaging-channel extensions and managed by the
ChannelRouter, which handles load balancing, health checks, and fallback.
All 37 Channels
Messaging & Chat
| Platform | Type | Required Env Vars |
|---|---|---|
discord | Chat | DISCORD_BOT_TOKEN, DISCORD_APPLICATION_ID |
slack | Chat | SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET |
telegram | Chat | TELEGRAM_BOT_TOKEN |
whatsapp | Chat | WHATSAPP_ACCESS_TOKEN, WHATSAPP_PHONE_NUMBER_ID |
google-chat | Chat | GOOGLE_CHAT_SERVICE_ACCOUNT_JSON |
teams | Chat | TEAMS_BOT_ID, TEAMS_BOT_PASSWORD |
signal | Chat | SIGNAL_CLI_PATH or SIGNAL_API_URL |
imessage | Chat | macOS only — no env vars |
matrix | Chat | MATRIX_HOMESERVER_URL, MATRIX_ACCESS_TOKEN |
webchat | Chat | WEBCHAT_SECRET (for webhook validation) |
sms | Messaging | TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_PHONE |
email | Messaging | SMTP_HOST, SMTP_USER, SMTP_PASS |
line | Chat | LINE_CHANNEL_ACCESS_TOKEN, LINE_CHANNEL_SECRET |
zalo | Chat | ZALO_APP_ID, ZALO_APP_SECRET |
feishu | Chat | FEISHU_APP_ID, FEISHU_APP_SECRET |
mattermost | Chat | MATTERMOST_URL, MATTERMOST_BOT_TOKEN |
nextcloud-talk | Chat | NEXTCLOUD_URL, NEXTCLOUD_TOKEN |
irc | Chat | IRC_SERVER, IRC_NICK, IRC_CHANNELS |
nostr | Decentralized | NOSTR_PRIVATE_KEY |
tlon | Decentralized | TLON_SHIP, TLON_CODE |
twitch | Streaming | TWITCH_CLIENT_ID, TWITCH_CLIENT_SECRET, TWITCH_CHANNEL |
Social Media — Broadcast
| Platform | Type | Required Env Vars |
|---|---|---|
twitter | Social | TWITTER_API_KEY, TWITTER_API_SECRET, TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_SECRET |
instagram | Social | INSTAGRAM_ACCESS_TOKEN, INSTAGRAM_ACCOUNT_ID |
linkedin | Social | LINKEDIN_ACCESS_TOKEN, LINKEDIN_ORGANIZATION_ID |
facebook | Social | FACEBOOK_PAGE_ACCESS_TOKEN, FACEBOOK_PAGE_ID |
threads | Social | THREADS_ACCESS_TOKEN, THREADS_USER_ID |
bluesky | Social | BLUESKY_IDENTIFIER, BLUESKY_PASSWORD |
mastodon | Social | MASTODON_INSTANCE_URL, MASTODON_ACCESS_TOKEN |
reddit | Social | REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET, REDDIT_USERNAME, REDDIT_PASSWORD |
pinterest | Social | PINTEREST_ACCESS_TOKEN |
tiktok | Social | TIKTOK_CLIENT_KEY, TIKTOK_CLIENT_SECRET |
youtube | Social | YOUTUBE_API_KEY, YOUTUBE_CHANNEL_ID |
farcaster | Social | FARCASTER_MNEMONIC |
lemmy | Social | LEMMY_INSTANCE_URL, LEMMY_USERNAME, LEMMY_PASSWORD |
Publishing
| Platform | Type | Required Env Vars |
|---|---|---|
devto | Blog | DEVTO_API_KEY |
hashnode | Blog | HASHNODE_TOKEN, HASHNODE_PUBLICATION_ID |
medium | Blog | MEDIUM_INTEGRATION_TOKEN |
wordpress | Blog | WORDPRESS_URL, WORDPRESS_USERNAME, WORDPRESS_PASSWORD |
google-business | Business | GOOGLE_BUSINESS_ACCOUNT_ID, GOOGLE_SERVICE_ACCOUNT_JSON |
Setup Guides
Discord
1. Create a Discord Application
- Go to discord.com/developers/applications
- Create a new application
- Under "Bot", create a bot and copy the token
- Under "OAuth2 → URL Generator", select scopes:
bot,applications.commands - Select permissions:
Send Messages,Read Message History,Use Slash Commands - Invite the bot to your server using the generated URL
2. Set environment variables
export DISCORD_BOT_TOKEN=your-bot-token
export DISCORD_APPLICATION_ID=your-application-id
export DISCORD_GUILD_ID=your-server-id # optional: restrict to one guild
3. Register the adapter
import { ChannelRouter } from '@framers/agentos/channels';
import { DiscordAdapter } from '@framers/agentos-extensions/channels/discord';
const router = new ChannelRouter();
const discord = new DiscordAdapter();
await discord.initialize({
credential: process.env.DISCORD_BOT_TOKEN!,
metadata: { applicationId: process.env.DISCORD_APPLICATION_ID },
});
router.register(discord);
// Listen for incoming messages
discord.on('message', async (message) => {
const response = await agent.reply(message.text);
await discord.sendMessage(message.conversationId, {
blocks: [{ type: 'text', text: response }],
});
});
Slack
1. Create a Slack App
- Go to api.slack.com/apps → Create New App → From Scratch
- Enable "Event Subscriptions" with Request URL pointing to your webhook endpoint
- Subscribe to
message.channels,message.im,app_mentionevents - Under "OAuth & Permissions", add scopes:
chat:write,channels:history,im:history - Install the app to your workspace, copy the Bot User OAuth Token
export SLACK_BOT_TOKEN=xoxb-...
export SLACK_SIGNING_SECRET=your-signing-secret
2. Register the adapter
import { SlackAdapter } from '@framers/agentos-extensions/channels/slack';
const slack = new SlackAdapter();
await slack.initialize({
credential: process.env.SLACK_BOT_TOKEN!,
metadata: { signingSecret: process.env.SLACK_SIGNING_SECRET },
});
router.register(slack);
Telegram
1. Create a bot
- Message @BotFather on Telegram
- Send
/newbotand follow the prompts - Copy the bot token
export TELEGRAM_BOT_TOKEN=123456789:ABC-...
2. Register the adapter
import { TelegramAdapter } from '@framers/agentos-extensions/channels/telegram';
const telegram = new TelegramAdapter();
await telegram.initialize({
credential: process.env.TELEGRAM_BOT_TOKEN!,
});
router.register(telegram);
Twitter / X
1. Create a Twitter Developer Project
- Go to developer.twitter.com → Create Project → Create App
- In the App settings, enable "Read and Write" permissions
- Generate Access Token and Secret under "Keys and Tokens"
export TWITTER_API_KEY=your-api-key
export TWITTER_API_SECRET=your-api-secret
export TWITTER_ACCESS_TOKEN=your-access-token
export TWITTER_ACCESS_SECRET=your-access-secret
2. Register the adapter
import { TwitterAdapter } from '@framers/agentos-extensions/channels/twitter';
const twitter = new TwitterAdapter();
await twitter.initialize({
credential: JSON.stringify({
apiKey: process.env.TWITTER_API_KEY,
apiSecret: process.env.TWITTER_API_SECRET,
accessToken: process.env.TWITTER_ACCESS_TOKEN,
accessSecret: process.env.TWITTER_ACCESS_SECRET,
}),
});
WhatsApp
1. Set up WhatsApp Business API
- Create a Meta Business account at business.facebook.com
- Add a WhatsApp Business App in Meta for Developers
- Configure a phone number and copy the Access Token and Phone Number ID
export WHATSAPP_ACCESS_TOKEN=your-access-token
export WHATSAPP_PHONE_NUMBER_ID=your-phone-number-id
2. Register the adapter
import { WhatsAppAdapter } from '@framers/agentos-extensions/channels/whatsapp';
const whatsapp = new WhatsAppAdapter();
await whatsapp.initialize({
credential: process.env.WHATSAPP_ACCESS_TOKEN!,
metadata: { phoneNumberId: process.env.WHATSAPP_PHONE_NUMBER_ID },
});
Custom Channel Adapter
Implement IChannelAdapter to add any platform not in the built-in set:
import type {
IChannelAdapter,
ChannelAuthConfig,
ChannelSendResult,
MessageContent,
ChannelEventHandler,
ChannelEventType,
ChannelConnectionInfo,
} from '@framers/agentos/channels';
class MyPlatformAdapter implements IChannelAdapter {
readonly platform = 'my-platform';
readonly displayName = 'My Platform';
readonly capabilities = ['text', 'images'] as const;
private client: MyPlatformClient | null = null;
private handlers = new Map<ChannelEventType, ChannelEventHandler[]>();
async initialize(auth: ChannelAuthConfig): Promise<void> {
this.client = new MyPlatformClient(auth.credential);
await this.client.connect();
this.client.on('message', (raw) => {
const normalizedMessage = {
id: raw.messageId,
conversationId: raw.channelId,
text: raw.body,
senderId: raw.userId,
timestamp: raw.ts,
platform: 'my-platform',
};
this.emit('message', normalizedMessage);
});
}
async shutdown(): Promise<void> {
await this.client?.disconnect();
this.client = null;
}
async sendMessage(
conversationId: string,
content: MessageContent,
): Promise<ChannelSendResult> {
const text = content.blocks.find((b) => b.type === 'text')?.text ?? '';
const sent = await this.client!.send({ channelId: conversationId, body: text });
return { messageId: sent.id };
}
on(event: ChannelEventType, handler: ChannelEventHandler): void {
const existing = this.handlers.get(event) ?? [];
this.handlers.set(event, [...existing, handler]);
}
off(event: ChannelEventType, handler: ChannelEventHandler): void {
const existing = this.handlers.get(event) ?? [];
this.handlers.set(event, existing.filter((h) => h !== handler));
}
async getConnectionInfo(): Promise<ChannelConnectionInfo> {
return { status: this.client ? 'connected' : 'disconnected' };
}
private emit(event: ChannelEventType, payload: unknown): void {
for (const handler of this.handlers.get(event) ?? []) {
handler(payload as any);
}
}
}
Register and use:
const myAdapter = new MyPlatformAdapter();
await myAdapter.initialize({ credential: 'my-api-key' });
router.register(myAdapter);
Message Routing
ChannelRouter manages all registered adapters and routes messages by platform:
import { ChannelRouter } from '@framers/agentos/channels';
const router = new ChannelRouter();
// Register all desired adapters
router.register(discordAdapter);
router.register(slackAdapter);
router.register(telegramAdapter);
// Route a message to a specific platform
await router.send('discord', channelId, {
blocks: [{ type: 'text', text: 'Hello from AgentOS!' }],
});
// Listen for messages across all platforms
router.onMessage(async (message, platform) => {
console.log(`[${platform}] ${message.senderId}: ${message.text}`);
const reply = await myAgent.reply(message.text);
await router.send(platform, message.conversationId, {
blocks: [{ type: 'text', text: reply }],
});
});
// Health check all adapters
const health = await router.healthCheck();
console.log(health);
// { discord: 'connected', slack: 'connected', telegram: 'error' }
Broadcast to Multiple Channels
Send the same message to multiple platforms simultaneously:
import { ChannelRouter } from '@framers/agentos/channels';
const router = new ChannelRouter();
// ... register adapters ...
// Broadcast to a fixed list of channels
await router.broadcast(
['discord', 'slack', 'telegram'],
{
blocks: [
{ type: 'text', text: '🚀 AgentOS v2.0 is now live!' },
],
},
{
// Map platform to its target conversation/channel ID
conversationIds: {
discord: '1234567890',
slack: 'C01234ABCDE',
telegram: '-100123456789',
},
}
);
For social media broadcast (Twitter, Bluesky, LinkedIn, etc.), see
SOCIAL_POSTING.md which provides the MultiChannelPostTool
with content adaptation per platform.
Related Guides
- SOCIAL_POSTING.md — publishing to social media platforms
- VOICE_PIPELINE.md — voice call channels (telephony)
- AGENCY_API.md —
agency().connect()for channel-aware agencies - RFC_EXTENSION_STANDARDS.md — extension packaging for channel adapters