--- title: "Claude Agent Discord Notifications" description: "Setup guide for the n8n workflow that sends Discord notifications when Claude Code subagents finish. Covers SubagentStop hook config, n8n webhook setup, Discord variable storage, payload reference, and testing." type: guide domain: productivity tags: [n8n, claude-code, discord, webhook, subagent, notifications, automation] --- # Claude Agent Done → Discord Notifications Notifies a Discord channel via webhook when a Claude Code subagent finishes. Useful for long-running pipelines (10+ minutes) where you want a heads-up when work completes. ## Architecture ``` Claude Code (SubagentStop hook) │ │ POST raw event JSON ▼ n8n Webhook: /webhook/claude-agent-done │ │ Extract agent name, build message ▼ Discord Webhook (stored as n8n variable) │ ▼ "🏁 Claude agent **{name}** has finished." ``` ### Why n8n as the middle layer? Claude Code HTTP hooks send raw event JSON — you can't customize the body. Discord requires `{"content": "..."}`. n8n does the transformation and keeps the Discord webhook URL out of local config files. ## Setup ### 1. n8n workflow Import `claude-agent-done.json` into n8n: 1. n8n → Workflows → Import from File → select `claude-agent-done.json` 2. Set the workflow to **Active** 3. Note the production webhook URL: `http://10.10.0.210:5678/webhook/claude-agent-done` ### 2. Discord webhook 1. Open the target Discord channel → Edit Channel → Integrations → Webhooks → New Webhook 2. Copy the webhook URL ### 3. n8n variable Store the Discord URL so it stays out of config files: 1. n8n → Settings → Variables → Add Variable 2. **Key:** `DISCORD_CLAUDE_ALERTS_WEBHOOK` 3. **Value:** your Discord webhook URL ### 4. Claude Code hook config The hook is configured in `.claude/settings.json` at the repo root: ```json { "hooks": { "SubagentStop": [ { "type": "http", "url": "http://localhost:5678/webhook/claude-agent-done", "async": true } ] } } ``` > **Note:** Update `localhost:5678` to match your n8n host if running remotely (e.g. `http://10.10.0.210:5678`). ## Testing Send a test payload to verify the pipeline end-to-end: ```bash curl -X POST http://10.10.0.210:5678/webhook-test/claude-agent-done \ -H "Content-Type: application/json" \ -d '{"hook_event_name": "SubagentStop", "session_id": "abc12345", "subagent_name": "test-agent"}' ``` Switch to `/webhook/` (not `/webhook-test/`) once confirmed working. ## Payload reference Claude Code sends a JSON payload on `SubagentStop`. Known fields: | Field | Description | |-------|-------------| | `hook_event_name` | Always `"SubagentStop"` | | `session_id` | Agent session identifier | | `subagent_name` | Name of the subagent (if set) | The n8n workflow uses `subagent_name` if present, falling back to the first 8 chars of `session_id`. ## Future extensions - Route different agent names to different Discord channels - Add rich embeds with duration and success/failure status - Filter by agent name (only notify for specific long-running pipelines) - Route to local TTS/voice server for audio alerts ## Change Log ### 2026-03-04 - Initial setup - Created n8n webhook workflow (`claude-agent-done.json`) - Added `SubagentStop` HTTP hook to `.claude/settings.json` - Discord webhook URL stored as n8n variable `DISCORD_CLAUDE_ALERTS_WEBHOOK`