@ariaflowagents/messaging-meta
v0.8.1
Published
Meta platform clients (WhatsApp, Messenger, Instagram) for AriaFlow messaging
Downloads
39
Readme
@ariaflowagents/messaging-meta
Meta platform clients (WhatsApp, Messenger, Instagram) for AriaFlow messaging. Each client implements the PlatformClient interface from @ariaflowagents/messaging.
Install
npm install @ariaflowagents/messaging-meta @ariaflowagents/messagingimport { createWhatsAppClient } from '@ariaflowagents/messaging-meta/whatsapp';
const whatsapp = createWhatsAppClient({
accessToken: process.env.WHATSAPP_ACCESS_TOKEN!,
appSecret: process.env.META_APP_SECRET!,
phoneNumberId: process.env.WHATSAPP_PHONE_NUMBER_ID!,
verifyToken: process.env.WHATSAPP_VERIFY_TOKEN!,
});
// Listen for messages
whatsapp.onMessage(async (msg) => {
await whatsapp.markAsRead(msg.id);
await whatsapp.sendText(msg.from.phone!, `You said: ${msg.text}`);
});
// Mount webhook (Hono)
app.route('/whatsapp', whatsapp.webhookRouter());Templates and Interactive Messages
import { buildTemplateSendPayload } from '@ariaflowagents/messaging-meta/whatsapp';
// Template
await whatsapp.sendTemplate('+1234567890', buildTemplateSendPayload({
name: 'order_confirmation',
language: { code: 'en_US' },
components: [{ type: 'body', parameters: [{ type: 'text', text: 'ORD-1234' }] }],
}));
// Buttons
await whatsapp.sendInteractiveButtons('+1234567890', {
body: 'How can we help?',
buttons: [{ id: 'sales', title: 'Sales' }, { id: 'support', title: 'Support' }],
});
// List
await whatsapp.sendListMessage('+1234567890', {
body: 'Select a department',
button: 'View Options',
sections: [{ title: 'Departments', rows: [{ id: 'eng', title: 'Engineering' }] }],
});WhatsApp-Specific Methods
| Method | Description |
|---|---|
| sendText(to, text) | Send text (auto-splits at 4096 chars) |
| sendMedia(to, media) | Send image, video, audio, document, sticker |
| sendTemplate(to, template) | Send approved template message |
| sendTextOrTemplate(to, opts) | Send text if window open, template if closed |
| sendInteractiveButtons(to, msg) | Send button message (max 3) |
| sendListMessage(to, list) | Send list picker |
| sendCTAButton(to, cta) | Send call-to-action URL button |
| sendInteractiveFlow(to, flow) | Launch a WhatsApp Flow |
| sendReaction(to, messageId, emoji) | React to a message |
| sendLocation(to, location) | Send a location pin |
| sendContacts(to, contacts) | Send contact cards |
| uploadMedia(file, options) | Upload media, get MediaHandle |
| downloadMedia(mediaId) | Download media by ID |
| markAsRead(messageId) | Mark message as read |
Messenger
import { createMessengerClient } from '@ariaflowagents/messaging-meta/messenger';
const messenger = createMessengerClient({
pageAccessToken: process.env.MESSENGER_PAGE_ACCESS_TOKEN!,
appSecret: process.env.META_APP_SECRET!,
pageId: process.env.MESSENGER_PAGE_ID!,
verifyToken: process.env.MESSENGER_VERIFY_TOKEN!,
});
messenger.onMessage(async (msg) => {
await messenger.sendText(msg.from.id, `Echo: ${msg.text}`);
});Templates and Quick Replies
// Button template
await messenger.sendButtonTemplate(psid, {
text: 'What would you like to do?',
buttons: [{ type: 'postback', title: 'Track Order', payload: 'TRACK' }],
});
// Generic template (carousel)
await messenger.sendGenericTemplate(psid, {
elements: [{ title: 'Product A', subtitle: '$29.99', image_url: 'https://example.com/a.jpg' }],
});
// Quick replies
await messenger.sendQuickReplies(psid, 'Choose one:', [
{ content_type: 'text', title: 'Yes', payload: 'YES' },
{ content_type: 'text', title: 'No', payload: 'NO' },
]);Messenger-Specific Methods
| Method | Description |
|---|---|
| sendText(to, text) | Send text (max 2000 chars) |
| sendMedia(to, media) | Send image, video, audio, or file |
| sendButtonTemplate(to, template) | Send button template (max 3 buttons) |
| sendGenericTemplate(to, template) | Send carousel (max 10 elements) |
| sendQuickReplies(to, text, replies) | Send quick reply buttons |
| sendSenderAction(to, action) | Send typing_on, typing_off, mark_seen |
| getUserProfile(psid) | Fetch user's name and profile picture |
| uploadMedia(file, options) | Upload media for reuse |
| downloadMedia(mediaUrl) | Download media by URL |
import { createInstagramClient } from '@ariaflowagents/messaging-meta/instagram';
const instagram = createInstagramClient({
accessToken: process.env.INSTAGRAM_ACCESS_TOKEN!,
appSecret: process.env.META_APP_SECRET!,
igId: process.env.INSTAGRAM_ACCOUNT_ID!,
verifyToken: process.env.INSTAGRAM_VERIFY_TOKEN!,
});
instagram.onMessage(async (msg) => {
await instagram.sendText(msg.from.id, `Thanks for your message!`);
});Ice Breakers
// Set conversation starters
await instagram.iceBreakers.set([
{ question: 'What are your hours?', payload: 'HOURS' },
{ question: 'Track my order', payload: 'TRACK' },
]);
// Get current ice breakers
const breakers = await instagram.iceBreakers.get();
// Delete all
await instagram.iceBreakers.delete();Instagram-Specific Methods
| Method | Description |
|---|---|
| sendText(to, text) | Send text (auto-splits at 1000 bytes) |
| sendMedia(to, media) | Send image attachment only |
| sendQuickReplies(to, text, replies) | Send quick reply buttons (max 13) |
| sendGenericTemplate(to, template) | Send carousel template |
| sendButtonTemplate(to, template) | Send button template |
| sendPrivateReply(options) | Reply privately to a comment |
| sendTextWithTag(to, text, tag) | Send with message tag (e.g. HUMAN_AGENT) |
| iceBreakers.set(breakers) | Set conversation starters |
| iceBreakers.get() | Get current ice breakers |
| iceBreakers.delete() | Remove all ice breakers |
Standalone Webhook Utilities
For server-side webhook handling without the full client:
import { verifySignature, normalizeWebhook } from '@ariaflowagents/messaging-meta/server';
app.post('/webhook', async (c) => {
const rawBody = await c.req.text();
const sig = c.req.header('x-hub-signature-256') ?? '';
if (!verifySignature({ appSecret, rawBody, signatureHeader: sig })) {
return c.text('Invalid signature', 403);
}
const events = normalizeWebhook(JSON.parse(rawBody));
// events.messages, events.statuses, events.reactions
});Platform Comparison
| Feature | WhatsApp | Messenger | Instagram | |---|:---:|:---:|:---:| | Text limit | 4096 chars | 2000 chars | 1000 bytes | | Media types | all | all | image only | | Buttons / List / Carousel | 3 / yes / no | 3 / no / 10 | 3 / no / 10 | | Quick replies | no | 13 | 13 | | Templates | yes | yes | yes | | Typing + reactions | yes | yes | yes | | Message window | 24h | none | 7d (tag) | | Unique features | Flows, CTA, lists | Personas, profiles | Ice breakers, private reply |
AriaFlow Integration
Use with @ariaflowagents/messaging to connect clients to the AriaFlow runtime:
import { createMessagingRouter } from '@ariaflowagents/messaging';
const router = createMessagingRouter({ runtime, platforms: { whatsapp, messenger, instagram } });
app.route('/messaging', router);
// Webhooks: /messaging/{whatsapp,messenger,instagram}/webhookSubpath Exports
| Import path | Contents |
|---|---|
| @ariaflowagents/messaging-meta | GraphAPIClient, errors, webhook utilities |
| @ariaflowagents/messaging-meta/whatsapp | WhatsAppClient, templates, flows, format converter |
| @ariaflowagents/messaging-meta/messenger | MessengerClient, format converter |
| @ariaflowagents/messaging-meta/instagram | InstagramClient, ice breakers, format converter |
| @ariaflowagents/messaging-meta/server | verifySignature + normalizeWebhook only |
Related
@ariaflowagents/messaging-- Core interfaces and runtime adapter@ariaflowagents/core-- Runtime, agents, flows
