The message router handles formatting messages for agents and routing outbound messages to the correct channel.
Core functions
escapeXml
Escapes special XML characters in strings.
function escapeXml(s: string): string
XML-escaped string with &, <, >, and " replaced with entities
Example:
import { escapeXml } from './router.js';
const escaped = escapeXml('Hello <world> & "friends"');
// 'Hello <world> & "friends"'
Formats an array of messages as XML for agent consumption.
function formatMessages(messages: NewMessage[]): string
Array of messages to format
XML-formatted messages wrapped in <messages> tags
Message format:
<messages>
<message sender="John Doe" time="2026-02-28T12:34:56.789Z">Hello!</message>
<message sender="Jane Smith" time="2026-02-28T12:35:01.234Z">Hi there!</message>
</messages>
Example:
import { formatMessages } from './router.js';
const messages = [
{
id: '1',
chat_jid: '[email protected]',
sender: '[email protected]',
sender_name: 'John',
content: 'Hello!',
timestamp: '2026-02-28T12:34:56.789Z',
},
];
const formatted = formatMessages(messages);
Removes <internal>...</internal> blocks from agent output.
function stripInternalTags(text: string): string
Text containing potential <internal> tags
Text with all <internal> blocks removed and trimmed
Purpose:
Agents use <internal> tags for internal reasoning that should not be shown to users.
Example:
import { stripInternalTags } from './router.js';
const raw = `<internal>Analyzing request...</internal>Here's your answer!`;
const clean = stripInternalTags(raw);
// "Here's your answer!"
Prepares agent output for sending to users (strips internal tags).
function formatOutbound(rawText: string): string
Cleaned text ready for user display (empty string if no content after stripping)
Example:
import { formatOutbound } from './router.js';
const raw = `<internal>Debug info</internal>Response to user`;
const outbound = formatOutbound(raw);
// "Response to user"
routeOutbound
Routes a message to the appropriate channel.
function routeOutbound(
channels: Channel[],
jid: string,
text: string,
): Promise<void>
Array of available channels
Throws: Error if no connected channel owns the JID
Example:
import { routeOutbound } from './router.js';
await routeOutbound(channels, '[email protected]', 'Hello!');
findChannel
Finds the channel that owns a given JID.
function findChannel(
channels: Channel[],
jid: string,
): Channel | undefined
Array of available channels
Channel that owns the JID, or undefined if none found
Example:
import { findChannel } from './router.js';
const channel = findChannel(channels, '[email protected]');
if (channel) {
await channel.sendMessage('[email protected]', 'Hello!');
}
Types
NewMessage
interface NewMessage {
id: string; // Unique message ID
chat_jid: string; // Chat identifier (e.g., "[email protected]")
sender: string; // Sender JID (e.g., "[email protected]")
sender_name: string; // Display name
content: string; // Message text
timestamp: string; // ISO 8601 timestamp
is_from_me?: boolean; // Whether sent by the bot
is_bot_message?: boolean; // Whether this is a bot message
}
Channel
interface Channel {
name: string;
connect(): Promise<void>;
sendMessage(jid: string, text: string): Promise<void>;
isConnected(): boolean;
ownsJid(jid: string): boolean;
disconnect(): Promise<void>;
setTyping?(jid: string, isTyping: boolean): Promise<void>; // Optional
}