# LLM Council

> **Greek:** Synedrion (Synedrion) — "assembly/council"
> **Sanskrit:** Sabha (Sabha) — "assembly/council"
> **Tagline:** *"Many minds, one recommendation"*

---

## Agent Identity

| Field | Value |
|---|---|
| ID | `llm_council` |
| Name | LLM Council |
| Phase | N/A — Horizontal (not pipeline-bound) |
| Type | `horizontal` |
| Granularity | `global` |
| Interaction | `interactive` |
| Mode | `all` |
| Domain | `dev` |

---

## Goal & Objectives

**Goal:** Provide on-demand multi-perspective analysis of any artifact, design decision, architecture question, or code review request by running a configurable panel of independent expert personas that reason separately and then synthesizing their outputs into a unified recommendation that highlights consensus, disagreements, and a final confidence-weighted suggestion.

| Priority | Objective |
|---|---|
| primary | Run multiple expert personas independently against the user's question or artifact, ensuring each persona reasons from its unique perspective without cross-contamination from other personas |
| secondary | Produce a synthesis that merges all persona outputs into a unified recommendation, explicitly surfacing areas of agreement, disagreement, and minority opinions rather than averaging them away |
| tertiary | Support custom user-defined personas beyond the default panel, allowing the user to tailor the council composition to specific domains or concerns relevant to their current decision |

---

## Inputs

### User Query / Context
- **Source:** User (interactive input) -> session context
- **Required:** yes
- **Shape:**
```json
{
  "session_id": {
    "type": "string",
    "description": "Unique session identifier for this council invocation, auto-generated",
    "example": "COUNCIL-2026-03-21-001"
  },
  "question": {
    "type": "string",
    "description": "The question or topic the user wants the council to evaluate",
    "example": "Should we use JWT or session-based authentication for this application?"
  },
  "context": {
    "type": "string | null",
    "description": "Additional context provided by the user — can be free text, a summary of the current state, or a reference to an artifact",
    "example": "We are building a multi-tenant SaaS application with 5 modules. Auth module handles login, registration, and OAuth. Expected scale: 10K concurrent users."
  },
  "artifact_refs": {
    "type": "array",
    "description": "References to pipeline artifacts the council should consider",
    "items": {
      "artifact_path": {
        "type": "string",
        "description": "Path to the artifact file",
        "example": "agent_output/contracts/auth/openapi.json"
      },
      "artifact_type": {
        "type": "string",
        "description": "Type of artifact for context",
        "example": "be_contract"
      }
    }
  },
  "selected_personas": {
    "type": "array",
    "description": "Which personas the user wants to participate in this session — if empty, all default personas are used",
    "items": {
      "type": "string"
    },
    "example": ["security_advisor", "scalability_architect", "devops_pragmatist"]
  },
  "custom_personas": {
    "type": "array | null",
    "description": "User-defined custom personas for this session, null if only using defaults",
    "items": {
      "name": {
        "type": "string",
        "description": "Custom persona display name",
        "example": "Compliance Officer"
      },
      "role": {
        "type": "string",
        "description": "Role description",
        "example": "Regulatory Compliance Evaluator"
      },
      "perspective": {
        "type": "string",
        "description": "What perspective this persona evaluates from",
        "example": "Evaluates decisions from GDPR, HIPAA, and SOC2 compliance requirements"
      },
      "expertise_areas": {
        "type": "array",
        "description": "Specific areas of expertise",
        "items": { "type": "string" },
        "example": ["data privacy", "audit trails", "data residency", "consent management"]
      }
    }
  }
}
```

### Pipeline State (optional)
- **Source:** `orchestrator` -> `audit.json`
- **Required:** no (council can be invoked with just a question)
- **Shape:**
```json
{
  "run_id": {
    "type": "string",
    "description": "Current pipeline run identifier",
    "example": "run-2026-03-21-001"
  },
  "current_phase": {
    "type": "number",
    "description": "Phase the pipeline is currently in",
    "example": 7
  },
  "modules": {
    "type": "array",
    "description": "List of modules and their current state",
    "items": {
      "module_id": { "type": "string", "example": "auth" },
      "current_phase": { "type": "number", "example": 7 },
      "status": { "type": "string", "enum": ["pending", "in_progress", "completed", "failed"], "example": "completed" }
    }
  },
  "completed_artifacts": {
    "type": "array",
    "description": "List of artifacts completed so far in this run",
    "items": { "type": "string" },
    "example": ["analysis_output.json", "user_stories_auth.json", "fe_details_auth.json"]
  }
}
```

### Referenced Artifacts (dynamic)
- **Source:** Any pipeline agent -> artifact files referenced by user
- **Required:** no (depends on user's artifact_refs)
- **Shape:**
```json
{
  "description": "Any artifact from the pipeline that the user references — shape varies by artifact type. The council reads the full artifact content and includes it in each persona's evaluation context."
}
```

---

## Outputs

### council_session.json
- **Path:** `agent_output/council/council_session_{session_id}.json`
- **Format:** `json`
- **Consumers:** User (dashboard display), `orchestrator` (logging), future council sessions (reference)
- **Shape:**
```json
{
  "session_id": {
    "type": "string",
    "description": "Unique session identifier",
    "example": "COUNCIL-2026-03-21-001"
  },
  "timestamp": {
    "type": "string",
    "description": "ISO-8601 timestamp of session",
    "example": "2026-03-21T14:30:00Z"
  },
  "question": {
    "type": "string",
    "description": "The question or topic evaluated",
    "example": "Should we use JWT or session-based authentication for this application?"
  },
  "context": {
    "type": "string | null",
    "description": "Additional context provided by the user"
  },
  "artifact_refs": {
    "type": "array",
    "description": "Artifacts that were referenced",
    "items": {
      "artifact_path": { "type": "string" },
      "artifact_type": { "type": "string" }
    }
  },
  "personas_used": {
    "type": "array",
    "description": "List of persona names that participated in this session",
    "items": { "type": "string" },
    "example": ["Security Advisor", "Scalability Architect", "DevOps Pragmatist"]
  },
  "persona_responses": {
    "type": "array",
    "description": "Independent responses from each persona — each reasoned in isolation without seeing other responses",
    "items": {
      "persona_name": {
        "type": "string",
        "description": "Name of the persona",
        "example": "Security Advisor"
      },
      "persona_role": {
        "type": "string",
        "description": "Role description of the persona",
        "example": "Evaluates from security perspective"
      },
      "perspective": {
        "type": "string",
        "description": "The lens through which this persona evaluated the question",
        "example": "Security implications, attack vectors, token management, session hijacking risks"
      },
      "analysis": {
        "type": "string",
        "description": "Detailed analysis from this persona's perspective — reasoning, trade-offs, considerations",
        "example": "JWT tokens are stateless and scalable but cannot be revoked without additional infrastructure (token blacklist). Session-based auth provides immediate revocation but requires centralized session store..."
      },
      "recommendations": {
        "type": "array",
        "description": "Specific recommendations from this persona",
        "items": {
          "type": "string"
        },
        "example": [
          "Use short-lived JWTs (15 min) with refresh token rotation for API authentication",
          "Implement token blacklist using Redis for immediate revocation capability",
          "Store refresh tokens server-side with device fingerprinting"
        ]
      },
      "concerns": {
        "type": "array",
        "description": "Specific concerns raised by this persona",
        "items": {
          "type": "string"
        },
        "example": [
          "JWT token size grows with claims — monitor payload size for mobile clients",
          "Refresh token rotation must handle race conditions in concurrent requests"
        ]
      },
      "confidence": {
        "type": "number",
        "description": "Persona's confidence in their recommendation (0.0 to 1.0)",
        "example": 0.85
      }
    }
  },
  "synthesis": {
    "type": "object",
    "description": "Merged recommendation from all persona outputs",
    "fields": {
      "merged_recommendation": {
        "type": "string",
        "description": "The synthesized recommendation that accounts for all persona perspectives",
        "example": "Use JWT-based authentication with short-lived access tokens (15 min) and server-side refresh tokens. Implement Redis-based token blacklist for revocation. This balances scalability (JWT), security (short TTL + blacklist), and operational simplicity (Redis is already in the stack for caching)."
      },
      "consensus_areas": {
        "type": "array",
        "description": "Areas where all (or most) personas agreed",
        "items": {
          "area": {
            "type": "string",
            "description": "Topic of consensus",
            "example": "Short-lived tokens are essential regardless of JWT vs session approach"
          },
          "agreeing_personas": {
            "type": "array",
            "items": { "type": "string" },
            "example": ["Security Advisor", "Scalability Architect", "DevOps Pragmatist"]
          }
        }
      },
      "disagreement_areas": {
        "type": "array",
        "description": "Areas where personas disagreed — these are explicitly surfaced, not hidden",
        "items": {
          "area": {
            "type": "string",
            "description": "Topic of disagreement",
            "example": "Token storage mechanism on client side"
          },
          "positions": {
            "type": "array",
            "description": "Different positions held by different personas",
            "items": {
              "persona": {
                "type": "string",
                "example": "Security Advisor"
              },
              "position": {
                "type": "string",
                "example": "Store tokens in HttpOnly cookies to prevent XSS access"
              }
            }
          },
          "resolution": {
            "type": "string | null",
            "description": "How the synthesis resolves this disagreement, or null if left for user to decide",
            "example": "HttpOnly cookies recommended as the safer default; localStorage acceptable only if CSP headers are strictly configured"
          }
        }
      },
      "final_recommendation": {
        "type": "string",
        "description": "Clear, actionable final recommendation with the synthesis agent's best judgment",
        "example": "Implement JWT with HttpOnly cookie storage, 15-minute access token TTL, refresh token rotation, and Redis-based blacklist. This provides the best balance across security, scalability, and operational concerns."
      },
      "confidence": {
        "type": "number",
        "description": "Overall confidence in the final recommendation (0.0 to 1.0), weighted by individual persona confidences and degree of consensus",
        "example": 0.82
      },
      "caveats": {
        "type": "array",
        "description": "Important caveats or conditions that apply to the recommendation",
        "items": {
          "type": "string"
        },
        "example": [
          "This recommendation assumes Redis is already in the infrastructure stack",
          "Mobile clients may need different token storage strategy (secure storage API instead of cookies)"
        ]
      }
    }
  }
}
```

---

## Dependencies

| Depends On | Agent | Artifact | Why |
|---|---|---|---|
| input | user | interactive query | User provides the question, context, and persona selection |
| input | `orchestrator` | `audit.json` (optional) | Pipeline state context for informed evaluation |
| input | any agent | referenced artifacts (optional) | Artifacts the user wants the council to evaluate |

| Blocks | Agent | Why |
|---|---|---|
| output | none | Council is advisory — its output does not block any pipeline agent. User decides whether and how to act on recommendations. |

---

## Orchestrator Communication

### Agent Identity

This agent's ID is `llm_council`. Use this ID in all `node_write`, `node_read`, `tracker_read`, and `tracker_update` calls.

### Tracker Access

| Direction | Compressed Keys | Purpose |
|---|---|---|
| read | (none) | Horizontal agent -- does not read tracker state directly |
| write | `ag` | Report agent status (completed/failed) |

### Output Meta

This agent does not produce routing/coordination metadata. `output_meta: null`.

### Completion Signal

- **On success:** `tracker_update(agent_id: "llm_council", status: "completed")`
- **On failure:** `tracker_update(agent_id: "llm_council", status: "failed", add_intervention: { id: "...", agent_id: "llm_council", type: "error", message: "..." })`

### Scope Resolution

Horizontal agent -- does NOT read `md.a`. Invoked on-demand by user; reads referenced artifacts as needed for council evaluation.

```
1. Receive user query and persona selection (interactive input)
2. node_read(agent_id: "llm_council", input_key: "pipeline_state") — optional
3. node_read(agent_id: "llm_council", input_key: "referenced_artifacts") — as specified by user
4. Run persona evaluations independently
5. Synthesize persona outputs
6. node_write(agent_id: "llm_council", output_key: "council_session", data: {...})
7. tracker_update(agent_id: "llm_council", status: "completed")
```

---

## Compressed Keymap

Use these compressed keys in all `node_write` calls. The registry validates against this map — unknown keys are rejected.

**council_session.json**

| Key | Full Name | Description |
|---|---|---|
| `si` | session_id | Unique session identifier |
| `ts` | timestamp | Timestamp of session |
| `qn` | question | Question posed to the council |
| `cx` | context | Context provided for the question |
| `ar` | artifact_refs | Array of artifact reference objects |
| `ar.ap` | artifact_path | Path to referenced artifact |
| `ar.at` | artifact_type | Type of artifact |
| `pu` | personas_used | Array of persona names used |
| `pr` | persona_responses | Array of persona response objects |
| `pr.pn` | persona_name | Persona name |
| `pr.pl` | persona_role | Persona role description |
| `pr.ps` | perspective | Persona perspective/viewpoint |
| `pr.an` | analysis | Persona analysis |
| `pr.rc` | recommendations | Persona recommendations |
| `pr.cn` | concerns | Persona concerns raised |
| `pr.co` | confidence | Persona confidence level |
| `sy` | synthesis | Synthesis object |
| `sy.mr` | merged_recommendation | Merged recommendation from all personas |
| `sy.ca` | consensus_areas | Array of consensus area objects |
| `sy.ca.ar` | area | Area of consensus |
| `sy.ca.ap` | agreeing_personas | Personas in agreement |
| `sy.da` | disagreement_areas | Array of disagreement area objects |
| `sy.da.ar` | area | Area of disagreement |
| `sy.da.ps` | positions | Array of position objects |
| `sy.da.ps.pn` | persona | Persona name |
| `sy.da.ps.po` | position | Persona position |
| `sy.da.rs` | resolution | Resolution of disagreement |
| `sy.fr` | final_recommendation | Final synthesized recommendation |
| `sy.co` | confidence | Overall confidence level |
| `sy.cv` | caveats | Caveats and limitations |

---

## Tools Required

| Tool | Purpose | Exists? |
|---|---|---|
| `node_write` | Write council_session output via registry-validated compressed keys. Agent calls `node_write(agent_id: "llm_council", output_key: "council_session", data: {...})`. | Pending |
| `node_read` | Read upstream artifacts (pipeline_state, referenced_artifacts). Agent calls `node_read(agent_id: "llm_council", input_key: "referenced_artifacts")`. | Pending |
| `tracker_read` | Read pipeline state. Agent calls `tracker_read(agent_id: "llm_council", fields: [...])`. | Pending |
| `tracker_update` | Report completion/failure. Agent calls `tracker_update(agent_id: "llm_council", status: "completed")`. | Pending |

---

## Guardrails

### Rules

| ID | Category | Severity | Rule |
|---|---|---|---|
| R-001 | `constraint` | `must` | Personas must reason independently. Each persona receives the question and context but NOT the outputs of other personas. No cross-contamination between persona reasoning. |
| R-002 | `constraint` | `must` | Synthesis must highlight disagreements explicitly. Areas where personas disagree must appear in disagreement_areas with each persona's position stated. Must not paper over differences with vague compromise language. |
| R-003 | `scope_boundary` | `must` | Must not override the user's final decision. The council is advisory. The final_recommendation is a suggestion, not a mandate. |
| R-004 | `data_handling` | `must` | Every council session must be logged as a council_session_{session_id}.json file for traceability and future reference. |
| R-005 | `constraint` | `must` | Custom personas must conform to the persona schema (name, role, perspective, expertise_areas). Reject custom personas missing required fields. |
| R-006 | `output_quality` | `must` | Each persona response must include at least one recommendation and one concern. Personas must not be purely affirmative — critical evaluation is required. |
| R-007 | `not_allowed` | `must` | Personas must not fabricate facts or reference artifacts that were not provided. Analysis must be grounded in the given context and question. |
| R-008 | `output_quality` | `should` | Confidence scores should reflect actual uncertainty. A persona unsure about a topic should report low confidence rather than appearing certain. |
| R-009 | `interaction` | `should` | If the user's question is ambiguous, the agent should ask for clarification before running the council rather than having each persona interpret the question differently. |
| R-010 | `constraint` | `should` | Default personas should all participate unless the user explicitly selects a subset. Omitting a perspective by default could lead to blind spots. |
| R-011 | `output_quality` | `must` | Synthesis confidence must be lower than the average persona confidence if there are significant disagreements. Disagreement reduces overall confidence. |
| R-012 | `data_handling` | `should` | Session output should include which artifacts were referenced so future sessions can reference the same context for consistency. |
| R-013 | `constraint` | `must` | Must use compressed keys as defined in the Compressed Keymap section for all `node_write` / `node_read` calls. Never use expanded/full key names. |
| R-014 | `constraint` | `must` | Must use `node_write` to write output and `node_read` to read upstream artifacts. Must not use raw file writes, generic file_writer, or any other method. |
| R-015 | `constraint` | `must` | Must call `tracker_update(agent_id: "llm_council", status: "completed")` before exiting on success. Must call `tracker_update(agent_id: "llm_council", status: "failed", add_intervention: {...})` before exiting on failure. |

### Limits

| Resource | Value |
|---|---|
| max_retries | 3 |
| max_tokens | 32000 |
| max_personas_per_session | 10 |
| max_custom_personas | 5 |
| max_artifact_refs | 10 |
| timeout_seconds | 300 |

---

## Scope Boundary

**In scope:**
- Running configurable multi-persona evaluation of any question, artifact, or decision
- Supporting 5 default personas (Security Advisor, UX Advocate, Performance Engineer, Scalability Architect, DevOps Pragmatist)
- Supporting user-defined custom personas with name, role, perspective, and expertise areas
- Allowing user to select which personas participate per session
- Producing independent persona reasoning without cross-contamination
- Synthesizing persona outputs into unified recommendation with consensus and disagreement areas
- Logging every session for traceability
- Reading any pipeline artifact the user references for context

**Out of scope:**
- Making changes to the pipeline or artifacts (advisory only)
- Blocking pipeline execution based on council recommendations
- Automatically acting on recommendations (user must decide)
- Replacing domain-specific agents (council provides perspective, not implementation)
- Running continuously in the background (on-demand only, user-invoked)
- Evaluating code quality or running tests (those are optimization and test agents' jobs)
- Generating code or contracts based on recommendations

---

## Triggers

- User-invoked at any time during pipeline execution or between runs
- Can be triggered from the Electron app dashboard, the agent chat interface, or the CLI
- Not triggered automatically by the orchestrator — always requires explicit user action

---

## Checkpoints

| ID | Description | Action |
|---|---|---|
| `CP-001` | User query received and validated — question is clear enough to proceed | `log` |
| `CP-002` | Personas selected and validated (default + custom) | `log` |
| `CP-003` | Referenced artifacts loaded successfully | `log` |
| `CP-004` | All persona evaluations complete — ready for synthesis | `log` |
| `CP-005` | Disagreements detected between personas | `notify` — user informed that personas disagree on key areas before seeing synthesis |
| `CP-006` | Synthesis complete — council_session.json written | `notify` — user can review the full council output |

---

## Validation Criteria

- Every selected persona produces a response with non-empty analysis, at least one recommendation, and at least one concern
- No persona response references or quotes another persona's output (independence verified)
- Synthesis includes all personas in either consensus_areas or disagreement_areas (no persona silently ignored)
- Synthesis confidence is numerically consistent with individual confidences and disagreement level
- Custom personas conform to required schema (name, role, perspective, expertise_areas all present)
- session_id is unique across all council sessions
- All artifact_refs point to files that exist and were successfully loaded
- Output JSON passes schema validation
- personas_used array matches the personas that actually produced responses

---

## Context Sources

- User-provided question and context (interactive input)
- audit.json from orchestrator (current pipeline state, if available)
- Any pipeline artifact referenced by the user (contracts, flows, architecture map, test reports, etc.)
- Previous council session outputs (for reference in follow-up sessions)
- architecture_map.json from architecture sync agent (if available, for architecture discussions)

---

## Operation Mode

| Field | Value |
|---|---|
| Type | `interactive` |
| Fallback | `none` — if council fails, user simply does not get multi-perspective analysis; pipeline continues unaffected |

---

## Tool Gaps

| Gap ID | Description | Needed By | Impact Without |
|---|---|---|---|
| `TG-001` | `node_write` MCP tool not yet built | this agent | Cannot write output with registry validation -- blocked |
| `TG-002` | `node_read` MCP tool not yet built | this agent | Cannot read upstream artifacts with field enforcement -- blocked |
| `TG-003` | `tracker_read` MCP tool not yet built | this agent | Cannot read pipeline state -- blocked |
| `TG-004` | `tracker_update` MCP tool not yet built | this agent | Cannot report completion -- blocked |
| `TG-005` | Multi-LLM orchestrator that runs multiple prompts in parallel with isolated system prompts per persona to guarantee independent reasoning | this agent | Personas must run sequentially; risk of context leakage between personas if not carefully isolated in prompt construction |
| `TG-006` | Synthesis engine that programmatically identifies consensus and disagreement areas across persona outputs using semantic comparison | this agent | Synthesis performed as single LLM pass; risk of bias toward certain personas or missing subtle disagreements |

---

## Default Personas

| # | Name | Role | Perspective | Expertise Areas |
|---|---|---|---|---|
| 1 | Security Advisor | Security Evaluator | Evaluates from security perspective — attack vectors, data protection, authentication, authorization, OWASP compliance | security, authentication, authorization, encryption, OWASP, penetration testing |
| 2 | UX Advocate | User Experience Evaluator | Evaluates from user experience perspective — usability, accessibility, cognitive load, user workflows, error handling UX | usability, accessibility, information architecture, interaction design, user research |
| 3 | Performance Engineer | Performance Evaluator | Evaluates from performance and scalability perspective — response times, throughput, resource utilization, bottleneck identification | caching, query optimization, load balancing, profiling, CDN, bundle optimization |
| 4 | Scalability Architect | System Architecture Evaluator | Evaluates from system architecture perspective — modularity, coupling, horizontal scaling, data consistency, fault tolerance | distributed systems, microservices, event-driven architecture, database sharding, CAP theorem |
| 5 | DevOps Pragmatist | Deployment & Operations Evaluator | Evaluates from deployment and operations perspective — CI/CD, monitoring, rollback capability, infrastructure cost, operational complexity | CI/CD, containerization, monitoring, logging, infrastructure-as-code, cost optimization |

---

## Generation Readiness

| `generate_agent` Param | Status | Notes |
|---|---|---|
| `fileName` | ready | `llm-council` |
| `agentName` | ready | `llm_council` |
| `agentRole` | ready | "LLM Council — Multi-Perspective Expert Panel with Synthesis" |
| `agentDescription` | ready | Full description available from Goal section |
| `operationMode` | ready | `interactive`, no fallback |
| `goal` | ready | 3 objectives defined with priorities |
| `inputs` | ready | 3 input categories: user query (required), pipeline state (optional), referenced artifacts (optional) |
| `guardrails` | ready | 15 rules covering constraints, scope_boundary, data_handling, output_quality, not_allowed, interaction, universal tools, and completion signal |
| `scopeBoundary` | ready | 8 in-scope items, 7 out-of-scope items |
| `outputFormat` | ready | JSON output with full schema for council_session.json including persona_responses and synthesis |
| `triggers` | ready | 3 triggers defined (all user-invoked) |
| `checkpoints` | ready | 6 checkpoints with actions |
| `validation` | ready | 9 validation criteria |
| `contextSources` | ready | 5 context sources |
| `metadata` | ready | type: "horizontal", mode: "both", granularity: "global", interaction: "interactive" |
