Aleph
Gateway RPCMethods Reference

channels.*

Communication channel management RPC methods

channels.* is the runtime surface over the ChannelRegistry. Methods are registered in two passes:

  • register_channel_handlers (src/bin/aleph-server/commands/start/builder/handlers/session.rs:202-303) — the core lifecycle methods (channels.list/status, channel.start/stop/pairing_data/send/create/delete/health, channels.dead_letters, channels.redrive_dead_letters, channels.set_agent).
  • start/mod.rs:2431-2466 — the channel-pairing methods (channel.pairing.list/approve/reject/approved/revoke).
  • The Discord Control-Plane panel methods (discord.validate_token, discord.list_guilds, discord.list_channels, discord.audit_permissions) are registered next to the other channel handlers.

The same registry backs all of these. Configured-but-not-yet-instantiated channels (e.g. a Telegram channel that exists in ~/.aleph/config.toml but is missing bot_token) show up as pending_config in channels.list.

Methods

channels.list

List every registered channel plus the configured-but-not-instantiated set. Also surfaces the durable outbound-delivery queue depth (R8) so an operator can spot a backlog.

Request: no params.

Response: { "channels": [ ...ChannelInfoResponse... ], "summary": { "total", "connected", "connecting", "pairing", "disconnected", "error", "disabled" }, "delivery_queue" | null }. Each ChannelInfoResponse carries id, name, channel_type, status, and a capabilities block (attachments, images, audio, video, reactions, replies, editing, deletion, typing_indicator, read_receipts, rich_text, max_message_length, max_attachment_size). pending_config channels carry empty capabilities.

channels.status

Live status of a single channel (overrides the stored status with the live ChannelStatus).

ParameterTypeRequiredDescription
channel_idstringyesChannel id

Response: the ChannelInfoResponse for that channel. INVALID_PARAMS: Channel not found: <id> when unknown.

channel.start

Start a channel. Re-reads the channel's config from ~/.aleph/config.toml (so a Panel save takes effect without a server restart) and re-injects vault-resolved secrets into the config before constructing the channel. Telegram channels have their ToolCatalog re-attached so slash commands are registered.

ParameterTypeRequiredDescription
channel_idstringyesChannel id

Response: { "channel_id", "status": "started" }.

channel.stop

Stop a channel.

ParameterTypeRequiredDescription
channel_idstringyesChannel id

Response: { "channel_id", "status": "stopped" }.

channel.create

Create a new channel instance, persist its config (with secrets stripped to the vault), register, and auto-start. If the config is incomplete (e.g. missing bot_token) the request still succeeds with status: "pending_config" so the user can fill in the missing fields via the Panel.

ParameterTypeRequiredDescription
idstringyesUnique channel id
typestringyestelegram / discord / slack / imessage (BlueBubbles) / …
configobjectyesType-specific config; secret fields (bot_token, app_token, app_secret, access_token, …) are stored in the vault (channel:<id>:<field>) and stripped from the persisted config

Response: { "id", "type", "status" } with status: "started" | "created_but_start_failed" | "pending_config".

channel.delete

Stop a channel (if running) and remove it from both the registry and the persisted config.

ParameterTypeRequiredDescription
idstringyesChannel id

Response: { "id", "status": "deleted" }. Refuses to delete a channel that exists in neither the registry nor the config.

channel.send

Send a message through a channel.

ParameterTypeRequiredDescription
channel_idstringyesChannel id
tostringyesConversation id (channel-specific target: chat id, channel id, user id, …)
textstringyesMessage body (non-empty)

Response: { "channel_id", "message_id", "timestamp", "sent": true }.

channel.pairing_data

Fetch the pairing data (QR code, code, or deep link) for a channel that supports it.

ParameterTypeRequiredDescription
channel_idstringyesChannel id

Response: the channel's pairing payload (shape is channel-defined).

channel.health

Read the channel-health monitor for one channel (or every channel, summarised).

ParameterTypeRequiredDescription
channel_idstringnoOmitted ⇒ every channel's health + a fleet summary

Response (one channel): the ChannelHealthResponse for that channel (id, channel_type, status, health_status (healthy / stale / degraded), last_event_at, failure_count, status_reason?).

Response (all): { "channels": [ ...ChannelHealthResponse... ], "summary": { "total", "healthy", "stale", "degraded" } }.

channels.dead_letters

Detail-on-demand companion to the dead_lettered count in channels.list. Lists the outbound deliveries that exhausted their retry budget.

ParameterTypeRequiredDescription
limitnumbernoDefaults to 50, capped at 500

Response: { "dead_letters": [ ...{channel, to, text_preview (≤ 200 chars), attachments, attempts, last_error, created_at, died_at, age_secs}... ], "count" }. { "dead_letters": [], "count": 0, "store": false } when no durable delivery store is attached.

channels.redrive_dead_letters

Recovery half of the dead-letter trail. Moves dead-lettered deliveries back into the live outbound queue for another delivery pass once the transport is healthy. Safe by construction — every dead letter was a duplicate-safe transient failure.

ParameterTypeRequiredDescription
channelstringnoRestrict the redrive to one transport

Response: { "redriven": N } on success. { "redriven": 0, "store": false } when no durable store is attached.

channels.set_agent

Bind or unbind an agent to a channel. Delegates to the shared binding seam (gateway::agent_binding) — the same implementation behind the agent_switch tool — so both surfaces share ghost validation, no-op detection, and Bound / Unbound events. Must specify an existing agent (the previous lenient behaviour was removed: 26.7.15+).

ParameterTypeRequiredDescription
channel_idstringyesChannel id
agent_idstringnoAgent id; null / absent unbinds

Response (bind): { "ok", "previous_agent" | null, "no_op": false } on a fresh bind; { "ok", "previous_agent", "no_op": true } on a no-op rebind.

Response (unbind): { "ok", "previous_agent" | null }.

INVALID_PARAMS when the agent_id does not exist in the live AgentRegistry. A minimal server with agent_registry: None skips the validation.

agents.bindings

Get every channel bound to each agent, sorted by channel id. The previous one-channel-per-agent map was lossy; the current response shape is { "bindings": { "<agent_id>": [ "<channel>", … ] } } and surfaces every channel bound to an agent.

Request: no params.

Response: { "bindings": { "agent-1": [ "discord", "telegram" ], … } }.

Channel pairing

Channels that support unknown-sender approval (Telegram, iMessage BlueBubbles) keep a per-channel pairing store. The same store backs the inbound router's auto-approve and the Panel's manual UI; the RPCs below are the manual UI.

MethodParametersDescription
channel.pairing.listchannel?{ "requests": [ ...PairingRequest... ], "count" }; optional channel filter. Each PairingRequest carries channel, sender_id, code, created_at.
channel.pairing.approvechannel (required), code (required){ "approved": true, "request": PairingRequest }
channel.pairing.rejectchannel (required), code (required){ "rejected": true, "channel", "code" }
channel.pairing.approvedchannel (required){ "channel", "approved": [ ...sender_id... ], "count" }
channel.pairing.revokechannel (required), sender_id (required){ "revoked": true, "channel", "sender_id" }

Discord Control-Plane panel

Four methods are registered for the Discord Control-Plane panel inside the Discord modal flow:

MethodDescription
discord.validate_tokenValidate a Discord bot token (no persistence)
discord.list_guildsList the guilds the bot is in
discord.list_channelsList the channels of a guild
discord.audit_permissionsAudit a guild's permission set against the operator's intent

These methods require a live ChannelRegistry and are always present; they do not depend on a connected channel state.

Channel type → secret field map

channel.create accepts the secret fields named below. Each is stored under channel:<id>:<field> in the vault and stripped from the persisted config.

Channel familySecret fields
telegrambot_token
discordbot_token
slackbot_token, app_token
feishuapp_secret
msteamsapp_password
matrixaccess_token
xmpp / irc / emailpassword
nostrprivate_key
webhooksecret
whatsappsession_data
qqclient_secret

A configured field is also surfaced as has_<field>: true on channels.list (and on the Settings page) — the editable input always starts empty, and a save with an empty value means "keep the existing vault value".

See Also

On this page