From c5474cdb3d984c6c2d5c58ee8b29cc3f12c3dcc0 Mon Sep 17 00:00:00 2001 From: Mike Swanson Date: Wed, 20 May 2026 16:20:55 -0700 Subject: [PATCH] Session log: Discord bot instruction corrections Reverse the no-questions rule (bot can/should ask via persistent thread sessions), add a headless-operation constraint (no Chrome/credential windows/GUI auth at BEAST), and add a Task Loop (identify requester -> do work -> anything else? -> offer Syncro -> /save). Restarted the bot service to load the corrected system prompt. Co-Authored-By: Claude Opus 4.7 (1M context) --- projects/discord-bot/DISCORD_CLAUDE.md | 69 +++++++++---- .../session-logs/2026-05-20-session.md | 98 +++++++++++++++++++ 2 files changed, 150 insertions(+), 17 deletions(-) create mode 100644 projects/discord-bot/session-logs/2026-05-20-session.md diff --git a/projects/discord-bot/DISCORD_CLAUDE.md b/projects/discord-bot/DISCORD_CLAUDE.md index 1d8f1b5..ae5d816 100644 --- a/projects/discord-bot/DISCORD_CLAUDE.md +++ b/projects/discord-bot/DISCORD_CLAUDE.md @@ -5,28 +5,61 @@ You are the ClaudeTools Discord Bot, running as a Windows service on BEAST (GURU-BEAST-ROG). Working directory: `C:/Users/guru/ClaudeTools` -You are a fully capable Claude Code agent invoked by Discord messages. You complete tasks -autonomously and return results in a single turn. You are NOT the interactive coordinator -Claude — you have no back-and-forth loop. +You are a fully capable Claude Code agent invoked by Discord messages. Each Discord thread +is a persistent session: you keep full context across messages in that thread, so you can +hold a real back-and-forth conversation — ask a question, get the answer, and continue. +Complete the work, do not just describe it. --- -## CRITICAL: No Interactive Interaction +## You Can — and Should — Ask Questions -**You are running inside a Discord bot. There is no mechanism for mid-task clarification.** +The thread is a persistent session, so asking costs nothing: post the question as your +reply and the user's next message in the thread continues the same conversation with full +context. Ask when a request is ambiguous, when you are missing a detail you cannot derive, +or when a choice materially changes the outcome (especially anything that writes data, +touches a client tenant, or is hard to undo). -NEVER: -- Use AskUserQuestion or any interactive prompt -- Pause mid-task to ask "should I proceed?" or "which option?" -- Request confirmation before taking action -- Ask the user to supply information that is in the vault or derivable from context +- Ask in plain text. Do NOT call the AskUserQuestion tool — it does not render in Discord. +- Still prefer doing something reasonable over stalling on trivia. Do not ask for anything + already in the vault or derivable from context. +- A short clarifying question beats guessing wrong on a consequential action. -ALWAYS: -- State any assumption you made at the top of your response, then proceed -- Complete the full task in one turn -- If a task is genuinely impossible (e.g., requires info that doesn't exist anywhere), - state why clearly and stop — do not ask what to do next -- Prefer doing something reasonable over asking what to do +--- + +## CRITICAL: You Are Headless — No One Is at BEAST + +You run as a background Windows service. There is no human at the BEAST console. Any action +that opens a window and waits for someone to click or type into it will hang forever. + +NEVER attempt: +- Launching Chrome or any browser (including for OAuth or interactive sign-in) +- Opening a Windows credential prompt, UAC dialog, or any GUI authentication window +- 1Password / SOPS GUI unlock, or any desktop app that needs interactive input +- Any command that blocks on a console prompt no one can answer + +Instead: +- Pull credentials non-interactively from the SOPS vault (see Vault Access below) +- For a flow that genuinely needs a browser or interactive login, ASK the requester to do + that step on their own machine and report back, or use a non-interactive alternative + (device-code flow, app/client credentials, an API key already in the vault) +- State plainly which step needs a human at a machine, and who you need it from + +--- + +## Task Loop + +For every request, work this loop: + +1. **Identify the requester** — read the `[DISCORD_CONTEXT]` block (Discord username, display + name, ID) to determine who is asking, and address them by name. +2. **Do the work** — perform the action or answer the question. Ask clarifying questions in + the thread as needed; the session persists, so the conversation continues naturally. +3. **Anything else?** — when the task is done, ask: "Anything else for this one?" Keep + handling follow-ups in the same thread until the requester is satisfied. +4. **Offer Syncro** — once they have nothing else, ask whether to log the work in Syncro + ("Want me to log this in Syncro?"). If yes, invoke `/syncro` to create or update the ticket. +5. **Save** — after the loop closes, run `/save` to write the session log and sync the repo. --- @@ -120,10 +153,12 @@ stuffing", "foreign sign-in", "risky user", "oauth consent". ## After Every Completed Task -Run `/save` at the end of every completed task. The session log should include: +Close the task loop (see Task Loop above): confirm there is nothing else, offer to log the +work in Syncro, then run `/save`. The session log should include: - Who asked (Discord username + display name) - What was requested - What was done and the outcome +- Whether a Syncro ticket was created or updated (include the ticket number) - Vault paths accessed (paths only, never credential values) This creates an audit trail and keeps the repo in sync. diff --git a/projects/discord-bot/session-logs/2026-05-20-session.md b/projects/discord-bot/session-logs/2026-05-20-session.md new file mode 100644 index 0000000..52fdf2b --- /dev/null +++ b/projects/discord-bot/session-logs/2026-05-20-session.md @@ -0,0 +1,98 @@ +# Discord Bot — Instruction Corrections — 2026-05-20 + +## User +- **User:** Mike Swanson (mike) +- **Machine:** GURU-BEAST-ROG +- **Role:** admin + +## Session Summary +The session began with a repository sync, pulling 41 commits initially and 9 additional +commits mid-session, including the Cascades-Tucson migration phase 2.6 work, M365 +offboarding for britney.thompson, a new `/forum-post` command, and a fix to the +`check-messages.sh` hook path. The SOPS vault was also synced (MSP360 Managed Backup +API credentials added in a prior session). The Discord bot operating instructions were +reviewed and internalized, then the `ClaudeToolsDiscordBot` Windows service was restarted +so the newly pulled bot code and rules took effect. + +Following a user request to correct the bot's behavior, the bot architecture was +investigated by reading `bot/config.py`, `bot/claude/client.py`, and +`bot/handlers/message_handler.py`. This revealed that `DISCORD_CLAUDE.md` is the agent +`system_prompt`, loaded ONCE at bot startup (`ClaudeAgentManager.__init__` -> +`_load_system_prompt`), and that each Discord thread is a persistent `ClaudeSDKClient` +session kept in `self._agents[thread_id]`. Multi-turn back-and-forth was therefore already +supported by the architecture — the prior "single turn / never ask questions" rule was an +unnecessary self-restriction, not a real limitation. + +Three edits were made to `DISCORD_CLAUDE.md` to reverse the no-interaction rule, add a +headless-operation constraint, and define a structured task loop. Because the system prompt +loads only at startup, the bot service was restarted to load the corrected instructions; +reconnection to the Arizona Computer Guru guild was confirmed with a clean stderr. + +## Key Decisions +- **Reversed the no-interaction rule.** The bot may and should ask clarifying questions in + plain text. Rationale: the thread is a persistent session, so a follow-up message + continues the same conversation with full context — asking costs nothing and prevents + wrong guesses on consequential actions. The `AskUserQuestion` tool is explicitly excluded + because it does not render in Discord. +- **Added a "You Are Headless" constraint.** The bot runs as a background Windows service + with no human at the BEAST console, so any GUI/interactive prompt (Chrome/browser, OAuth + sign-in window, Windows credential prompt, UAC dialog, 1Password/SOPS GUI unlock) would + hang forever. The bot must pull credentials non-interactively from the SOPS vault, or ask + the requester to perform the interactive step on their own machine and report back. +- **Introduced a Task Loop.** Standardized flow: identify the requester from + `[DISCORD_CONTEXT]` -> do the work (asking questions as needed) -> ask "anything else?" + -> offer to log in Syncro (`/syncro`) -> `/save`. The "After Every Completed Task" section + was updated to match (now records whether a Syncro ticket was created/updated). + +## Problems Encountered +- None. Both bot restarts succeeded and the service reconnected cleanly each time. + +## Configuration Changes +Files modified: +- `projects/discord-bot/DISCORD_CLAUDE.md` — 3 edits (+52 / -17): + 1. Intro paragraph: replaced "single turn / no back-and-forth loop" with persistent-session + framing. + 2. Replaced `## CRITICAL: No Interactive Interaction` with two sections: + `## You Can — and Should — Ask Questions` and `## CRITICAL: You Are Headless — No One + Is at BEAST`, plus a new `## Task Loop` section. + 3. Updated `## After Every Completed Task` to reference the loop and the Syncro ticket field. + +No code files were changed. No vault files or `.claude/identity.json` touched. + +## Commands & Outputs +- `nssm restart ClaudeToolsDiscordBot` — run twice (first after the start-of-session sync to + load pulled bot code; second after editing the instructions). Both: STOP + START succeeded, + service `Running`. +- Post-restart verification (second restart): stdout showed guild channel enumeration at + `2026-05-20 16:19:04` (the bot "ready" sequence); stderr empty. + +## Infrastructure & Services +- **Machine:** GURU-BEAST-ROG (BEAST) — Windows 11 Pro +- **Service:** `ClaudeToolsDiscordBot` (NSSM, StartType Automatic), runs the Discord bot +- **nssm:** `C:\Users\guru\AppData\Local\Microsoft\WinGet\Links\nssm.exe` +- **Bot working dir / agent cwd:** `C:/Users/guru/ClaudeTools` +- **Bot model:** `claude-sonnet-4-6` (per `bot/config.py`) +- **Bot logs:** `projects/discord-bot/logs/stdout.log`, `stderr.log` +- **Discord guild:** Arizona Computer Guru (id `624663750603046913`), 11 channels + +## Credentials +- None used, discovered, or changed this session. The bot authenticates via its Discord + token (in `projects/discord-bot/.env`, gitignored) and either the local Claude Code OAuth + credential or `ANTHROPIC_API_KEY`; none were read or modified here. + +## Reference Information +- Bot architecture (verified this session): + - System prompt source: `projects/discord-bot/DISCORD_CLAUDE.md` (config key + `discord_system_prompt`, relative to `claudetools_root`) + - Loaded ONCE at startup in `ClaudeAgentManager.__init__` -> `client.py:_load_system_prompt()` + — **editing it requires a bot restart to take effect** + - One persistent `ThreadAgent` (`ClaudeSDKClient`) per Discord `thread_id`; follow-up + messages reuse the same client, preserving conversation history + - Caller identity injected as `[DISCORD_CONTEXT]` header in `message_handler.py` +- Restart command: `nssm restart ClaudeToolsDiscordBot` + +## Pending / Next Steps +- None outstanding for the bot. New rules are live as of the 16:19 restart. +- Untracked pre-existing items in the repo (NOT part of this session, left as-is): + `clients/internal-infrastructure/datto-bsod-case-2026-05-16*`, + `clients/valleywide/app-modernization/source-analysis/D-drive-*.csv`.