Channel adapters & their credentials

August 31, 2026 · View on GitHub

IronClaw delivers an agent's replies through channel adapters in internal/host/channels/. Each adapter implements a tiny interface (Name() + Deliver()) and talks to one platform. This page is the single reference for what each adapter needs to be configured.

Two things to know up front:

  • Secrets are host-only. Every token/password below is held by the control-plane and never enters a sandbox. Adapters redact their own credential from any error string, so a token can't leak into logs.
  • How an adapter is activated. Some adapters auto-register from environment variables when the control-plane starts (the daemon reads the var and registers the adapter if it's set). The rest are implemented and ready, but are wired programmatically / via the registry rather than from a single env var today — the "Auto-registered from env" column says which is which.

Reference

AdapterCredentials / config it needsAuto-registered from envWhere it comes from
SlackBot tokenSLACK_BOT_TOKENA Slack app → OAuth & PermissionsBot User OAuth Token (xoxb-…); needs the chat:write scope.
DiscordBot tokenDISCORD_BOT_TOKENDiscord Developer Portal → your app → BotToken; invite the bot to the server with the Send Messages permission.
TelegramBot tokenTELEGRAM_BOT_TOKENTalk to @BotFather/newbot → the HTTP API token.
Microsoft TeamsIncoming Webhook URLIRONCLAW_TEAMS_WEBHOOK_URLA Teams channel → Connectors / WorkflowsIncoming Webhook → copy the generated URL.
Signalsignal-cli REST base URL + sender numberIRONCLAW_SIGNAL_CLI_URL, IRONCLAW_SIGNAL_NUMBERRun signal-cli-rest-api and register the sender number; point the URL at it (e.g. http://127.0.0.1:8080).
iMessage(none — macOS Messages bridge)IRONCLAW_IMESSAGE_ENABLE=1 (macOS host only)Runs on a macOS host signed in to Messages; no token. Enabled only when the var is 1 and GOOS=darwin.
RocketChatServer URL + Auth Token + User ID + ChannelIRONCLAW_ROCKETCHAT_URL, IRONCLAW_ROCKETCHAT_USER_ID, IRONCLAW_ROCKETCHAT_AUTH_TOKEN, IRONCLAW_ROCKETCHAT_CHANNELRocket.Chat → AccountPersonal Access TokensNew Token; get the Token and your User ID (X-User-Id). Set the base URL to your server.
WebhookA POST URL(wired explicitly)Any HTTPS endpoint that accepts a JSON POST of the outbound message — your own service, an automation platform, etc.
WhatsAppCloud API access token + phone-number id(wired explicitly)Meta for Developers → WhatsApp Cloud API: a system-user access token and the sender's phone-number id.
Email / SMTPSMTP host, port (default 587), username, password, from-address(wired explicitly)Any SMTP submission server (PLAIN auth over STARTTLS) — e.g. smtp.gmail.com:587 with an app password.
MatrixHomeserver URL + access token(wired explicitly)Your Matrix account: the homeserver base URL (e.g. https://matrix.example.org) and an access token for the bot user.
Google ChatOAuth2 / service-account access token(wired explicitly)A Google Cloud service account with the Chat API enabled; the adapter sends the bearer access token.
MattermostIncoming Webhook URLIRONCLAW_MATTERMOST_WEBHOOK_URLA Mattermost Incoming Webhook URL for the target channel. The adapter posts outbound messages as {"text":"..."} using the standard webhook endpoint.

The in-product web chat playground (webchat) is registered automatically and needs no credential — it's the browser-based chat surface, not an external platform.

Configuring an auto-registered adapter

Set the variable in the control-plane's environment (or in .env when running with Docker Compose), then start the daemon:

export DISCORD_BOT_TOKEN=...      # registers the Discord adapter on boot
# the daemon logs: channel adapter registered  adapter=discord

Then wire it to an agent group with the registry — see examples/ for runnable templates and the CLI reference for ironctl registry.

Adding a new adapter

Want a platform that isn't here yet? See Writing a channel adapter for the interface, the house pattern (stdlib HTTP, test-overridable BaseURL, secret redaction, threading), and the test pattern.