2026-03-02 00:45:39 +01:00
import { MIN_RESPONSE_LENGTH } from "../../tools/council-archive/council-response-extractor"
2026-02-17 12:33:49 +01:00
import type { AgentConfig } from "@opencode-ai/sdk"
import type { AgentMode } from "../types"
2026-02-23 12:46:44 +01:00
import { createAgentToolAllowlist } from "../../shared"
2026-02-17 12:33:49 +01:00
const MODE : AgentMode = "subagent"
2026-02-27 16:46:23 +01:00
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.
2026-02-19 02:21:09 +01:00
## 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
2026-02-27 16:46:23 +01:00
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
2026-02-23 19:42:56 +01:00
2026-02-26 12:38:15 +01:00
## 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:**
2026-02-27 16:46:23 +01:00
- Key findings with supporting evidence
2026-02-26 12:38:15 +01:00
- 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
2026-03-01 11:28:52 +01:00
Example:
<COUNCIL_MEMBER_RESPONSE>
Your analysis here...
</COUNCIL_MEMBER_RESPONSE>
2026-03-01 16:48:12 +01:00
If you do not wrap your response in <COUNCIL_MEMBER_RESPONSE> tags, your analysis will not be included in the synthesis.
2026-03-02 00:45:39 +01:00
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. `
2026-02-23 19:42:56 +01:00
2026-02-24 12:14:15 +01:00
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 `
2026-02-23 19:42:56 +01:00
export const COUNCIL_DELEGATION_ADDENDUM = `
## Delegation Mode
2026-02-24 12:14:15 +01:00
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.")
2026-02-28 00:50:23 +01:00
// 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
2026-02-24 12:14:15 +01:00
background_output(task_id="<id>")
\` \` \`
**Rules:**
- ALWAYS set \` run_in_background=true \` — never block on a single search
2026-02-28 00:50:23 +01:00
- 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
2026-02-24 12:14:15 +01:00
- 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
2026-02-28 00:50:23 +01:00
- Collect results with \` background_output \` after \` background_wait \` returns
2026-02-28 20:26:35 +01:00
- 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 \`
`
2026-02-17 12:33:49 +01:00
export function createCouncilMemberAgent ( model : string ) : AgentConfig {
2026-02-23 19:42:56 +01:00
// Allow-list: only read-only analysis tools + optional delegation.
// Everything else is denied via `*: deny`.
// TodoWrite/TodoRead explicitly denied to prevent uncompletable todo loops.
2026-02-23 12:46:44 +01:00
const restrictions = createAgentToolAllowlist ( [
"read" ,
"grep" ,
"glob" ,
"lsp_goto_definition" ,
"lsp_find_references" ,
"lsp_symbols" ,
"lsp_diagnostics" ,
"ast_grep_search" ,
2026-03-01 02:52:42 +01:00
// 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.
2026-02-23 19:42:56 +01:00
"call_omo_agent" ,
2026-02-24 01:48:18 +01:00
"background_output" ,
2026-02-28 00:50:23 +01:00
"background_wait" ,
"background_cancel" ,
2026-02-18 20:55:19 +01:00
] )
2026-02-23 19:42:56 +01:00
// 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"
2026-02-18 23:32:08 +01:00
const base = {
description :
"Independent code analyst for Athena multi-model council. Read-only, evidence-based analysis. (Council Member - OhMyOpenCode)" ,
2026-02-17 12:33:49 +01:00
mode : MODE ,
model ,
temperature : 0.1 ,
prompt : COUNCIL_MEMBER_PROMPT ,
2026-02-18 20:55:19 +01:00
. . . restrictions ,
2026-02-18 23:32:08 +01:00
}
2026-02-26 15:12:57 +01:00
return base
2026-02-17 12:33:49 +01:00
}
createCouncilMemberAgent . mode = MODE