Agents with ibot- prefix integrating with WeChat callback messages
This article introduces how to implement WeChat callback message handling for Agents with the ibot- prefix, enabling AI auto-reply in scenarios such as WeChat official accounts, WeChat Mini Program customer service, and WeChat Customer Service.
Overview
Agents with the ibot- prefix are function-based Agents provided by TCB. By implementing the wxSendMessage method, they can receive and process callback messages from the WeChat platform.
Supported WeChat Platforms
| Platform | triggerSrc Value | Reply Mode |
|---|---|---|
| WeChat Mini Program Customer Service | WXMiniapp | Always asynchronous |
| WeChat Service Account | WXService | Synchronous (authenticated) / Asynchronous (unauthenticated) |
| WeChat Subscription Account | WXSubscription | Synchronous (authenticated) / Asynchronous (unauthenticated) |
| WeChat Customer Service | WXCustomerService | Always asynchronous |
Core Interfaces
wxSendMessage Method
ibot- Agent needs to implement the wxSendMessage method for handling WeChat callback messages:
wxSendMessage(input: WxSendMessageInput): Promise<WeChatTextOutput>
API Route: POST /v1/aibot/bots/:botId/wx-send-message
When a WeChat user sends a message, TCB will forward the message to this interface to be handled by your ibot- Agent.
Input Parameters
WxSendMessageInput
| Field | Type | Description |
|---|---|---|
| callbackData | WeChatTextInput | WeChatVoiceInput | WeChatWorkTextInput | WeChatWorkVoiceInput | WeChat callback message data |
| triggerSrc | string | Message source: WXSubscription (Subscription Account), WXService (Service Account), WXMiniapp (Mini Program), WXCustomerService (Customer Service) |
| wxVerify | boolean | Authentication status of the WeChat AppId |
WeChatTextInput (Text Messages from WeChat Official Accounts/Mini Programs)
| Field | Type | Description |
|---|---|---|
| content | string | Message content |
| createTime | number | Message creation time |
| fromUserName | string | Sender's OpenId |
| toUserName | string | Recipient |
| msgId | string | Message ID |
| msgType | string | Message type |
WeChatVoiceInput (Voice Messages from WeChat Official Accounts/Mini Programs)
| Field | Type | Description |
|---|---|---|
| format | string | Audio format |
| mediaId | string | Voice Media ID |
| createTime | number | Message creation time |
| fromUserName | string | Sender's OpenId |
| toUserName | string | Recipient |
| msgId | string | Message ID |
| msgType | string | Message type |
WeChatWorkTextInput (WeChat Customer Service Text Messages)
| Field | Type | Description |
|---|---|---|
| externalUserId | string | External User ID |
| openKfId | string | Customer Service ID |
| origin | number | Message source |
| sendTime | number | Message sending time |
| msgId | string | Message ID |
| msgType | string | Message type |
| text.content | string | Message content |
WeChatWorkVoiceInput (WeChat Customer Service Voice Messages)
| Field | Type | Description |
|---|---|---|
| externalUserId | string | External User ID |
| openKfId | string | Customer Service ID |
| origin | number | Message source |
| sendTime | number | Message sending time |
| msgId | string | Message ID |
| msgType | string | Message type |
| voice.mediaId | string | Voice Media ID |
Response Parameters
WeChatTextOutput
For authenticated WeChat official accounts, it is necessary to return synchronous reply messages:
| Field | Type | Description |
|---|---|---|
| Content | string | Reply content |
| CreateTime | number | Creation timestamp |
| FromUserName | string | Sender (WeChat official accounts) |
| ToUserName | string | Recipient (User) |
| MsgType | string | Message type, fixed to text |
Quick Start
Step 1: Create a Project
Use the @cloudbase/aiagent-framework framework to create a project:
npm init -y
npm install @cloudbase/aiagent-framework
Step 2: Implement the wxSendMessage Method
const { BotCore, BotRunner } = require("@cloudbase/aiagent-framework");
class MyBot extends BotCore {
/**
* Handle WeChat callback messages
* @param {import('@cloudbase/aiagent-framework').WxSendMessageInput} input
* @returns {Promise<import('@cloudbase/aiagent-framework').WeChatTextOutput>}
*/
async wxSendMessage(input) {
const { callbackData, triggerSrc, wxVerify } = input;
// Get user message content
let userMessage = '';
if (callbackData.msgType === 'text') {
// Text message
userMessage = callbackData.content || callbackData.text?.content || '';
} else if (callbackData.msgType === 'voice') {
// Voice message - speech-to-text can be called
const voiceResult = await this.tools.speechToText({
mediaId: callbackData.mediaId || callbackData.voice?.mediaId,
});
userMessage = voiceResult.Result;
}
// Invoke the large model to generate a reply
const reply = await this.generateReply(userMessage);
// Return different formats based on the authentication status
if (wxVerify && (triggerSrc === 'WXSubscription' || triggerSrc === 'WXService')) {
// Authenticated WeChat official accounts: synchronous reply
return {
Content: reply,
CreateTime: Math.floor(Date.now() / 1000),
FromUserName: callbackData.toUserName,
ToUserName: callbackData.fromUserName,
MsgType: 'text',
};
} else {
// Unauthenticated or Mini Program / WeChat Customer Service: asynchronous sending
await this.tools.sendWxMessage({
toUser: callbackData.fromUserName || callbackData.externalUserId,
content: reply,
triggerSrc,
});
return {};
}
}
/**
* Generate AI reply
*/
async generateReply(userMessage) {
// Implement your AI reply logic here
// Can invoke large models, knowledge bases, etc.
const result = await this.tools.chat({
messages: [{ role: 'user', content: userMessage }],
});
return result.content;
}
}
exports.main = function (event, context) {
return BotRunner.run(event, context, new MyBot(context));
};
Step 3: Process Messages from Different Platforms
Differentiate platforms based on triggerSrc and perform differential processing:
class MyBot extends BotCore {
async wxSendMessage(input) {
const { callbackData, triggerSrc, wxVerify } = input;
switch (triggerSrc) {
case 'WXMiniapp':
return this.handleMiniappMessage(callbackData);
case 'WXSubscription':
return this.handleSubscriptionMessage(callbackData, wxVerify);
case 'WXService':
return this.handleServiceMessage(callbackData, wxVerify);
case 'WXCustomerService':
return this.handleWorkWxMessage(callbackData);
default:
console.log('Unknown message source:', triggerSrc);
return {};
}
}
// Handle Mini Program customer service messages (always asynchronous)
async handleMiniappMessage(data) {
const reply = await this.generateReply(data.content);
await this.tools.sendWxMessage({
toUser: data.fromUserName,
content: reply,
triggerSrc: 'WXMiniapp',
});
return {};
}
// Handle Subscription Account messages
async handleSubscriptionMessage(data, wxVerify) {
const reply = await this.generateReply(data.content);
if (wxVerify) {
// Authenticated: synchronous reply
return {
Content: reply,
CreateTime: Math.floor(Date.now() / 1000),
FromUserName: data.toUserName,
ToUserName: data.fromUserName,
MsgType: 'text',
};
} else {
// Unauthenticated: asynchronous sending
await this.tools.sendWxMessage({
toUser: data.fromUserName,
content: reply,
triggerSrc: 'WXSubscription',
});
return {};
}
}
// Handle Service Account messages
async handleServiceMessage(data, wxVerify) {
// The logic is similar to that of Subscription Accounts
return this.handleSubscriptionMessage(data, wxVerify);
}
// Handling WeChat customer service messages (always asynchronous)
async handleWorkWxMessage(data) {
const reply = await this.generateReply(data.text.content);
await this.tools.sendWxMessage({
toUser: data.externalUserId,
content: reply,
triggerSrc: 'WXCustomerService',
openKfId: data.openKfId,
});
return {};
}
}
Complete Example
Combining BotCore's Chat History Feature
const { BotCore, BotRunner } = require("@cloudbase/aiagent-framework");
class MyBot extends BotCore {
async wxSendMessage(input) {
const { callbackData, triggerSrc, wxVerify } = input;
// Obtain user message
const userMessage = this.extractMessage(callbackData);
const userId = callbackData.fromUserName || callbackData.externalUserId;
// Create chat history pair
const { updateBotRecord } = await this.createRecordPair({
userContent: userMessage,
});
// Obtain historical messages for context
const history = await this.getHistoryMessages({ size: 10 });
// Invoke large model
const reply = await this.tools.chat({
messages: [
...history,
{ role: 'user', content: userMessage },
],
});
// Update Bot record
await updateBotRecord({ content: reply.content });
// Return or send the message
if (wxVerify && (triggerSrc === 'WXSubscription' || triggerSrc === 'WXService')) {
return {
Content: reply.content,
CreateTime: Math.floor(Date.now() / 1000),
FromUserName: callbackData.toUserName,
ToUserName: callbackData.fromUserName,
MsgType: 'text',
};
} else {
await this.tools.sendWxMessage({
toUser: userId,
content: reply.content,
triggerSrc,
openKfId: callbackData.openKfId,
});
return {};
}
}
extractMessage(data) {
if (data.content) return data.content;
if (data.text?.content) return data.text.content;
return '';
}
}
exports.main = function (event, context) {
return BotRunner.run(event, context, new MyBot(context));
};
Deployment
After completing the code development, deploy the function to cloud function or cloud hosting:
- Create a function-type cloud hosting service in the TCB console
- Upload the code and deploy
- Associate the Agent with the service in the TCB AI console.
Notes
1. Timeout Handling
The WeChat platform imposes a time limit on message replies:
- WeChat official accounts: A response must be returned within 5 seconds; otherwise, WeChat will retry.
- Mini Program/WeChat customer service: Adopts asynchronous mode with no strict time limit.
It is recommended to uniformly use the asynchronous mode for sending messages in complex AI processing.
2. Message Deduplication
WeChat may repeatedly push the same message. It is recommended to perform deduplication based on msgId:
async wxSendMessage(input) {
const { callbackData } = input;
// Check whether it has been processed
const processed = await this.checkMessageProcessed(callbackData.msgId);
if (processed) {
return {}; // Processed, return directly
}
// Mark as processed
await this.markMessageProcessed(callbackData.msgId);
// Continue processing the message...
}
3. Reply Length Limit
WeChat imposes a length limit on individual messages (approximately 2000 characters). For lengthy AI-generated replies, it is recommended to:
- Segment and send
- Prompt the user to send "Continue" to obtain the subsequent content.
- Restrict the reply length in the prompt