Skip to content

Discord Integration

Discord serves as Aegis's primary communication channel for status updates, notifications, and autonomous task reception.

Configuration

Guild ID: 1454722052777836546 Bot Token: Stored in ~/.claude.json at mcpServers.discord.env.DISCORD_BOT_TOKEN

# Token value
MTQ1NDcxNTUzOTQ4OTI5MjQyOQ.GemVa6._uWh_V9Mt8UUWVJahpcAUv9dRacuZ-q_CLkjjI

Channels

Channel ID Purpose
#general 1454722053495324844 General updates and conversations
#scratchpad 1457830898681516137 Unstructured ideas and thoughts
#logs 1455049129313959937 System logs and debug output
#alerts 1455049130614329508 Critical system alerts
#journal 1455049131725816023 Daily journal entries
#tasks 1455049133189627926 Task requests and execution
#decisions 1460610168118055006 Architectural and strategic decisions

MCP Tools

The Discord MCP server provides the following tools:

Message Posting

# Send message to a channel
mcp__discord__discord_send_message(
    channel_id="1454722053495324844",  # #general
    content="Hello from Aegis"
)

Authentication

# Login (usually automatic, but can be called manually if needed)
mcp__discord__discord_login(
    token="MTQ1NDcxNTUzOTQ4OTI5MjQyOQ.GemVa6._uWh_V9Mt8UUWVJahpcAUv9dRacuZ-q_CLkjjI"
)

Task Polling System

The DiscordTaskPoller provides autonomous task reception from #tasks channel.

Location: /home/agent/projects/aegis-core/aegis/discord/task_poller.py

Features

  • Polls #tasks channel for !task prefixed messages
  • Tracks last processed message ID in database
  • Filters out bot messages
  • Queues tasks for execution
  • Can trigger Claude Code sessions

Database Schema

CREATE TABLE discord_tasks (
    id SERIAL PRIMARY KEY,
    message_id VARCHAR(64) UNIQUE NOT NULL,
    content TEXT NOT NULL,
    author_id VARCHAR(64) NOT NULL,
    author_name VARCHAR(128) NOT NULL,
    status VARCHAR(32) DEFAULT 'pending',
    result TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    completed_at TIMESTAMPTZ
);

Usage

from aegis.discord import DiscordTaskPoller

poller = DiscordTaskPoller()

# Run a poll cycle
stats = poller.run_poll_cycle()
# Returns: {"tasks_found": 2, "tasks_processed": 2, "duration_ms": 1234}

# Get pending tasks
pending = poller.get_pending_tasks()

Task Format

Users post tasks in #tasks with the !task prefix:

!task Deploy nginx to production with Traefik routing

The poller: 1. Detects the message 2. Queues it in discord_tasks table 3. Sends acknowledgment reply 4. Triggers Claude Code session (via tmux if available)

Daily Workflow

Morning Updates

Post to #journal:

mcp__discord__discord_send_message(
    channel_id="1455049131725816023",
    content=f"☀️ **Morning Check - {date}**\n\n{system_status}"
)

Evening Summaries

Post to #journal:

mcp__discord__discord_send_message(
    channel_id="1455049131725816023",
    content=f"🌙 **Evening Summary - {date}**\n\n{daily_summary}"
)

Error Escalations

Post to #alerts after three-strike protocol:

mcp__discord__discord_send_message(
    channel_id="1455049130614329508",
    content=f"🔴 **Error Escalation**\n\n{error_details}"
)

Strategic Decisions

Post to #decisions:

mcp__discord__discord_send_message(
    channel_id="1460610168118055006",
    content=f"🎯 **Decision: {title}**\n\n{reasoning}"
)

Troubleshooting

Login Failures

If discord_login fails with "token not configured", pass token directly:

mcp__discord__discord_login(
    token="MTQ1NDcxNTUzOTQ4OTI5MjQyOQ.GemVa6._uWh_V9Mt8UUWVJahpcAUv9dRacuZ-q_CLkjjI"
)

Rate Limits

Discord enforces rate limits: - 5 messages per 5 seconds per channel - 50 messages per second globally

Use batch operations when posting multiple messages.

Best Practices

  1. Channel Selection: Use appropriate channels (logs for debugging, alerts for critical issues)
  2. Formatting: Use Discord markdown for readability
  3. Context: Include relevant links and IDs in messages
  4. Batching: Combine related updates into single messages when possible
  5. Error Handling: Always wrap Discord calls in try/except to avoid workflow failures