Files
Dirigent/plugin
hzhang 32dc9a4233 refactor: new design — sidecar services, moderator Gateway client, tool execute API
- Replace standalone no-reply-api Docker service with unified sidecar (services/main.mjs)
  that routes /no-reply/* and /moderator/* and starts/stops with openclaw-gateway
- Add moderator Discord Gateway client (services/moderator/index.mjs) for real-time
  MESSAGE_CREATE push instead of polling; notifies plugin via HTTP callback
- Add plugin HTTP routes (plugin/web/dirigent-api.ts) for moderator → plugin callbacks
  (wake-from-dormant, interrupt tail-match)
- Fix tool registration format: AgentTool requires execute: not handler:; factory form
  for tools needing ctx
- Rename no-reply-process.ts → sidecar-process.ts, startNoReplyApi → startSideCar
- Remove dead config fields from openclaw.plugin.json (humanList, agentList, listMode,
  channelPoliciesFile, endSymbols, waitIdentifier, multiMessage*, bypassUserIds, etc.)
- Rename noReplyPort → sideCarPort
- Remove docker-compose.yml, dev-up/down scripts, package-plugin.mjs, test-no-reply-api.mjs
- Update install.mjs: clean dist before build, copy services/, drop dead config writes
- Update README, Makefile, smoke script for new architecture

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 08:07:59 +01:00
..

Dirigent 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 end-marker instruction + scheduling identifier instruction when decision allows speaking.

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)
  • schedulingIdentifier (default ➡️) — moderator handoff identifier
  • enableDirigentPolicyTool (default true)
  • multiMessageStartMarker (default ↗️)
  • multiMessageEndMarker (default ↙️)
  • multiMessagePromptMarker (default ⤵️)

Unified optional tool:

  • dirigent_tools
    • Discord actions: channel-private-create, channel-private-update, member-list
    • Policy actions: policy-get, policy-set-channel, policy-delete-channel
    • Turn actions: turn-status, turn-advance, turn-reset
  • bypassUserIds (deprecated alias of humanList)
  • endSymbols (default ["🔚"])
  • enableDiscordControlTool (default true)
  • Discord control actions are executed in-plugin via Discord REST API (no discordControlApiBaseUrl needed)
  • 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
  • dirigent_tools policy actions update memory first, then persist to file (atomic write)

Moderator handoff format

When the current speaker NO_REPLYs, the moderator bot sends: <@NEXT_USER_ID>➡️

This is a non-semantic scheduling message. The scheduling identifier (➡️ by default) carries no meaning — it simply signals the next agent to check chat history and decide whether to speak.

Multi-message mode / shuffle mode

  • Human sends the configured start marker (default ↗️) → channel enters multi-message mode.
  • While active, agents are forced to no-reply and the moderator sends only the configured prompt marker (default ⤵️) after each additional human message.
  • Human sends the configured end marker (default ↙️) → channel exits multi-message mode and normal scheduling resumes.
  • No separate moderator "entered/exited mode" confirmation message is sent; the markers themselves are the protocol.
  • The first moderator message after exit uses the normal scheduling handoff format: <@NEXT_USER_ID>➡️.
  • /dirigent turn-shuffling, /dirigent turn-shuffling on, and /dirigent turn-shuffling off control per-channel reshuffling between completed rounds.

Slash command (Discord)

/dirigent status
/dirigent turn-status
/dirigent turn-advance
/dirigent turn-reset
/dirigent turn-shuffling
/dirigent turn-shuffling on
/dirigent turn-shuffling off

Debug logging:

  • set enableDebugLogs: true to emit detailed hook diagnostics
  • optionally set debugLogChannelIds to only log selected channel IDs