@ariaflowagents/messaging
v0.8.1
Published
Core interfaces and AriaFlow adapter for messaging platforms
Readme
@ariaflowagents/messaging
Core interfaces and Hono adapter for connecting messaging platforms to the AriaFlow runtime.
Install
npm install @ariaflowagents/messagingQuick Start
import { Hono } from 'hono';
import { Runtime } from '@ariaflowagents/core';
import { createMessagingRouter } from '@ariaflowagents/messaging';
import { 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!,
});
const runtime = new Runtime({ agents: [/* ... */], defaultAgentId: 'support' });
const router = createMessagingRouter({
runtime,
platforms: { whatsapp },
});
const app = new Hono();
app.route('/messaging', router);
// Webhook URL: POST /messaging/whatsapp/webhookCore Concepts
PlatformClient-- The interface every vendor package implements. Normalizes sending, receiving, media, webhooks, and format conversion into a single contract.SessionResolver-- Maps inbound messages to AriaFlow sessions. Default:{platform}:{threadId}.ResponseMapper-- Controls how runtime stream output is sent to the platform. Default sends accumulated text and renders suggested questions as interactive buttons.StreamMapper-- ConsumesAsyncIterable<HarnessStreamPart>, sends typing indicators during streaming, delegates final output to aResponseMapper.
Error Handling
All errors extend MessagingError with a machine-readable code and platform field.
| Class | Code | When |
|---|---|---|
| RateLimitError | RATE_LIMIT | Platform rate limit exceeded. Carries retryAfterMs. |
| WindowClosedError | WINDOW_CLOSED | 24h messaging window expired. Carries suggestedTemplates. |
| AuthenticationError | AUTH_FAILED | Invalid or expired API token. |
| PermissionError | PERMISSION_DENIED | Token lacks required permissions. |
| RecipientError | RECIPIENT_ERROR | Recipient invalid, blocked, or unreachable. |
| TemplateError | TEMPLATE_ERROR | Template message invalid or not approved. |
| MediaError | MEDIA_ERROR | Media upload/download/format failure. |
| WebhookVerificationError | WEBHOOK_VERIFICATION_FAILED | Webhook signature check failed. |
import { RateLimitError, WindowClosedError } from '@ariaflowagents/messaging';
try {
await client.sendText(to, text);
} catch (e) {
if (e instanceof RateLimitError) {
await sleep(e.retryAfterMs);
}
if (e instanceof WindowClosedError) {
// Send a template message instead
}
}Shared Utilities
MessageDeduplicator
LRU cache that prevents duplicate webhook processing. Used automatically by createMessagingRouter.
import { MessageDeduplicator } from '@ariaflowagents/messaging';
const dedup = new MessageDeduplicator(10_000, 300_000); // maxSize, ttlMs
if (dedup.isDuplicate(messageId)) return;WindowTracker
Tracks 24-hour messaging windows per thread. Updated automatically from inbound messages and status webhooks.
import { WindowTracker } from '@ariaflowagents/messaging';
const tracker = new WindowTracker();
tracker.recordInbound(threadId, new Date());
tracker.isWindowOpen(threadId); // true (within 24h)Custom Session Resolver
import { createMessagingRouter } from '@ariaflowagents/messaging';
import type { SessionResolver } from '@ariaflowagents/messaging';
const resolver: SessionResolver = {
async resolve(message) {
const userId = await lookupUser(message.from.phone);
return { sessionId: `user:${userId}`, userId };
},
};
const router = createMessagingRouter({
runtime,
platforms: { whatsapp },
sessionResolver: resolver,
});Custom Response Mapper
import { createMessagingRouter } from '@ariaflowagents/messaging';
import type { ResponseMapper, ResponseContext } from '@ariaflowagents/messaging';
import type { HarnessStreamPart } from '@ariaflowagents/core';
const mapper: ResponseMapper = {
async mapResponse(parts: HarnessStreamPart[], ctx: ResponseContext) {
const text = parts
.filter((p) => p.type === 'text-delta')
.map((p) => p.text)
.join('');
// Split long responses into multiple messages
for (const chunk of splitIntoChunks(text, 4096)) {
await ctx.sendText(chunk);
}
},
};
const router = createMessagingRouter({
runtime,
platforms: { whatsapp },
responseMapper: mapper,
});Multi-Platform
Pass multiple clients to platforms. Add onStatus, onError, and fallbackMessage for production use:
const router = createMessagingRouter({
runtime,
platforms: { whatsapp, messenger, instagram },
onStatus: (status) => console.log(`${status.status}: ${status.messageId}`),
onError: (err, ctx) => console.error(`[${ctx.platform}]`, err.message),
fallbackMessage: 'Something went wrong. Please try again later.',
});Related
@ariaflowagents/messaging-meta-- WhatsApp, Messenger, and Instagram clients@ariaflowagents/core-- Runtime, agents, flows
