Files
Dirigent/plugin
zhi 54ff78cffe feat: moderator bot for turn handoff messages
Add a dedicated moderator Discord bot that sends handoff messages when
the current speaker says NO_REPLY. This solves the wakeup problem.

Flow:
1. Agent A is current speaker, receives message
2. Agent A responds with NO_REPLY
3. Plugin detects NO_REPLY in message_sent hook, advances turn to Agent B
4. Plugin sends via moderator bot: '轮到(@AgentB)了,如果没有想说的请直接回复NO_REPLY'
5. This real Discord message triggers Agent B's session
6. Turn manager allows Agent B to respond

Implementation:
- moderatorBotToken config field for the moderator bot's Discord token
- userIdFromToken() extracts Discord user ID from bot token (base64)
- resolveDiscordUserId() maps accountId → Discord user ID via account tokens
- sendModeratorMessage() calls Discord REST API directly
- message_received ignores moderator bot messages (transparent to turn state)
- Moderator bot is NOT in the turn order
2026-02-28 12:10:52 +00:00
..

WhisperGate Plugin

Hook strategy

  • message:received caches a per-session decision from deterministic rules.
  • before_model_resolve applies providerOverride + modelOverride when decision says no-reply.
  • before_prompt_build prepends instruction 你的这次发言必须以🔚作为结尾。 when decision is:
    • bypass_sender
    • end_symbol:*

Rules (in order)

  1. non-discord -> skip
  2. bypass sender -> skip
  3. end symbol matched -> skip
  4. else -> no-reply override

Config

See docs/CONFIG.example.json.

Required:

  • noReplyProvider
  • noReplyModel

Optional:

  • enabled (default true)
  • discordOnly (default true)
  • listMode (human-list | agent-list, default human-list)
  • humanList (default [])
  • agentList (default [])
  • channelPoliciesFile (per-channel overrides in a standalone JSON file)
  • enableWhispergatePolicyTool (default true)

Unified optional tool:

  • whispergateway_tools
    • Discord actions: channel-private-create, channel-private-update, member-list
    • Policy actions: policy-get, policy-set-channel, policy-delete-channel
  • bypassUserIds (deprecated alias of humanList)
  • endSymbols (default ["🔚"])
  • enableDiscordControlTool (default true)
  • discordControlApiBaseUrl (default http://127.0.0.1:8790)
  • discordControlApiToken
  • discordControlCallerId
  • enableDebugLogs (default false)
  • debugLogChannelIds (default [], empty = all channels when debug enabled)

Per-channel policy file example: docs/channel-policies.example.json.

Policy file behavior:

  • loaded once on startup into memory
  • runtime decisions read memory state only
  • direct file edits do NOT affect memory state
  • whispergateway_tools policy actions update memory first, then persist to file (atomic write)

Optional tool: whispergateway_tools

This plugin registers one unified optional tool: whispergateway_tools. To use it, add tool allowlist entry for either:

  • tool name: whispergateway_tools
  • plugin id: whispergate

Supported actions:

  • Discord: channel-private-create, channel-private-update, member-list
  • Policy: policy-get, policy-set-channel, policy-delete-channel

Debug logging:

  • set enableDebugLogs: true to emit detailed hook diagnostics
  • optionally set debugLogChannelIds to only log selected channel IDs
  • logs include key ctx fields + decision status at message_received, before_model_resolve, before_prompt_build