Skip to content

Privacy-safe AutoMod rules and reviewed changes

list_automod_rules and get_automod_rule expose a bounded inventory or one exact AutoMod rule for a separately allowlisted guild. Set capabilities.automodAudit: true and list every eligible guild in scopes.automodGuildIds. This allowlist must be a subset of readScope.guildIds when the outer read allowlist exists. The equivalent discord://guilds/{guildId}/automod-rules resource returns the same summary inventory.

Inventory deliberately exposes only each rule's exact ID, guild and creator IDs, name, enabled state, event and trigger types, action types, policy-entry and exemption counts, reference health, and complete permission evidence. Keyword filters, regex patterns, allow lists, preset selections, custom block messages, alert-channel IDs, timeout durations, and exact exemption IDs require get_automod_rule for one known rule. Exact policy is returned transiently for review but is never cached, journaled, exported, or copied into resource discovery. Both reads verify the application and bot identity, exact guild and owner, connector membership, complete bounded roles, visible channels, all referenced IDs, and MANAGE_GUILD. A referenced channel omitted by Discord is reported unsafe and blocks a change.

Changes have no immediate-call path. Set capabilities.automodChanges: true in addition to audit scope. The strict action union supports disabled creation, disabled-rule update, a separate enable or disable transition, and exact-ID deletion of a disabled rule. Create always sets enabled to false. An enabled rule must be disabled under its own reviewed plan before it can be edited or deleted, and Discord's immutable trigger type can change only through disabled deletion and a separately reviewed creation.

Supported triggers are keyword, keyword preset, spam, mention spam, and member profile. Supported actions are block message, send alert message, timeout, and block member interaction. Member-profile rules require block-member-interaction as their only action and cannot exempt channels; other triggers reject that action. Timeout is available only for keyword and mention-spam triggers, and creating, updating, or enabling a timeout-bearing rule requires MODERATE_MEMBERS. Rule names, policy strings, actions, exemptions, mention thresholds, timeout duration, and list sizes use strict closed schemas and Discord's documented bounds. Creation binds the complete inventory and enforces the connector safety ceiling plus per-trigger capacity: six keyword rules and one rule for each other trigger type.

Every desired exempt role and channel must resolve in the complete guild inventories, and the guild's @everyone role cannot be exempted. A send-alert action additionally requires its exact destination in scopes.automodAlertChannelIds, an existing text or announcement channel, and complete effective VIEW_CHANNEL evidence for the connector. Alert actions can copy matched user content into that channel, so the destination allowlist is independent from general AutoMod guild scope and should remain narrow.

  1. Call plan_automod_change with the exact guild, strict action-specific policy, Discord audit-log reason, and unique one-shot operation key.
  2. Review the verified application and bot IDs, exact guild, existing and desired transient policy, lifecycle effect, complete permissions, capacity, reference health and names, privacy guarantees, warnings, operation-key hash, and keyed digest.
  3. If the plan reports already-current, no confirmation, reservation, activity record, or Discord write is needed.
  4. Call execute_automod_change with identical inputs plus the digest.
  5. Approve the signed MCP confirmation only if every exact identity, policy field, lifecycle effect, permission, reference, warning, audit reason, operation-key hash, and digest remains intended.
  6. Review the returned exact transient policy state or verified absence, activity ID, and outcome before any follow-up.
  7. After completion or a connector restart, call verify_automod_change with the identical caller-retained request. Treat only verified as receipt-bound fresh evidence; not-found, blocked, and drifted require inspection before another reviewed intent.

The process-keyed HMAC digest binds the normalized request, verified identities, exact guild and owner, connector member and relevant roles, complete permission evidence, current and desired policy, selected channels and permission overwrites, exact reference evidence, creation capacity and inventory digest, privacy projection, operation-key hash, and warnings. A connector restart invalidates the digest. The MCP adapter rebuilds the plan before approval, and the service rebuilds it immediately before mutation. Any policy, lifecycle, role, channel, permission, reference, or capacity drift invalidates the reviewed plan.

Execution atomically reserves the operation-key hash and appends a pending content-free activity record before one non-retried POST, PATCH, or DELETE. The strict schema-v2 receipt contains a token-derived keyed requestDigest that binds the normalized request and exact identity without storing any policy string, name, reference, audit reason, or raw operation key. There is no schema-v1 AutoMod receipt compatibility parser, migration, or fallback. Execution performs an exact rule GET for creation, update, or enable-state changes, and requires a not-found result from the exact rule GET after deletion. Matching controlled state or verified absence is completed; valid server-adjusted state or a target that remains after deletion is completed-with-drift; a known pre-write Discord client error is failed; transport failure, Discord server error, malformed success, or failed post-write verification is uncertain. The connector never retries or issues a compensating change.

verify_automod_change verifies the pinned connector identity, then reads the receipt before any guild, permission, inventory, or exact-rule request. A missing receipt returns not-found; a changed caller request, rotated token-derived verification key, or nonterminal receipt returns a content-free blocker without an AutoMod-domain Discord read. A matching completed create receipt binds the exact created rule ID and checks the requested policy and connector creator identity while deliberately ignoring a later separately reviewed enabled-state transition. Update verification compares only the explicitly requested fields, enable verification compares the boolean, and deletion verification requires exact absence. The result contains only IDs, hashes, receipt state, timestamps, booleans, and fixed reason codes.

All AutoMod changes in one guild serialize inside one process because lifecycle, rule capacity, roles, channels, and alert destinations are shared evidence. The production facade additionally acquires a durable exact guild AutoMod-collection claim, so connector processes sharing the activity-state root exclude overlapping changes. An uncertain result retains that claim for operator review before another key can be reserved. Activity and operation records contain only exact guild and rule IDs, action and trigger type, optional target enabled state, plan digest, operation-key hash, timestamps, fixed verification and outcome values, activity ID, and sanitized error category; the schema-v2 operation receipt additionally contains the keyed request digest. Rule names, trigger strings, regex patterns, presets, custom messages, action settings, role and channel names, audit reasons, and raw operation keys never enter durable records, diagnostics, or telemetry. AutoMod action-execution Gateway dispatches are deliberately unsupported because their raw payloads can contain message content, matched content, and matched keywords. See Discord's Auto Moderation resource and permission flags.

Canonical source: docs/reference.md

Documentation generated for guildcontrol@0.0.0. Canonical source and edit history remain in the public repository. GuildControl is an independent project and is not affiliated with or endorsed by Discord Inc. Discord is used only to identify the platform that GuildControl connects to.