Skip to main content

Messaging Orchestrator

One config file runs every channel. Each gateway starts with shared middleware and routes into the same agent and session layer, so a customer gets the same agent whether they arrive on WhatsApp or Slack.

Shape of the config

allowApply: false is the default and should stay false until you’ve watched the agent on real traffic. It’s the same read-only-by-default posture as the CLI safety model — a channel agent that can’t write can’t get a write wrong.

Middleware

Applied across all channels, so you configure protection once rather than per gateway:
The rate limiter is per-channel protection against a spam flood, and also a cost control — every inbound message that reaches the agent costs model tokens. maxPerHour is the ceiling on what a single abusive sender can spend.

Notification routing

Route engine events outward to the channels that should see them:
One event can fan out to several channels. The "*" route catches everything not matched above — useful as a safety net while you learn which events matter.
Route approvals:request:created somewhere a human actually watches. That event is the review gate asking for a decision — if nobody sees it, the action waits indefinitely.

Channels

Supported: WhatsApp, Telegram, Slack, Discord, Signal, Google Chat.
An empty allowList on Telegram means anyone who finds the bot can talk to it. Set it while testing, and rely on the rate limiter and content filter once it’s open.
Secrets come from environment variables via ${VAR} interpolation — keep them out of the YAML.

Where messages go

All channels feed the same session layer, so conversation state persists per user across turns and, with persistSessions: true, across restarts. That’s what lets a handoff work: a conversation escalated to a human keeps its history.