docs: default discord reactions to on

This commit is contained in:
Peter Steinberger
2026-01-02 01:11:04 +01:00
parent c0976ec099
commit 464dabdc16
4 changed files with 86 additions and 12 deletions

View File

@@ -114,6 +114,7 @@ Controls how inbound messages behave when an agent run is already active.
whatsapp: "interrupt", whatsapp: "interrupt",
telegram: "interrupt", telegram: "interrupt",
discord: "queue", discord: "queue",
imessage: "interrupt",
webchat: "queue" webchat: "queue"
} }
} }
@@ -180,13 +181,37 @@ Configure the Discord bot by setting the bot token and optional gating:
requireMention: true, // require @bot mentions in guilds requireMention: true, // require @bot mentions in guilds
mediaMaxMb: 8, // clamp inbound media size mediaMaxMb: 8, // clamp inbound media size
historyLimit: 20, // include last N guild messages as context historyLimit: 20, // include last N guild messages as context
enableReactions: false // allow agent-triggered reactions enableReactions: true // allow agent-triggered reactions
} }
} }
``` ```
Clawdis reads `DISCORD_BOT_TOKEN` or `discord.token` to start the provider (unless `discord.enabled` is `false`). Use `user:<id>` (DM) or `channel:<id>` (guild channel) when specifying delivery targets for cron/CLI commands. Clawdis reads `DISCORD_BOT_TOKEN` or `discord.token` to start the provider (unless `discord.enabled` is `false`). Use `user:<id>` (DM) or `channel:<id>` (guild channel) when specifying delivery targets for cron/CLI commands.
### `imessage` (imsg CLI)
Clawdis spawns `imsg rpc` (JSON-RPC over stdio). No daemon or port required.
```json5
{
imessage: {
enabled: true,
cliPath: "imsg",
dbPath: "~/Library/Messages/chat.db",
allowFrom: ["+15555550123", "user@example.com", "chat_id:123"],
includeAttachments: false,
mediaMaxMb: 16,
service: "auto",
region: "US"
}
}
```
Notes:
- Requires Full Disk Access to the Messages DB.
- The first send will prompt for Messages automation permission.
- Prefer `chat_id:<id>` targets. Use `imsg chats --limit 20` to list chats.
### `agent.workspace` ### `agent.workspace`
Sets the **single global workspace directory** used by the agent for file operations. Sets the **single global workspace directory** used by the agent for file operations.
@@ -284,7 +309,7 @@ Z.AI models are available as `zai/<model>` (e.g. `zai/glm-4.7`) and require
- `every`: duration string (`ms`, `s`, `m`, `h`); default unit minutes. Omit or set - `every`: duration string (`ms`, `s`, `m`, `h`); default unit minutes. Omit or set
`0m` to disable. `0m` to disable.
- `model`: optional override model for heartbeat runs (`provider/model`). - `model`: optional override model for heartbeat runs (`provider/model`).
- `target`: optional delivery channel (`last`, `whatsapp`, `telegram`, `discord`, `none`). Default: `last`. - `target`: optional delivery channel (`last`, `whatsapp`, `telegram`, `discord`, `imessage`, `none`). Default: `last`.
- `to`: optional recipient override (E.164 for WhatsApp, chat id for Telegram). - `to`: optional recipient override (E.164 for WhatsApp, chat id for Telegram).
- `prompt`: optional override for the heartbeat body (default: `HEARTBEAT`). - `prompt`: optional override for the heartbeat body (default: `HEARTBEAT`).
@@ -718,7 +743,7 @@ Template placeholders are expanded in `routing.transcribeAudio.command` (and any
| `{{GroupMembers}}` | Group members preview (best effort) | | `{{GroupMembers}}` | Group members preview (best effort) |
| `{{SenderName}}` | Sender display name (best effort) | | `{{SenderName}}` | Sender display name (best effort) |
| `{{SenderE164}}` | Sender phone number (best effort) | | `{{SenderE164}}` | Sender phone number (best effort) |
| `{{Surface}}` | Surface hint (whatsapp|telegram|discord|webchat|…) | | `{{Surface}}` | Surface hint (whatsapp|telegram|discord|imessage|webchat|…) |
## Cron (Gateway scheduler) ## Cron (Gateway scheduler)

View File

@@ -24,7 +24,7 @@ Status: ready for DM and guild text channels via the official Discord bot gatewa
7. Optional DM allowlist: reuse `discord.allowFrom` with user ids (`1234567890` or `discord:1234567890`). Use `"*"` to allow all DMs. 7. Optional DM allowlist: reuse `discord.allowFrom` with user ids (`1234567890` or `discord:1234567890`). Use `"*"` to allow all DMs.
8. Optional guild allowlist: set `discord.guildAllowFrom` with `guilds` and/or `users` to gate who can invoke the bot in servers. 8. Optional guild allowlist: set `discord.guildAllowFrom` with `guilds` and/or `users` to gate who can invoke the bot in servers.
9. Optional guild context history: set `discord.historyLimit` (default 20) to include the last N guild messages as context when replying to a mention. Set `0` to disable. 9. Optional guild context history: set `discord.historyLimit` (default 20) to include the last N guild messages as context when replying to a mention. Set `0` to disable.
10. Optional reactions: set `discord.enableReactions = true` to allow the agent to react to Discord messages via the `clawdis_discord` tool. 10. Reactions (default on): set `discord.enableReactions = false` to disable agent-triggered reactions via the `clawdis_discord` tool.
Note: Discord does not provide a simple username → id lookup without extra guild context, so prefer ids or `<@id>` mentions for DM delivery targets. Note: Discord does not provide a simple username → id lookup without extra guild context, so prefer ids or `<@id>` mentions for DM delivery targets.
@@ -49,7 +49,7 @@ Note: Discord does not provide a simple username → id lookup without extra gui
requireMention: true, requireMention: true,
mediaMaxMb: 8, mediaMaxMb: 8,
historyLimit: 20, historyLimit: 20,
enableReactions: false enableReactions: true
} }
} }
``` ```
@@ -59,7 +59,7 @@ Note: Discord does not provide a simple username → id lookup without extra gui
- `requireMention`: when `true`, messages in guild channels must mention the bot. - `requireMention`: when `true`, messages in guild channels must mention the bot.
- `mediaMaxMb`: clamp inbound media saved to disk. - `mediaMaxMb`: clamp inbound media saved to disk.
- `historyLimit`: number of recent guild messages to include as context when replying to a mention (default 20, `0` disables). - `historyLimit`: number of recent guild messages to include as context when replying to a mention (default 20, `0` disables).
- `enableReactions`: allow agent-triggered reactions via the `clawdis_discord` tool (default `false`). - `enableReactions`: allow agent-triggered reactions via the `clawdis_discord` tool (default `true`).
## Reactions ## Reactions
When `discord.enableReactions = true`, the agent can call `clawdis_discord` with: When `discord.enableReactions = true`, the agent can call `clawdis_discord` with:

View File

@@ -1437,7 +1437,7 @@ function createDiscordTool(): AnyAgentTool {
label: "Clawdis Discord", label: "Clawdis Discord",
name: "clawdis_discord", name: "clawdis_discord",
description: description:
"React to Discord messages. Requires discord.enableReactions=true in config.", "React to Discord messages. Controlled by discord.enableReactions (default: true).",
parameters: DiscordToolSchema, parameters: DiscordToolSchema,
execute: async (_toolCallId, args) => { execute: async (_toolCallId, args) => {
const params = args as Record<string, unknown>; const params = args as Record<string, unknown>;
@@ -1445,7 +1445,7 @@ function createDiscordTool(): AnyAgentTool {
if (action !== "react") throw new Error(`Unknown action: ${action}`); if (action !== "react") throw new Error(`Unknown action: ${action}`);
const cfg = loadConfig(); const cfg = loadConfig();
if (!cfg.discord?.enableReactions) { if (cfg.discord?.enableReactions === false) {
throw new Error( throw new Error(
"Discord reactions are disabled (set discord.enableReactions=true).", "Discord reactions are disabled (set discord.enableReactions=true).",
); );

View File

@@ -102,7 +102,7 @@ export type HookMappingConfig = {
messageTemplate?: string; messageTemplate?: string;
textTemplate?: string; textTemplate?: string;
deliver?: boolean; deliver?: boolean;
channel?: "last" | "whatsapp" | "telegram" | "discord"; channel?: "last" | "whatsapp" | "telegram" | "discord" | "signal" | "imessage";
to?: string; to?: string;
thinking?: string; thinking?: string;
timeoutSeconds?: number; timeoutSeconds?: number;
@@ -171,7 +171,7 @@ export type DiscordConfig = {
mediaMaxMb?: number; mediaMaxMb?: number;
/** Number of recent guild messages to include for context (default: 20). */ /** Number of recent guild messages to include for context (default: 20). */
historyLimit?: number; historyLimit?: number;
/** Allow agent-triggered Discord reactions (default: false). */ /** Allow agent-triggered Discord reactions (default: true). */
enableReactions?: boolean; enableReactions?: boolean;
}; };
@@ -198,6 +198,25 @@ export type SignalConfig = {
mediaMaxMb?: number; mediaMaxMb?: number;
}; };
export type IMessageConfig = {
/** If false, do not start the iMessage provider. Default: true. */
enabled?: boolean;
/** imsg CLI binary path (default: imsg). */
cliPath?: string;
/** Optional Messages db path override. */
dbPath?: string;
/** Optional default send service (imessage|sms|auto). */
service?: "imessage" | "sms" | "auto";
/** Optional default region (used when sending SMS). */
region?: string;
/** Optional allowlist for inbound handles or chat_id targets. */
allowFrom?: Array<string | number>;
/** Include attachments + reactions in watch payloads. */
includeAttachments?: boolean;
/** Max outbound media size in MB. */
mediaMaxMb?: number;
};
export type QueueMode = "queue" | "interrupt"; export type QueueMode = "queue" | "interrupt";
export type QueueModeBySurface = { export type QueueModeBySurface = {
@@ -205,6 +224,7 @@ export type QueueModeBySurface = {
telegram?: QueueMode; telegram?: QueueMode;
discord?: QueueMode; discord?: QueueMode;
signal?: QueueMode; signal?: QueueMode;
imessage?: QueueMode;
webchat?: QueueMode; webchat?: QueueMode;
}; };
@@ -450,8 +470,15 @@ export type ClawdisConfig = {
every?: string; every?: string;
/** Heartbeat model override (provider/model). */ /** Heartbeat model override (provider/model). */
model?: string; model?: string;
/** Delivery target (last|whatsapp|telegram|discord|signal|none). */ /** Delivery target (last|whatsapp|telegram|discord|signal|imessage|none). */
target?: "last" | "whatsapp" | "telegram" | "discord" | "signal" | "none"; target?:
| "last"
| "whatsapp"
| "telegram"
| "discord"
| "signal"
| "imessage"
| "none";
/** Optional delivery override (E.164 for WhatsApp, chat id for Telegram). */ /** Optional delivery override (E.164 for WhatsApp, chat id for Telegram). */
to?: string; to?: string;
/** Override the heartbeat prompt body (default: "HEARTBEAT"). */ /** Override the heartbeat prompt body (default: "HEARTBEAT"). */
@@ -476,6 +503,7 @@ export type ClawdisConfig = {
telegram?: TelegramConfig; telegram?: TelegramConfig;
discord?: DiscordConfig; discord?: DiscordConfig;
signal?: SignalConfig; signal?: SignalConfig;
imessage?: IMessageConfig;
cron?: CronConfig; cron?: CronConfig;
hooks?: HooksConfig; hooks?: HooksConfig;
bridge?: BridgeConfig; bridge?: BridgeConfig;
@@ -570,6 +598,7 @@ const QueueModeBySurfaceSchema = z
telegram: QueueModeSchema.optional(), telegram: QueueModeSchema.optional(),
discord: QueueModeSchema.optional(), discord: QueueModeSchema.optional(),
signal: QueueModeSchema.optional(), signal: QueueModeSchema.optional(),
imessage: QueueModeSchema.optional(),
webchat: QueueModeSchema.optional(), webchat: QueueModeSchema.optional(),
}) })
.optional(); .optional();
@@ -616,6 +645,7 @@ const HeartbeatSchema = z
z.literal("telegram"), z.literal("telegram"),
z.literal("discord"), z.literal("discord"),
z.literal("signal"), z.literal("signal"),
z.literal("imessage"),
z.literal("none"), z.literal("none"),
]) ])
.optional(), .optional(),
@@ -675,6 +705,7 @@ const HookMappingSchema = z
z.literal("telegram"), z.literal("telegram"),
z.literal("discord"), z.literal("discord"),
z.literal("signal"), z.literal("signal"),
z.literal("imessage"),
]) ])
.optional(), .optional(),
to: z.string().optional(), to: z.string().optional(),
@@ -903,6 +934,24 @@ const ClawdisSchema = z.object({
mediaMaxMb: z.number().positive().optional(), mediaMaxMb: z.number().positive().optional(),
}) })
.optional(), .optional(),
imessage: z
.object({
enabled: z.boolean().optional(),
cliPath: z.string().optional(),
dbPath: z.string().optional(),
service: z
.union([
z.literal("imessage"),
z.literal("sms"),
z.literal("auto"),
])
.optional(),
region: z.string().optional(),
allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
includeAttachments: z.boolean().optional(),
mediaMaxMb: z.number().positive().optional(),
})
.optional(),
bridge: z bridge: z
.object({ .object({
enabled: z.boolean().optional(), enabled: z.boolean().optional(),