🏠 Home ← Docs Index
Open Beta πŸ“– Interactive Reader Raw .md llms.txt

Discord Bot Setup

All user, server, channel and role IDs below are synthetic. Replace them with your own IDs.

GoClaw provides full support for Discord, including direct messages, guild channels, slash commands, and file processing.


Quick Setup

1. Create a Discord Application and Bot

  1. Go to the Discord Developer Portal and click New Application.
  2. Name your application and agree to the terms.
  3. Click Bot on the sidebar.
  4. Set the bot Username and (optionally) an icon.

2. Enable Privileged Intents

GoClaw requires specific intents to see and process messages. On the Bot page, scroll down to Privileged Gateway Intents and enable:

3. Copy Your Bot Token

On the Bot page, click Reset Token. Copy and save the token securely. You will need it for the GoClaw configuration.

4. Generate an Invite URL

Click OAuth2 on the sidebar, then URL Generator. Enable:

Copy the generated URL and open it in your browser to add the bot to your server.

5. Enable Developer Mode

In your Discord client: User Settings β†’ Advanced β†’ toggle on Developer Mode. This allows you to right-click on users, roles, or channels to copy their IDs β€” needed for allowlists and per-guild configuration.

6. Configure GoClaw

Edit your ~/.goclaw/config.yaml to include the Discord section:

channels:
  discord:
    enabled: true
    token: "YOUR_BOT_TOKEN"

To keep the token out of the file, use a reference: token: "${DISCORD_BOT_TOKEN}" reads the environment variable, and token: "${secret:DISCORD_BOT_TOKEN}" reads the encrypted vault. GoClaw does not read DISCORD_BOT_TOKEN by itself; the channel starts only when enabled is true and token is set.

7. Start and Pair

Start GoClaw and send a DM to your bot. If dm_policy is set to pairing (the default), it will respond with a pairing code.

Approve the request on the Web UI (Pairing tab). The CLI works too, but a running gateway does not see a CLI approval until it restarts β€” see Pairing:

./goclaw pairing approve <CODE>

Runtime Behavior

Message Handling

Slash Commands

GoClaw automatically registers several slash commands:

Command Description
/ask <question> Ask the agent a question using a deferred reply (bypasses Discord's 3-second timeout). The question goes into your own conversation with the bot in that channel, the one your messages there are in.
/memory [show|clear] Sends the agent the message "Show me my memory contents. Action: show" (or clear) and posts its answer. The command itself clears nothing.
/status Replies with a fixed line: "GoClaw is running. Use the web UI for detailed stats."

Slash commands do not need an @mention. In a server they follow the same guild and channel settings as messages: a channel set to allow: false, or a member not on the users/roles allowlist, gets a private "You cannot use this bot in this channel." and the agent is not asked. In a DM, the DM policy (pairing) applies as it does to messages.

Text Attachments

Discord file attachments with text-readable MIME types (e.g., .md, .txt, .json, .py, .go, .js, .ts, .sql, .csv, .yaml, .xml) are automatically downloaded and included in the message context. Only the first 256 KB of a text file is included.

Binary files (images, audio, PDFs) are saved to workspace/uploads/ and the agent is given the local path to process them.

A text file larger than 10 MB, or a binary file larger than 50 MB, is not read; the agent is told it was attached and could not be read, and the rest of the message is still answered.

Typing Indicator

A typing indicator is shown while the agent processes the message, refreshing every 8 seconds to ensure visibility.

Message Chunking

Messages exceeding 2,000 characters are split at line breaks. Code blocks are properly closed and reopened across chunks to maintain formatting.


Access Control

DM Policy

Controlled via channels.dm_policy in config.yaml. Despite the name, it applies to guild messages too: an unapproved member who @mentions the bot in a server channel gets the pairing reply in that channel.

Value Behavior
pairing (default) Unknown users receive a one-time pairing code; owner approves via Web UI or CLI
allowlist Only user IDs listed in channels.allow_from, and users already approved through pairing, get an answer; no codes are issued
open Anyone can use the bot without approval

allow_from: ["*"] admits everyone. The guild settings below are checked in addition to this policy, not instead of it.

channels:
  dm_policy: "pairing"      # pairing | allowlist | open
  allow_from:
    - "100000000000000103"   # Discord user IDs

Guild Channel Restrictions

GoClaw offers a per-guild and per-channel access control system. This lets you:

How Precedence Works

Resolution order (most specific wins):

per-channel config  β†’  per-guild config  β†’  global default (allow all)
  1. Channel-level (guilds.<id>.channels.<channel_id>) is checked first.
  2. Guild-level (guilds.<id>.users / guilds.<id>.roles) is the fallback.
  3. If neither is configured, all users are allowed.

A channel that is not listed under channels follows the guild-level settings, so listing one channel does not keep the bot out of the others.


Per-Guild Configuration

Under channels.discord.guilds, add an entry keyed by the Guild (Server) ID:

channels:
  discord:
    enabled: true
    token: "YOUR_BOT_TOKEN"
    guilds:
      "100000000000000103":          # Guild ID (right-click server β†’ Copy Server ID)
        require_mention: true        # true = bot must be @mentioned (default for guilds)
        users:                       # Allowlist: only these users can interact
          - "100000000000000101"
          - "100000000000000106"
        roles:                       # Allowlist: only members with these roles can interact
          - "100000000000000111"      # Role ID (right-click role β†’ Copy ID)
        reaction_notifications: "own"  # off | own | all

Guild-level fields:

Field Type Default Description
require_mention bool true in guilds Whether the bot must be @mentioned to respond
users []string β€” Discord user IDs allowed to interact. If set, only these users are allowed
roles []string β€” Discord role IDs allowed to interact. If set, only members with at least one listed role are allowed
reaction_notifications string "off" Controls emoji reaction forwarding: off, own (bot's messages only), all
channels map β€” Per-channel overrides (see below)

Note: If both users and roles are empty at the guild level, all users in that guild are permitted (subject to channel-level rules).

A guild entry also accepts slug, but GoClaw does not use it.


Per-Channel Configuration

Inside a guild entry, add a channels map keyed by Discord channel ID:

guilds:
  "100000000000000103":
    channels:
      "100000000000000110":          # Channel ID (right-click channel β†’ Copy ID)
        allow: true                  # true = enabled, false = disabled entirely
        require_mention: false       # override: respond to all messages, no @mention needed
        auto_thread: true            # Create a thread for each message automatically
        users:                       # Channel-level user allowlist
          - "100000000000000101"
        roles:                       # Channel-level role allowlist
          - "100000000000000108"

Per-channel fields:

Field Type Default Description
allow *bool nil (inherit) false disables the bot entirely in this channel regardless of guild config
require_mention *bool nil (inherit guild or global) false lets the bot respond to all messages without @mention; true enforces it
auto_thread bool false Automatically creates a Discord thread per message
users []string β€” Channel-specific user allowlist (overrides guild allowlist)
roles []string β€” Channel-specific role allowlist (overrides guild allowlist)

A channel entry also accepts system_prompt, but GoClaw does not use it: nothing is added to the agent's prompt.

Threads

Inside a thread, GoClaw uses the thread's own entry under channels when it has one, and otherwise its channel's. A channel's allow, require_mention, users and roles therefore apply in its threads too: a channel set to allow: false is closed in its threads as well, and in a channel with require_mention: false its threads need no @mention either.

With auto_thread: true, the bot answers each new message in the channel in a thread it creates from that message. The conversation belongs to that thread from the first message, so the agent sees the whole exchange when the person goes on writing in the thread.


Common Patterns

Public server β€” bot responds anywhere it's mentioned

channels:
  discord:
    enabled: true
    token: "YOUR_BOT_TOKEN"
    # No guilds config needed: bot responds to @mentions everywhere by default

Answer every message in one channel, stay out of another

channels:
  discord:
    enabled: true
    token: "YOUR_BOT_TOKEN"
    guilds:
      "100000000000000103":
        channels:
          "100000000000000110":
            allow: true
            require_mention: false   # Respond to every message in this channel
          "100000000000000101":
            allow: false             # Explicitly disable bot in this channel

Channels not listed here still answer @mentions. GoClaw has no "only this channel" switch: to keep the bot to one channel, list every other channel with allow: false, or deny the bot the View Channels permission in the other channels in Discord's own channel settings.

Allow only specific roles (e.g., "Admin", "Staff")

channels:
  discord:
    enabled: true
    token: "YOUR_BOT_TOKEN"
    guilds:
      "100000000000000103":
        roles:
          - "100000000000000107"     # Admin role ID
          - "100000000000000108"     # Staff role ID

Per-channel role override β€” different access per channel

guilds:
  "100000000000000103":
    roles:
      - "100000000000000107"         # Guild default: Admin only
    channels:
      "100000000000000110":          # This channel
        roles:
          - "100000000000000109"     # Allowed for a different role (e.g., "Support Team")
          - "100000000000000107"

Auto-thread channel

guilds:
  "100000000000000103":
    channels:
      "100000000000000110":
        allow: true
        require_mention: false
        auto_thread: true

Follow-ups inside the created threads need an @mention or a reply to the bot. See Threads for how the conversation is split between the channel and the thread.

Reaction notifications β€” bot forwards reactions as messages

guilds:
  "100000000000000103":
    reaction_notifications: "own"   # Only reactions on bot's own messages

Bot Presence & Activity

Control the bot's online status and activity text:

channels:
  discord:
    status: "online"         # online | dnd | idle | invisible
    activity: "tasks"
    activity_type: 3         # 0=Playing, 1=Streaming, 2=Listening, 3=Watching, 4=Custom, 5=Competing

Presence is set only when activity is set: without it, status is ignored too and the bot shows as plain online. An unset activity_type is 0 (Playing). Avoid 4 (Custom): Discord shows a custom status's separate state text, which GoClaw does not set.


Streaming Mode

By default, the bot sends a complete reply after processing.

channels:
  discord:
    streaming: "partial"     # off (default) | partial

In partial mode, a _thinking…_ placeholder message is posted right away, shows the answer as it is written (updated at most every 1.5 seconds), and is replaced by the full reply when the agent finishes. In this mode the status reactions are not shown, and the reply is split at 2,000 characters whatever text_chunk_limit and max_lines_per_message say.


Advanced Options

channels:
  discord:
    enabled: true
    token: "YOUR_BOT_TOKEN"

    text_chunk_limit: 2000       # Max characters per message (Discord hard cap: 2000)
    max_lines_per_message: 17    # Soft line limit; set to avoid collapsed walls of text
    allow_bots: false            # Whether other bot messages trigger responses
    ack_reaction: ""             # Override status emoji (e.g. "βœ…"). Empty = animated sequence
    ack_reaction_scope: ""       # "off" turns status reactions off; any other value leaves them on
    streaming: "off"             # "off" | "partial"
    status: "online"             # online | dnd | idle | invisible (needs activity)
    activity: "tasks"            # Presence text
    activity_type: 3             # 0=Playing 1=Streaming 2=Listening 3=Watching 5=Competing

ack_reaction_scope has one effective value, off. group-mentions and all behave like the empty default: reactions are shown on every message the bot works on.


Configuration Reference Summary

channels:
  dm_policy: "pairing"          # pairing | allowlist | open
  allow_from:                   # User IDs for allowlist DM policy
    - "100000000000000103"

  discord:
    enabled: true
    token: "YOUR_BOT_TOKEN"
    text_chunk_limit: 2000
    max_lines_per_message: 0    # 0 = unlimited
    streaming: "off"
    allow_bots: false
    status: "online"
    activity: ""
    activity_type: 0
    ack_reaction: ""
    ack_reaction_scope: ""

    guilds:
      "<GUILD_ID>":
        require_mention: true
        reaction_notifications: "off"   # off | own | all
        users:
          - "<USER_ID>"
        roles:
          - "<ROLE_ID>"
        channels:
          "<CHANNEL_ID>":
            allow: true                 # false = disable bot in this channel
            require_mention: false
            auto_thread: false
            users:
              - "<USER_ID>"
            roles:
              - "<ROLE_ID>"

Troubleshooting

Bot sees no messages

Guild messages not working

A user is being blocked unexpectedly

Pairing not working

Finding IDs (Developer Mode required)

Object How to copy ID
Guild (Server) Right-click the server icon in the sidebar β†’ Copy Server ID
Channel Right-click the channel name β†’ Copy Channel ID
User Right-click on a username in chat or member list β†’ Copy User ID
Role Server Settings β†’ Roles β†’ right-click a role β†’ Copy Role ID