簡介
人工智慧代理僅在用戶可以從熟悉的平台存取它們時才有用。聊天頻道允許代理部署到 Telegram、Slack、Discord 和許多其他平台 - 所有平台都使用相同的代理核心。
1. 通道適配器介面
// packages/channels/src/types.ts
export interface ChannelAdapter {
readonly channelType: string;
// Initialize channel (set up webhooks, etc.)
initialize(config: ChannelConfig): Promise<void>;
// Send message to channel
sendMessage(channelId: string, message: ChannelMessage): Promise<void>;
// Parse incoming webhook to unified format
parseIncoming(rawPayload: unknown): IncomingMessage;
// Cleanup
shutdown(): Promise<void>;
}
export interface ChannelMessage {
text: string;
markdown?: string;
images?: string[];
buttons?: { label: string; action: string }[];
metadata?: Record<string, unknown>;
}
export interface IncomingMessage {
channelType: string;
channelId: string; // channel/group ID
userId: string; // user ID on the platform
userName: string;
text: string;
images?: string[];
replyToMessageId?: string;
raw: unknown; // Original payload
}
export interface ChannelConfig {
token: string;
webhookUrl?: string;
additionalConfig?: Record<string, unknown>;
}
2. 電報頻道
// packages/channels/telegram/src/telegram-adapter.ts
export class TelegramAdapter implements ChannelAdapter {
readonly channelType = 'telegram';
private bot: TelegramBot;
async initialize(config: ChannelConfig) {
this.bot = new TelegramBot(config.token);
if (config.webhookUrl) {
await this.bot.setWebhook(config.webhookUrl);
}
}
parseIncoming(payload: unknown): IncomingMessage {
const update = payload as TelegramUpdate;
const msg = update.message!;
return {
channelType: 'telegram',
channelId: String(msg.chat.id),
userId: String(msg.from!.id),
userName: msg.from!.first_name,
text: msg.text || '',
images: msg.photo?.map(p => p.file_id),
replyToMessageId: msg.reply_to_message
? String(msg.reply_to_message.message_id)
: undefined,
raw: payload,
};
}
async sendMessage(chatId: string, message: ChannelMessage) {
if (message.markdown) {
await this.bot.sendMessage(chatId, message.markdown, {
parse_mode: 'MarkdownV2',
});
} else {
await this.bot.sendMessage(chatId, message.text);
}
// Send images if any
if (message.images) {
for (const image of message.images) {
await this.bot.sendPhoto(chatId, image);
}
}
}
async shutdown() {
await this.bot.deleteWebhook();
}
}
3. 頻道路由器
// packages/gateway/src/channels/channel-router.ts
export class ChannelRouter {
private channels = new Map<string, ChannelAdapter>();
private agent: Agent;
register(adapter: ChannelAdapter) {
this.channels.set(adapter.channelType, adapter);
}
// Webhook handler — receives messages from all channels
async handleWebhook(channelType: string, payload: unknown): Promise<void> {
const adapter = this.channels.get(channelType);
if (!adapter) throw new Error(`Unknown channel: ${channelType}`);
// Parse to unified format
const incoming = adapter.parseIncoming(payload);
// Find or create user mapping
const user = await this.resolveUser(incoming);
// Chat with agent
const response = await this.agent.chat(
incoming.text,
{
tenantId: user.tenantId,
userId: user.id,
sessionId: `${channelType}:${incoming.channelId}`,
},
);
// Send response back through the same channel
await adapter.sendMessage(incoming.channelId, {
text: response,
markdown: response,
});
}
}
// Webhook routes
app.post('/webhooks/telegram', async (c) => {
const payload = await c.req.json();
await channelRouter.handleWebhook('telegram', payload);
return c.json({ ok: true });
});
app.post('/webhooks/slack', async (c) => {
const payload = await c.req.json();
await channelRouter.handleWebhook('slack', payload);
return c.json({ ok: true });
});
4. 支援的頻道
| 頻道 | 特點 | 適配器 |
|---|---|---|
| 網頁聊天 | 完整豐富的 UI、串流、檔案上傳 | 內建 React 應用程式 |
| 電報 | Markdown、內嵌按鈕、群組 | 機器人 API + webhooks |
| 鬆弛 | 執行緒、反應、斜線指令 | 事件 API |
| 不和諧 | 嵌入、執行緒、斜線指令 | Discord.js |
| 扎洛 | 越南語訊息、OA API | Zalo OA API |
| Facebook Messenger | 快速回覆、模板 | 圖形API |
| 線路 | 豐富的選單,靈活的訊息 | 訊息API |
| 範本、媒體、商業 API | 雲端API |
5. 總結
- 適配器模式 — 適用於所有平台的統一接口
- Channel Router — webhook 閘道→解析→agent.chat()→傳送回應
- 用戶映射 — 外部平台用戶→內部用戶
- 一個代理,多個頻道 - 相同的人工智慧,不同的前端
下一篇文章: React Frontend - 建立網路聊天介面。