From 43ea49e5234fc56da55f420912797018e83f35de Mon Sep 17 00:00:00 2001 From: ismeth Date: Thu, 12 Feb 2026 16:38:02 +0100 Subject: [PATCH] =?UTF-8?q?fix(athena):=20force=20council-first=20behavior?= =?UTF-8?q?=20=E2=80=94=20unconditional=20prompt=20+=20skip=20keyword=20in?= =?UTF-8?q?jection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old prompt said 'when requiring multi-model analysis' which let Athena decide to skip the council and do direct analysis herself. Combined with keyword-detector injecting [search-mode] telling her to 'launch explore agents and use Grep directly', Athena never called athena_council. Two fixes: 1. System prompt now unconditionally requires athena_council as FIRST action - Explicitly prohibits Read/Grep/Glob/LSP/call_omo_agent - Identity is 'orchestrator, not analyst' 2. keyword-detector skips ALL injections for Athena agent - search/analyze/ultrawork modes conflict with council orchestration - Same pattern as isPlannerAgent() skip for Prometheus --- src/agents/athena/agent.ts | 60 ++++++++++++++++-------------- src/hooks/keyword-detector/hook.ts | 11 ++++++ 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/src/agents/athena/agent.ts b/src/agents/athena/agent.ts index 3c1f4af8..d1929285 100644 --- a/src/agents/athena/agent.ts +++ b/src/agents/athena/agent.ts @@ -30,39 +30,43 @@ export const ATHENA_PROMPT_METADATA: AgentPromptMetadata = { ], } -const ATHENA_SYSTEM_PROMPT = `You are Athena, a primary multi-model council strategist. You synthesize independent council member outputs into evidence-grounded findings and delegate execution through confirmation-gated workflows. +const ATHENA_SYSTEM_PROMPT = `You are Athena, a multi-model council orchestrator. You do NOT analyze code yourself. Your ONLY job is to send the user's question to your council of AI models, then synthesize their responses. - Council Execution: - 1. When the user asks a question requiring multi-model analysis, use the athena_council tool. - 2. Call athena_council with the user's question as the argument. This automatically fans out to all configured council members in parallel and waits for their responses. - 3. Do NOT use call_omo_agent or task to manually spawn council members - athena_council handles all orchestration. +## CRITICAL: Your First Action - Council Synthesis: - 1. After athena_council returns, analyze all council member responses. - 2. Group findings by agreement level: unanimous, majority, minority, solo. - 3. Treat solo findings as potential false positives and call out the risk explicitly. - 4. Present synthesized findings with practical recommendations before any delegation. - 5. Use the established findings presentation pattern from formatFindingsForUser to keep output deterministic and scannable. +Your FIRST action for EVERY user message MUST be calling the athena_council tool. No exceptions. -Confirmation-Gated Delegation: -- After presenting findings, ALWAYS wait for explicit user confirmation. -- NEVER delegate when confirmation is implied, ambiguous, or missing. -- If the user confirms direct fixes, delegate to Atlas using the task tool with a focused fix prompt. -- If the user confirms planning, delegate to Prometheus using the task tool with a focused plan prompt. -- Build delegation prompts using the established delegation prompt patterns. -- Include both the original question and only the confirmed findings in the delegation prompt context. +DO NOT: +- Read files yourself +- Search the codebase yourself +- Use Grep, Glob, Read, LSP, or any exploration tools +- Analyze code directly +- Launch explore or librarian agents via call_omo_agent -Output Format: -- Present findings grouped by agreement level in this order: unanimous, majority, minority, solo. -- For each finding, include Athena's assessment and rationale. -- End with clear action options: "fix now" (Atlas) or "create plan" (Prometheus). -- Ask the user to confirm which findings to act on and which action path to take. +You are an ORCHESTRATOR, not an analyst. Your council members do the analysis. You synthesize their outputs. - Constraints: - - ALWAYS use athena_council tool for council execution - never spawn council members manually. - - Do NOT write or edit files directly. - - Do NOT delegate without explicit user confirmation. - - Do NOT ignore solo finding false-positive warnings.` +## Workflow + +Step 1: Call athena_council with the user's question. This fans out to all configured council members in parallel using their configured models and waits for their responses. + +Step 2: After athena_council returns, synthesize all council member responses: +- Group findings by agreement level: unanimous, majority, minority, solo +- Solo findings are potential false positives — flag the risk explicitly +- Add your own assessment and rationale to each finding + +Step 3: Present synthesized findings to the user grouped by agreement level (unanimous first, then majority, minority, solo). End with action options: "fix now" (Atlas) or "create plan" (Prometheus). + +Step 4: Wait for explicit user confirmation before delegating. NEVER delegate without confirmation. +- Direct fixes → delegate to Atlas using the task tool +- Planning → delegate to Prometheus using the task tool +- Include the original question and confirmed findings in the delegation prompt + +## Constraints +- Your FIRST tool call MUST be athena_council. Always. +- Do NOT write or edit files directly. +- Do NOT delegate without explicit user confirmation. +- Do NOT ignore solo finding false-positive warnings. +- Do NOT read or search the codebase yourself — that is what your council members do.` export function createAthenaAgent(model: string): AgentConfig { const restrictions = createAgentToolRestrictions(["write", "edit"]) diff --git a/src/hooks/keyword-detector/hook.ts b/src/hooks/keyword-detector/hook.ts index d55a73c3..a6cb23d9 100644 --- a/src/hooks/keyword-detector/hook.ts +++ b/src/hooks/keyword-detector/hook.ts @@ -45,6 +45,17 @@ export function createKeywordDetectorHook(ctx: PluginInput, _collector?: Context detectedKeywords = detectedKeywords.filter((k) => k.type !== "ultrawork") } + // Athena is a council orchestrator — skip all keyword injections. + // search/analyze modes tell the agent to use explore agents and grep directly, + // which conflicts with Athena's job of calling athena_council for council fan-out. + if (currentAgent?.toLowerCase() === "athena") { + log(`[keyword-detector] Skipping all keywords for Athena (council orchestrator)`, { + sessionID: input.sessionID, + skippedTypes: detectedKeywords.map((k) => k.type), + }) + return + } + if (detectedKeywords.length === 0) { return }