IRC Integration Setup, Access Controls, and Troubleshooting

Set up the official IRC plugin for OpenClaw, configure host, nick, and channels, and apply access controls. Includes troubleshooting and durability details for IRC bot operators.

Read this when

  • You want to connect OpenClaw to IRC channels or DMs
  • You are configuring IRC allowlists, group policy, or mention gating

When you need OpenClaw to work inside traditional IRC channels (#room) and direct messages, use the IRC integration. First install the official IRC plugin, then set it up under channels.irc.

Quick start

  1. Add the plugin:
openclaw plugins install @openclaw/irc
  1. In ~/.openclaw/openclaw.json, configure at minimum the host, the nick, and which channels to join:
{
  channels: {
    irc: {
      enabled: true,
      host: "irc.example.com",
      port: 6697,
      tls: true,
      nick: "openclaw-bot",
      channels: ["#openclaw"],
    },
  },
}
  1. Check that the channel is working:
openclaw channels status --probe

Configuration updates take effect through hot reload. Should the Gateway be down, launch it with openclaw gateway run.

Running a private IRC server is the better choice for bot coordination. If you deliberately connect to a public IRC network, Libera.Chat, OFTC, and Snoonet are among the usual options. For bot or swarm backchannel traffic, steer clear of public channels whose names are easy to guess.

Inbound durability

Every accepted IRC PRIVMSG is written by OpenClaw into its durable ingress queue, ahead of the normal policy checks and agent dispatch. Messages that are pending or retryable make it through a Gateway restart and stay serialized per channel or per direct-message peer.

IRC offers no replayable delivery ID, and it will not resend messages a disconnected client missed. Because of that, OpenClaw creates a local ID that holds stable only for the current TCP connection. What the queue covers is the local window between accept and dispatch. It cannot bring back a message that never arrived at OpenClaw, nor can it deduplicate a server resend that spans connections.

Connection settings

KeyDefaultNotes
hostnone (required)IRC server hostname
port6697 with TLS, 6667 plain1-65535
tlstrueSet false only for intentional plaintext
nicknone (required)Bot nick
usernamenick, else openclawIRC username
realnameOpenClawRealname/GECOS field
password / passwordFilenoneServer password; file must be a regular file
channelsnoneChannels to join (["#openclaw"])
replyToModeallReply-reference mode: off, first, all, or batched
accounts / defaultAccountnoneMulti-account setup; env vars fill only the default account

The channel-wide reply mode is inherited by named accounts; use channels.irc.accounts.<id>.replyToMode to override it.

Under the default hybrid reload mode, a non-default named account that is added or edited causes only that IRC account to restart. Connections for other accounts keep going, the Gateway keeps running, and accounts you stopped by hand remain stopped. When shared IRC settings, accounts.default, or account removal are involved, the entire IRC channel restarts, since inheritance or account selection can be affected.

Before an account restart closes its ingress queue, it finishes the message admissions it has already accepted; the replacement monitor then pulls pending channel messages back out of that same queue. Anything missed during the disconnect is unrecoverable, and pending DMs left over from a previous connection get dropped, because IRC nicknames can be taken over by someone else.

Outbound text

Markdown goes out over IRC as plain text, with code contents and link destinations kept intact. Before a long reply is split into IRC messages, it is rendered, so code fences and inline formatting stay consistent even when they cross a chunk boundary. Text splitting is governed by textChunkLimit and streaming.chunkMode; the socket additionally applies IRC's line-size limit.

Should nonempty text end up empty after formatting or IRC sanitization, the send fails rather than being reported as delivered. Message content does not include reply references.

To send straight to a channel or nick, use the message CLI:

openclaw message send --channel irc --target '#openclaw' --message 'Hello from OpenClaw'

Security defaults

  • IRC opens raw TCP/TLS sockets, which sit outside OpenClaw's operator-managed forward proxy routing. Where a deployment demands that all egress pass through that forward proxy, configure channels.irc.enabled=false unless direct IRC egress has been explicitly approved.
  • channels.irc.dmPolicy ships with a default of "pairing": a DM from an unknown sender receives a pairing code that you approve using openclaw pairing approve irc <code>.
  • channels.irc.groupPolicy ships with a default of "allowlist".
  • When groupPolicy="allowlist" is in use, define the allowed channels by setting channels.irc.groups.
  • Unless you knowingly accept plaintext transport, use TLS (channels.irc.tls=true).

Access control

IRC channels have two distinct "gates":

  1. Channel access (groupPolicy + groups): whether the bot accepts messages from a channel at all.
  2. Sender access (groupAllowFrom / per-channel groups["#channel"].allowFrom): who is allowed to trigger the bot inside that channel.

Config keys:

  • DM allowlist (who may send DMs): channels.irc.allowFrom
  • Group sender allowlist (who may post in channels): channels.irc.groupAllowFrom
  • Per-channel controls (channel + sender + mention rules): channels.irc.groups["#channel"] with requireMention, allowFrom, enabled, tools, toolsBySender, skills, and systemPrompt
  • channels.irc.groupPolicy="open" permits channels that have no configuration (mention gating still applies by default)

Entries in an allowlist ought to be based on stable sender identities (nick!user@host). Matching on a bare nick can change over time and works only when channels.irc.dangerouslyAllowNameMatching: true is on.

Common gotcha: allowFrom is for DMs, not channels

Should your logs contain lines such as:

  • irc: drop group sender alice!ident@host (policy=allowlist)

...then the sender was not permitted for group/channel messages. Two ways to fix it:

  • set channels.irc.groupAllowFrom (applies to every channel), or
  • configure sender allowlists per channel: channels.irc.groups["#channel"].allowFrom

Example (let anyone in #openclaw talk to the bot):

{
  channels: {
    irc: {
      groupPolicy: "allowlist",
      groups: {
        "#openclaw": { allowFrom: ["*"] },
      },
    },
  },
}

Reply triggering (mentions)

A channel can be permitted (through groupPolicy + groups) and the sender can be permitted too, yet OpenClaw still applies mention gating in group contexts by default. The bot is treated as mentioned whenever the message includes the connected bot nick or matches the mention patterns you configured.

As a result, logs like drop channel … (missing-mention) can appear unless the message carries a mention pattern that matches the bot.

To have the bot respond in an IRC channel with no mention required, turn off mention gating for that channel:

{
  channels: {
    irc: {
      groupPolicy: "allowlist",
      groups: {
        "#openclaw": {
          requireMention: false,
          allowFrom: ["*"],
        },
      },
    },
  },
}

Alternatively, permit every IRC channel (no per-channel allowlist) while still replying without mentions:

{
  channels: {
    irc: {
      groupPolicy: "open",
      groups: {
        "*": { requireMention: false, allowFrom: ["*"] },
      },
    },
  },
}

Security note (recommended for public channels)

Permitting allowFrom: ["*"] in a public channel means any user can prompt the bot. Limit the tools available in that channel to lower the risk.

Same tools for everyone in the channel

{
  channels: {
    irc: {
      groups: {
        "#openclaw": {
          allowFrom: ["*"],
          tools: {
            deny: ["group:runtime", "group:fs", "gateway", "nodes", "cron", "browser"],
          },
        },
      },
    },
  },
}

Different tools per sender (owner gets more power)

Apply a tighter policy to "*" and a more permissive one to your own nick by using toolsBySender:

{
  channels: {
    irc: {
      groups: {
        "#openclaw": {
          allowFrom: ["*"],
          toolsBySender: {
            "*": {
              deny: ["group:runtime", "group:fs", "gateway", "nodes", "cron", "browser"],
            },
            "id:alice": {
              deny: ["gateway", "nodes", "cron"],
            },
          },
        },
      },
    },
  },
}

Notes:

  • Keys for toolsBySender should carry explicit prefixes (channel:, id:, e164:, username:, name:). For IRC, pair id: with the sender identity value: id:alice or id:alice!~alice@203.0.113.7 for stronger matching.
  • Unprefixed legacy keys remain valid, are matched as id: only, and trigger a deprecation warning.
  • Whichever sender policy matches first takes effect; "*" serves as the wildcard fallback.

For details on group access versus mention gating (and how the two interact), see: /channels/groups.

NickServ

To authenticate with NickServ once connected:

{
  channels: {
    irc: {
      nickserv: {
        enabled: true,
        service: "NickServ",
        password: "your-nickserv-password",
      },
    },
  },
}

Whenever a password is set, NickServ identify runs by default (to opt out, enabled only has to be false). service defaults to NickServ; instead of inline password, passwordFile is an option.

Optional one-time registration at connect time (register: true needs registerEmail):

{
  channels: {
    irc: {
      nickserv: {
        register: true,
        registerEmail: "bot@example.com",
      },
    },
  },
}

Once the nick is registered, turn off register so REGISTER is not attempted over and over.

Environment variables

The default account supports:

  • IRC_HOST
  • IRC_PORT
  • IRC_TLS
  • IRC_NICK
  • IRC_USERNAME
  • IRC_REALNAME
  • IRC_PASSWORD
  • IRC_CHANNELS (comma-separated)
  • IRC_NICKSERV_PASSWORD
  • IRC_NICKSERV_REGISTER_EMAIL

A workspace .env cannot be used to set IRC_HOST; refer to Workspace .env files.

Troubleshooting

  • When the bot joins but stays silent in channels, check channels.irc.groups and confirm that mention-gating is not discarding messages (missing-mention). To have it answer without being pinged, configure requireMention:false for that channel.
  • When login does not succeed, check that the nick is free and confirm the server password.
  • When TLS breaks on a custom network, check the host/port values and the certificate configuration.
1,568 words · updated Sep 18, 2026