CEO Bot — Multi-Bot Org

hub-and-spoke architecture — 10+ bots, 1 coordinator, @mention protocol

1

Architecture — Hub and Spoke

      graph TD
        CEO["CEO Bot"]:::ceo

        MGR["Manager Bot"]:::bot
        MON["Monitor Bot"]:::bot
        DEP["Deploy Bot"]:::bot
        SEC["Security Bot"]:::bot
        LOG["Logger Bot"]:::bot
        DB["Database Bot"]:::bot
        API["API Bot"]:::bot
        ALERT["Alert Bot"]:::bot
        SCHED["Scheduler Bot"]:::bot
        REPORT["Report Bot"]:::bot

        CEO <-->|"@mention"| MGR
        CEO <-->|"@mention"| MON
        CEO <-->|"@mention"| DEP
        CEO <-->|"@mention"| SEC
        CEO <-->|"@mention"| LOG
        CEO <-->|"@mention"| DB
        CEO <-->|"@mention"| API
        CEO <-->|"@mention"| ALERT
        CEO <-->|"@mention"| SCHED
        CEO <-->|"@mention"| REPORT

        HUMAN["Human Owner"]:::human
        HUMAN <-->|"direct message"| CEO

        classDef ceo fill:#1e1b4b,stroke:#5865F2,color:#c4b5fd,stroke-width:3px
        classDef bot fill:#1b2e2e,stroke:#00d4aa,color:#a0f0dd
        classDef human fill:#1b2e1e,stroke:#43b581,color:#a3d9b1,stroke-width:2px
    
All bots communicate through CEO via @mentions — no direct bot-to-bot chatter
2

The Problem

Blocked — All Bot Messages Dropped
server.ts : line 803 — shared by ALL bots using the Discord plugin
client.on('messageCreate', msg => {
  if (msg.author.bot) return  // blocks ALL bot messages — entire org is deaf   handleInbound(msg).catch(e => ...)
})
      graph LR
        A["Any Bot sends message"]:::bot --> B{"msg.author.bot?"}:::decision
        B -->|"true"| C["DROPPED"]:::dropped
        H["Human sends message"]:::human --> B
        B -->|"false"| D["handleInbound()"]:::processed

        classDef bot fill:#1b2e2e,stroke:#00d4aa,color:#a0f0dd
        classDef human fill:#1b2e1e,stroke:#43b581,color:#a3d9b1
        classDef decision fill:#2e2618,stroke:#faa61a,color:#fdd87a
        classDef dropped fill:#2e1818,stroke:#f04747,color:#f8a0a0
        classDef processed fill:#1e1b4b,stroke:#5865F2,color:#c4b5fd
    
BEFORE — every bot message dropped, org is paralyzed
↓ FIX ↓
3

The Fix — @Mention Gate

RULE 1

Ignore Self

Never process your own messages. Prevents self-loops.

RULE 2

Require @mention

Bot messages only processed if they explicitly @mention this bot.

RULE 3

1 Bot Per Message

CEO @mentions only one bot at a time. Sequential, not parallel.

RULE 4

End = No @mention

Reply without @mention to close the conversation. Natural termination.

RULE 5

No Bot-to-Bot Direct

Bots don't talk to each other directly. Everything routes through CEO.

Fixed Code — One Change, All Bots Benefit
server.ts : line 803 (replace) — single file shared by all plugin instances
client.on('messageCreate', msg => {
  // Rule 1: ignore own messages   if (msg.author.id === client.user?.id) return
  // Rule 2: other bots must @mention this bot   if (msg.author.bot && !msg.mentions.has(client.user!.id)) return
  handleInbound(msg).catch(e => ...)
})
      graph TD
        A["Bot X sends message"]:::bot --> B{"From self?"}:::decision
        B -->|"Yes"| C["IGNORED"]:::dropped
        B -->|"No"| D{"Author is bot?"}:::decision
        D -->|"No — human"| E["handleInbound()"]:::processed
        D -->|"Yes"| F{"@mentions me?"}:::decision
        F -->|"No"| G["IGNORED — not my concern"]:::ignored
        F -->|"Yes"| E
        E --> H["Process + Reply"]:::ceo
        H --> I{"Need follow-up?"}:::decision
        I -->|"Yes — @mention them"| J["Conversation continues"]:::bot
        I -->|"No — plain reply"| K["Conversation ends"]:::success

        classDef bot fill:#1b2e2e,stroke:#00d4aa,color:#a0f0dd
        classDef ceo fill:#1e1b4b,stroke:#5865F2,color:#c4b5fd
        classDef decision fill:#2e2618,stroke:#faa61a,color:#fdd87a
        classDef dropped fill:#2e1818,stroke:#f04747,color:#f8a0a0
        classDef ignored fill:#1e1e2e,stroke:#555570,color:#8888a8
        classDef processed fill:#1e1b4b,stroke:#5865F2,color:#c4b5fd
        classDef success fill:#1b2e1e,stroke:#43b581,color:#a3d9b1
    
AFTER — @mention gate allows controlled bot-to-bot communication
4

Example — CEO Gathers Daily Report

C
CEO Bot
@Manager send me today's logs and status
M
Manager Bot
@CEO 3 deploys, 0 failures. Logs attached. payments-api latency up 12%.
C
CEO Bot
@Monitor check payments-api latency, is it degraded?
Mo
Monitor Bot
@CEO payments-api p99 at 340ms (normal: 200ms). Cause: connection pool saturation on db-replica-2.
C
CEO Bot
Daily summary: 3 deploys OK. payments-api latency elevated due to db-replica-2 pool saturation. Monitoring. conversation ended
CEO chains bots sequentially — Manager first, then Monitor. Ends with no @mention.
5

Implementation

1

Edit server.ts line 803

Replace if (msg.author.bot) return with the 2-line @mention gate. One file change covers all bots.

2

Restart all bot services

systemctl restart claude-discord.service and any other bot services to pick up the change.

3

Test with 2 bots first

Have CEO @mention Manager. Manager should see it and @mention CEO back. CEO processes, replies without @mention. Verify conversation ends.

4

Scale to 10+ bots

Each new bot just needs a Claude Code instance with the Discord plugin. The @mention protocol works the same regardless of how many bots are in the server.

CEO Bot
Specialist Bot
Success / End
Decision
Blocked
Human Owner
Scaling to 10+ bots. The @mention protocol is O(1) per bot — adding a new bot doesn't affect existing ones. Each bot only processes messages that @mention it, so 10 bots in a channel don't create 10x noise. The CEO Bot acts as the orchestrator: it knows which bot to ask for what, chains requests sequentially, and synthesizes the results into a single summary. No bot talks to another bot directly — everything routes through CEO.