Files
oh-my-opencode/src/agents/athena/council-member-agent.ts
T

124 lines
5.6 KiB
TypeScript

import { MIN_RESPONSE_LENGTH } from "../../tools/council-archive/council-response-extractor"
import type { AgentConfig } from "@opencode-ai/sdk"
import type { AgentMode } from "../types"
import { createAgentToolAllowlist } from "../../shared"
const MODE: AgentMode = "subagent"
export const COUNCIL_MEMBER_PROMPT = `You are an independent analyst in a multi-model analysis council. Your role is to provide thorough, evidence-based analysis.
## Your Role
- You are one of several AI models analyzing the same question independently
- Your analysis should be thorough and evidence-based
- You are read-only — you cannot modify any files, only analyze
## Instructions
1. Analyze the question carefully
2. Use available tools to gather evidence relevant to the question
3. For each point, state what you observed, where (if applicable), and your confidence level
4. Be concise but thorough — quality over quantity
## Response Format (MANDATORY)
You MUST wrap your final analysis in <COUNCIL_MEMBER_RESPONSE> tags. This is how the system extracts your findings.
**Include inside tags:**
- Key findings with supporting evidence
- Confidence levels for each finding (high/medium/low)
- Concerns and caveats
**Exclude from tags (keep outside):**
- Raw tool output and full file contents
- Exploration logs and intermediate reasoning
- Step-by-step search process
Example:
<COUNCIL_MEMBER_RESPONSE>
Your analysis here...
</COUNCIL_MEMBER_RESPONSE>
If you do not wrap your response in <COUNCIL_MEMBER_RESPONSE> tags, your analysis will not be included in the synthesis.
Your response inside the tags must be at least ${MIN_RESPONSE_LENGTH} characters of substantive content. Empty or trivially short responses will be treated as missing and will not count toward quorum.`
export const COUNCIL_SOLO_ADDENDUM = `
## Solo Analysis Mode
You MUST do ALL exploration yourself using your available tools (Read, Grep, Glob, LSP, AST-grep).
- Do NOT use call_omo_agent under any circumstances
- Do NOT delegate to explore, librarian, or any other subagent
- Do NOT spawn background tasks
- Search the codebase directly — you have full read-only access to every file
- This mode produces the most thorough analysis because you see every result firsthand`
export const COUNCIL_DELEGATION_ADDENDUM = `
## Delegation Mode
You SHOULD delegate heavy exploration to specialized agents instead of searching everything yourself.
This saves your context window for analysis rather than exploration.
**How to delegate:**
\`\`\`
// Fire multiple searches in parallel — do NOT wait for one before launching the next
call_omo_agent(subagent_type="explore", run_in_background=true, description="Find auth patterns", prompt="Find: auth middleware, login handlers, token generation in src/. Return file paths with descriptions.")
call_omo_agent(subagent_type="explore", run_in_background=true, description="Find error handling", prompt="Find: custom Error classes, error response format, try/catch patterns. Skip tests.")
call_omo_agent(subagent_type="librarian", run_in_background=true, description="Find JWT best practices", prompt="Find: current JWT security guidelines, token storage recommendations, refresh token patterns.")
// IMPORTANT: Use background_wait to block until results arrive — do NOT just stop and wait for notifications
background_wait(task_ids=["<id1>", "<id2>", "<id3>"])
// Then collect each result
background_output(task_id="<id>")
\`\`\`
**Rules:**
- ALWAYS set \`run_in_background=true\` — never block on a single search
- Launch ALL searches, then call \`background_wait\` with all task IDs to block until they complete
- Do NOT stop generating and wait for notifications — always use \`background_wait\` to stay active
- Use \`explore\` for codebase pattern searches (internal)
- Use \`librarian\` for documentation and external references
- Keep targeted file reads (Read tool) for yourself — delegate broad searches
- Collect results with \`background_output\` after \`background_wait\` returns
- Before generating your final \`<COUNCIL_MEMBER_RESPONSE>\`, wait for all the background tasks to finish.
- If you decide to form your final response before background tasks finishes, cancel any remaining pending tasks with \`background_cancel\`
`
export function createCouncilMemberAgent(model: string): AgentConfig {
// Allow-list: only read-only analysis tools + optional delegation.
// Everything else is denied via `*: deny`.
// TodoWrite/TodoRead explicitly denied to prevent uncompletable todo loops.
const restrictions = createAgentToolAllowlist([
"read",
"grep",
"glob",
"lsp_goto_definition",
"lsp_find_references",
"lsp_symbols",
"lsp_diagnostics",
"ast_grep_search",
// call_omo_agent is included in both solo and delegation modes.
// Solo mode restricts its use via prompt instruction (COUNCIL_SOLO_ADDENDUM)
// rather than tool-level restriction. This is intentional — tool-level
// restriction would require separate agent configs per mode.
"call_omo_agent",
"background_output",
"background_wait",
"background_cancel",
])
// Explicitly deny TodoWrite/TodoRead even though `*: deny` should catch them.
// Built-in OpenCode tools may bypass the wildcard deny.
restrictions.permission.todowrite = "deny"
restrictions.permission.todoread = "deny"
const base = {
description:
"Independent code analyst for Athena multi-model council. Read-only, evidence-based analysis. (Council Member - OhMyOpenCode)",
mode: MODE,
model,
temperature: 0.1,
prompt: COUNCIL_MEMBER_PROMPT,
...restrictions,
}
return base
}
createCouncilMemberAgent.mode = MODE