Skip to content

Channels

Channels are how a mono-agent receives input and delivers replies. Core channels use independent JSON sections in mono-agent.config.json; external channel packages are declared under channels.plugins[] and return the same ChannelDriver shape. Most channels opt in through their own enabled flag; the loopback operator endpoint retains the compatibility config id tui, defaults on, and can be disabled explicitly. @mono-agent/app composes the resolved drivers into the running host. This page explains the shared lifecycle, how to pick a channel, and links to every per-channel guide. Coverage: config unless a feature is noted otherwise.

ChannelTransportSectionGuide
TelegramBot long pollingtelegramTelegram
SlackSocket Mode botslackSlack
WebhookHTTP POST, sync or asyncwebhookWebhook
OpenAI-compatible API/v1/chat/completions (SSE)openaiApiOpenAI-compatible API
CronScheduled promptscronCron
Operator stream endpointLoopback NDJSON turns for mono-agent web, ACP, and jobs clientstuiOperator stream endpoint
ChannelTransportPlugin packageGuide
WhatsAppBaileys socket (QR login)@mono-agent/channel-whatsappWhatsApp
Facebook MessengerMeta webhook + Send API@mono-agent/channel-messengerMessenger
A2AAgent-to-Agent provider/consumer@mono-agent/channel-a2aA2A

Channels are fully independent: enabling one neither requires nor affects another, and a misconfigured channel never blocks the rest of the host from starting.

Most channels default to off. The deliberate exception is the tui operator stream endpoint, which defaults to on (loopback-only, ephemeral port, so the web console can chat without a config edit). Set "tui": {"enabled": false} to opt out. You turn other channels on with enabled: true and supply their required settings; external channels also need a channels.plugins[] entry naming the package. Human status output groups communication channels separately from the operator transport, labels the stable tui id as gui (Web Console), and folds disabled ids into one compact line. JSON retains stable ids and full reasons. Active entries reflect one of five states:

StateMeaning
disabledThe resolved enabled value is false. Omission resolves false for most channels, but tui defaults true and requires an explicit false to reach this state.
waiting_for_configenabled: true but a required setting is missing — the line names the exact missing field.
runningReady and listening; the line includes endpoint facts (host/port/path, or the bot it connected as).
degradedWas running but the live transport connection dropped on a transient failure (e.g. a Telegram poll crash on a network switch, or a Slack Socket Mode disconnect); the responder/harness is kept alive and the adapter is reconnecting, so the channel keeps serving. Rendered degraded: <reason> with a warning badge. Non-fatal and self-recovering — it returns to running automatically once the transport stays up, unlike failed.
failedThe channel errored on startup; the line includes the reason.
{
"telegram": {
"enabled": true,
"allowedChatIds": ["123456789"]
}
}

Put MONO_AGENT_TELEGRAM_BOT_TOKEN=... in the agent’s .env; source-config examples omit credentials even though inline fields remain accepted for compatibility.

Fields with a documented mapping can also be set with a MONO_AGENT_<CHANNEL>_* environment variable, which is especially useful for secrets you do not want in the JSON file. Some fields are JSON-only. A .env in the agent folder is loaded automatically (exported shell variables win); use --env-file <path> for an alternate file. Per-channel env var names are listed in each channel’s guide. See Environment variables for the complete mapping.

Terminal window
export MONO_AGENT_TELEGRAM_ENABLED=true
export MONO_AGENT_TELEGRAM_BOT_TOKEN=REPLACE_WITH_BOT_TOKEN

Pick by who or what is on the other end:

You want…UseWhy
A human chatting interactivelyTelegram, Slack, WhatsApp, or MessengerConversational adapters with allowlists, working indicators, and final-answer delivery; WhatsApp and Messenger are loaded as external plugins
Programmatic / pipeline invocationWebhook or A2AWebhook for plain HTTP POST (sync or async polling); A2A for agent-to-agent calls with Agent Card discovery and is loaded as an external plugin
A chat UI (e.g. Open WebUI)OpenAI-compatible APIExposes /v1/models + /v1/chat/completions with token-by-token SSE streaming
A first-party operator consoleWeb consoleConnects through the loopback operator endpoint while keeping transport details out of user-facing chat
Scheduled / unattended runsCronTimezone-aware five-field jobs that invoke the responder on a schedule

You can enable any combination — for example Telegram for your own use plus a webhook for automation and cron for a daily digest.

The app builds one runtime harness per channel, and each harness holds its own concurrency limiter. The concurrency.* bounds therefore apply to each channel independently, not as a single global cap: with N enabled channels the effective ceiling is N× the configured value. See Sessions & concurrency for maxConcurrentRuns / maxPendingRuns and the admission model.

Replies go back over the same channel that received the request. To send outbound messages — proactive notifications from cron/webhook turns, or app-owned send tools like SlackSendMessage and TelegramSendMessage — see Delivery & send tools. Note that these send tools require the target adapter to already be enabled and configured, and the adapter’s own allowlist remains the delivery boundary.

For a bespoke transport, implement a ChannelDriver from @mono-agent/contracts and either expose it from a package loaded by channels.plugins[] or pass it via startMonoAgentApp({ drivers }). See Write your own channel adapter.