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.
GoClaw requires specific intents to see and process messages. On the Bot page, scroll down to Privileged Gateway Intents and enable:
On the Bot page, click Reset Token. Copy and save the token securely. You will need it for the GoClaw configuration.
Click OAuth2 on the sidebar, then URL Generator. Enable:
bot, applications.commandsauto_thread and for answering inside threads)Copy the generated URL and open it in your browser to add the bot to your server.
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.
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.
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>
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.
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.
A typing indicator is shown while the agent processes the message, refreshing every 8 seconds to ensure visibility.
Messages exceeding 2,000 characters are split at line breaks. Code blocks are properly closed and reopened across chunks to maintain formatting.
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
GoClaw offers a per-guild and per-channel access control system. This lets you:
Resolution order (most specific wins):
per-channel config β per-guild config β global default (allow all)
guilds.<id>.channels.<channel_id>) is checked first.guilds.<id>.users / guilds.<id>.roles) is the fallback.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.
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
usersandrolesare 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.
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.
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.
channels:
discord:
enabled: true
token: "YOUR_BOT_TOKEN"
# No guilds config needed: bot responds to @mentions everywhere by default
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.
channels:
discord:
enabled: true
token: "YOUR_BOT_TOKEN"
guilds:
"100000000000000103":
roles:
- "100000000000000107" # Admin role ID
- "100000000000000108" # Staff role ID
guilds:
"100000000000000103":
roles:
- "100000000000000107" # Guild default: Admin only
channels:
"100000000000000110": # This channel
roles:
- "100000000000000109" # Allowed for a different role (e.g., "Support Team")
- "100000000000000107"
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.
guilds:
"100000000000000103":
reaction_notifications: "own" # Only reactions on bot's own messages
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.
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.
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.
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>"
guilds config, check that the Guild ID is correct (right-click server icon β Copy Server ID).users or roles is set at the guild level β if so, only listed entries are allowed.allow: false will silently block all messages in that channel.users/roles overrides guild-level allowlists; ensure the user/role ID appears at the right level.dm_policy applies in server channels too.dm_policy is set to pairing (not allowlist).goclaw pairing pending discord or on the Web UI's Pairing tab (they are kept in <state dir>/credentials/goclaw-pending.json).| 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 |