EXECUTION RUNTIME: GROK BOT LINUX SANDBOX (/workspace) LIVE TEMPLATES: 15 AVAILABLE (FREE + $19, $29, $39 & $49 · CARD) · ZERO SUBSCRIPTIONS PRIVACY: LOCAL CREDENTIAL VAULT · ZERO DATA EXFILTRATION
● LIVE NOW · $39 · card (ONE-TIME · 3 REBINDS) · ORCHESTRATION & DEVOPS · CODING & SECURITY

Agent Council — Multi-Model Swarm Debate & Pair-Architect Collaborator — Put several models on the problem and keep the argument, not just the answer.

Seat 2–6 AI agents around one design question, patch or diff: local claude personas out of the box, plus codex, gemini, aider or your own OpenAI, Anthropic, xAI/Grok, Gemini, OpenRouter, DeepSeek and Ollama keys. They propose blind, cross-examine each other anonymously, pair-program, compete on a rubric or review your code. A Chair returns the consensus, the minority report, a verdict and an action plan, inside the time limit and budget you set, with a one-file HTML transcript.

SKU: agent-council · Skills: agent-council-setup + agent-council · Runtime: 2,801 lines stdlib Python · Price: $39.00 USD one-time · card, Apple Pay or Google Pay

⚡ Works in Grok Bot + Cursor + Claude Code + Any Terminal (Zero-Dep Python 3 CLI Included)
See Real Council Transcript View in Homepage Catalog

What It Does

  • 2–6 configurable seats (--seats & --discover): works out of the box on Grok Bot's computer with local claude multi-persona seats (architect, security, skeptic, pragmatist, driver, navigator, plus performance and reviewer), the local codex, gemini and aider CLIs, and optional BYOK HTTP seats (OpenAI, Anthropic, xAI/Grok, Gemini, OpenRouter, DeepSeek, Ollama). --discover lists what your computer can field and which keys are set, never their values.
  • 4 modes (deliberate, pair, compete, review): blind round 1 parallel proposals; anonymized round 2+ delta cross-examination (Seat A, Seat B); a Driver + Navigator pair-programming loop ending in APPROVE / REQUEST_CHANGES / BLOCK; SwarmSolve-style rubric competition with peer grading and a deterministic winner; and deduplicated, severity-ranked code and diff review (CRITICAL..INFO) with file:line citations.
  • Unthrottled reasoning, structural token efficiency: output budgets are left at the model's native ceiling (Anthropic defaults to 16384 tokens with extended thinking; reasoning_effort: high where supported). Tokens are saved by structure instead: one pinned brief so prompt caches hit, compact line-range slicing (--files path:1-120, --git-diff) with automatic secret redaction, delta-only round forwarding, and --early-stop on consensus.
  • Timers, deadlines & mid-flight steering: --seat-timeout, --total-deadline and --quorum with graceful DEGRADED_TIMEOUT fallback; stateful session steering (--session ID, --status, --pause, --inject "note", --resume); a --max-cost-usd budget guard; and a one-click, self-contained dark-slate HTML council viewer (--html-out).

How It Runs (6 Steps)

1 · License pre-flight
.wattcoin_license_check.py check --sku agent-council must return "state": "OK" before every run.
2 · Pinned runtime check
Setup verifies the canonical SHA-256 of agent_council.py and bot_common.py against the pinned values; any mismatch stops the run.
3 · Seats & pinned brief
--discover picks available seats; the prompt plus line-numbered, redacted --files / --git-diff context becomes one cache-friendly brief.
4 · Blind round 1
All seats answer in parallel without seeing each other, each with its role preset and a per-seat timeout.
5 · Anonymized rounds 2+
Seats see only peers' structured positions and deltas as Seat A/Seat B, plus any injected moderator notes; early stop on convergence, budget or deadline.
6 · Chair synthesis
Consensus matrix, minority report, confidence shifts, verdict and action plan or patch; Markdown/JSON/HTML report, cost ledger and exit code.

Real Sample Output: 3-seat deliberation on bot_common.http_json

Sample disclosure: this is a representative sample, not a customer report. It was produced against public or fictional test targets; account and credential values are placeholders or redacted (for example wck_<REDACTED>), and no private keys, seed phrases or secrets are ever shown. Your own report will differ in content and length.

Excerpt from a live 2-round deliberate council run on 2026-10-27 with three local claude seats (architect, security, skeptic) over /workspace/lib/bot_common.py lines 85–177. Seat text is unedited; the omitted parts are marked. Exit 2: the Chair kept one HIGH item in the minority report at the default --fail-on medium. Total: 7 calls, about 71k tokens, an estimated $0.95 at the claude CLI's list price (normally covered by a subscription).

# Agent Council Report - deliberate

```
snapshot   2026-10-27 20:54:29 UTC | tool=agent-council
endpoints  claude
```

| Field | Value |
|---|---|
| Mode | deliberate |
| Session | sample-live-20261027-165133 |
| Rounds | 2 of 2 |
| Converged | True |
| Early stop | False |
| Quorum | 3/3 active (need 2) |
| Elapsed | 176.2s |
| Stop reason | - |
| Exit code | 2 (fail-on medium) |

## Problem statement

> Architecture & security review: we plan to reuse bot_common.http_json (shown) as the transport for metered, BYOK LLM API calls (OpenAI/Anthropic/xAI) inside paid BotAppStore tools, and keep exit_code() as the CI contract. Is that safe and correct? Consider retry/backoff semantics for non-idempotent paid POSTs, timeout behaviour, error-body handling (could API keys or prompts leak into logs?), MAX_RAW truncation of large JSON responses, and whether exit_code() can ever report a clean pass for a degraded run. Recommend concrete, minimal changes.

## Context bundle

- `/workspace/lib/bot_common.py` lines 85-177 of 274, sha256 `d1941b61b95ca664`
- redactions: none; skipped: none

## Seats

| Seat | Role | Backend | Model | Status |
|---|---|---|---|---|
| A | Architect | claude | (default) | OK |
| B | Security | claude | (default) | OK |
| C | Skeptic | claude | (default) | OK |
| Chair | Judge | claude | (default) | OK |


[... Round 1 (three blind proposals) and Round 2 Seats A-B omitted; Seat C's cross-examination shown ...]

## Round 2 - cross examination

### Seat C - OK - 48960ms, 5678 in / 4778 out tokens, $0.1410

**Position:** Do not reuse http_json unchanged for metered BYOK LLM POSTs; keep it for idempotent GETs and route paid calls through a thin llm_call()/idempotent=False policy that: (1) retries only on proven-not-accepted outcomes (429, 503, 529, and pre-send connect failures such as DNS/ECONNREFUSED/TLS handshake), never on read timeouts, resets after send, or 500/502/504; max 2 retries, Retry-After honored (with a 1-2s floor plus jitter when absent) inside a total wall-clock deadline; (2) uses a configurable long per-call timeout (120-600s) instead of 20s; (3) does a bounded read(cap+1) for both success and error bodies, with an LLM-sized cap, and treats truncated or non-JSON 2xx as errors (.error set, .truncated=True), never status 200 with error=None and {'_raw':...}; (4) stores no raw completions or request headers in HttpResult, Finding.evidence or logs, keeps only the provider error type/code/message, and scrubs sk-/sk-ant-/xai-/Bearer patterns as a backstop; (5) disables redirects and enforces https, with an optional user-configured base_url allowlist rather than a hardcoded provider list; (6) derives degraded automatically from any errored or status<0 result and records attempts and possibly-billed attempts. Keep exit_code() as the CI contract, but fail closed: assert at import that every SEV level reachable by fail_on is in _SEV_EXIT, validate fail_on up front, emit degraded=true in the report even when a severity exit wins, and wrap main so unhandled exceptions exit with a dedicated non-severity code (not Python's default 1, which collides with severity exits).
- *critique:* Seat A: retrying only 429/529 and never retrying any transport exception is over-strict; pre-send connect failures and edge 503s cannot have billed and are safe to retry.
- *critique:* Seat A: rating caller-wired degraded as MEDIUM understates it; http_json never raises (L105), so an all-failed run gives 0 findings and EXIT_OK (L175), a false green in CI, which is HIGH.
- *critique:* Seat A/B: a hardcoded provider host allowlist breaks legitimate BYOK endpoints (Azure OpenAI, proxies, gateways); use https plus no redirects plus a user-configured allowlist.
- *critique:* Seat A/B: the redirect concern is valid but should be precise: with default urllib, POST 301/302/303 becomes a GET that forwards Authorization/x-api-key (the leak), while POST 307/308 raises HTTPError and is returned at L126, so there is no re-POST or double-bill via redirect.
- *critique:* All seats (including mine): missed that exit 1/2 collide with Python's uncaught-exception exit (1) and argparse errors (2), and that an invalid fail_on raises KeyError at L171, so a crashed run can look like a findings result.
- *changes:* Added the exit-code collision and crash-path issue (uncaught exception or invalid fail_on yields exit 1, indistinguishable from a severity exit) and the fix (dedicated crash code, upfront fail_on validation).
- *changes:* Adopted Seat A/B's no-redirect plus https requirement, made the allowlist user-configurable, and stated the urllib 301/302/303 vs 307/308 behaviour precisely.
- *changes:* Adopted a total wall-clock deadline and degraded=true in the report even when a severity exit wins (Seat A).
- *changes:* Added a Retry-After floor plus jitter, noting that _retry_after (L93-97) ignores HTTP-date values and allows 0s retries.
- *disagree* [LOW] Retry set for paid POSTs
- *disagree* [LOW] Severity rating of caller-wired degraded
- *disagree* [MEDIUM] Exit-code collision with crashes

## Chair synthesis (chair)

Unanimous: do NOT reuse bot_common.http_json unchanged as the transport for metered BYOK LLM POSTs. Keep it for idempotent GETs and add a thin llm_call() wrapper with a non-idempotent retry policy.

Verified hazards in the code:
(a) Up to 5 attempts (L113) that retry timeouts and resets (L129-132). Combined with the 20s default timeout (L100), long completions will time out and be re-billed.
(b) Silent truncation. r.read()[:MAX_RAW] (L119) reads the full body and then slices it, so an oversized or non-JSON 2xx becomes status 200, error=None, {'_raw': first 300 chars} (L90). This can also persist completion or prompt text.
(c) Unbounded e.read() (L123). Provider error bodies stored verbatim (L125) can echo masked keys. str(e) (L130) can carry URLs.
(d) _retry_after (L93-97) ignores HTTP-date values and allows 0s sleeps.
(e) Redirects. Assuming _urlopen uses stock urllib (unseen), a POST 301/302/303 is followed as a GET carrying the auth headers; 307/308 is returned at L126.

exit_code() is correct only if callers wire degraded=True. Because http_json never raises, an all-failed run yields 0 findings and EXIT_OK: a false green. It also has a fail-open hole at L172-175: a worst finding whose sev is absent from _SEV_EXIT falls through to EXIT_OK/EXIT_DEGRADED. SEV[fail_on.upper()] (L171) raises KeyError on bad input. An uncaught exception exits 1, which may collide with a severity code (_SEV_EXIT values unseen).

Outcome: keep exit_code as the CI contract, but make it fail closed and derive degraded automatically.

### Consensus matrix

| Point | Agree | Disagree |
|---|---|---|
| Do not reuse http_json unchanged for paid LLM POSTs; keep it for idempotent GETs and add an llm_call()/idempotent=False policy | Seat A, Seat B, Seat C |  |
| Never retry POST on read timeouts, connection resets after send, or 500/502/504. Max 2 retries, jitter, honor Retry-After, and enforce a total wall-clock deadline | Seat A, Seat B, Seat C |  |
| Retry 429 rate limits and 529. Never retry 429 insufficient_quota or billing errors (terminal BYOK config errors) | Seat A, Seat B, Seat C |  |
| Transport errors are retryable only when provably pre-send, classified by URLError.reason (socket.gaierror, ConnectionRefusedError). Timeouts count as possibly billed | Seat A, Seat B, Seat C |  |
| Configurable long per-op timeout (about 120-300s, up to 600s) instead of 20s, plus a separate total deadline (urllib timeout is per socket op) | Seat A, Seat B, Seat C |  |
| Bounded read(cap+1) for both success and error bodies. An oversized or non-JSON 2xx sets error and truncated=True; never return 200 with error=None | Seat A, Seat B, Seat C |  |
| Persist no raw completions, prompts or request headers. Keep only the provider error type/code/message, scrub sk-/sk-ant-/xai-/Bearer patterns, and make the repr body-free | Seat A, Seat B, Seat C |  |
| No-redirect opener (any 3xx is an error) and https required before attaching keys | Seat A, Seat B, Seat C |  |
| Derive degraded automatically from any errored or status<0 llm_call result; record attempts and possibly_billed_attempts | Seat A, Seat B, Seat C |  |
| Keep exit_code as the CI contract but fail closed. Close the L172-175 unmapped-severity hole, validate fail_on up front, and always emit degraded=true in the report even when a severity exit wins | Seat A, Seat B, Seat C |  |
| Map uncaught exceptions and argparse errors to a dedicated non-severity exit code (contingent on unseen _SEV_EXIT values) | Seat A, Seat C |  |
| Host allowlist: hardcoded provider hosts (A/B) vs user-configured base_url allowlist (C). Chair merge: built-in default allowlist extended by an explicit user-configured base_url (Azure/proxies), https-only, no redirects | Seat A, Seat B, Seat C |  |

### Dissent / minority report

- **LOW** 503 retry condition - Seat B would retry 503 only when Retry-After is present; Seats A and C retry 503 generally. A 503 normally means the request was not processed. Chair adopts: retry 503 within the deadline and count it as possibly billed in metering. Projects that see billed 503s should switch to B's stricter rule. (Seat B)
- **LOW** TLS handshake errors as pre-send - Seats A and C also treat SSL handshake failures as pre-send. Seat B limits pre-send to gaierror/ConnectionRefusedError. A handshake failure precedes any HTTP bytes, but ssl.SSLError can also surface mid-stream. Chair adopts: retry only when the error is raised before the connection is established; if this cannot be distinguished cleanly, use B's narrower set. (Seat B)
- **HIGH** Rating of caller-wired degraded - Seat C rates it HIGH; Seat A originally rated it MEDIUM. Chair sides with HIGH. http_json never raises (L105), so a run where every paid call failed returns EXIT_OK (L175) unless every caller remembers degraded=True. This is a false green in paid CI. The remedy is agreed by all seats; only the label differed. (Seat C)
- **LOW** exit_code fix shape - Seat B prefers a generic fail-closed code when any finding meets the threshold but is unmapped. Seats A and C prefer 'worst over mapped severities' plus an import-time coverage assert. Chair merges both: assert coverage AND fail closed, so mapped-only can never yield EXIT_OK when a finding meets the threshold. (Seat B)

### Confidence shifts

| Seat | First | Last | Shift |
|---|---|---|---|
| A | 80 | 82 | +2 |
| B | 78 | 82 | +4 |
| C | 72 | 82 | +10 |

**Verdict:** `REQUEST_CHANGES`

### Action plan

1. Add an LLM transport policy in lib/bot_common.py: llm_call(url, body, headers, *, timeout=180, deadline=600, max_retries=2, cap=LLM_MAX_RAW, allowed_hosts=DEFAULT_LLM_HOSTS | user_base_url_hosts). Leave http_json's GET behaviour untouched, and add a guard so http_json refuses to send an Authorization or x-api-key header with a POST body unless idempotent=True is passed.
2. Retry classifier for llm_call. Retryable: 429 unless error.code/type is insufficient_quota or billing; 503; 529; URLError whose .reason is socket.gaierror or ConnectionRefusedError. Everything else returns immediately, including socket.timeout/TimeoutError, ConnectionResetError, RemoteDisconnected, 500/502/504 and other 4xx. Sleep = min(remaining_deadline, max(1.0, Retry-After or backoff*2**n)) + random.uniform(0, 0.5), and stop if the deadline would be exceeded. Also parse HTTP-date Retry-After values via email.utils.parsedate_to_datetime.
3. Metering: on every attempt that may have reached the provider (any HTTP status, or a timeout/reset), increment possibly_billed_attempts and attach it, along with attempts, to the result.
4. Bounded reads: raw = r.read(cap + 1). If len(raw) > cap, return status preserved, error='response too large', truncated=True, body=None. Do the same with e.read(ERR_CAP + 1). If a 2xx body fails json.loads, set error='invalid JSON' and do not return {'_raw': ...}. Use non-streaming requests (SSE is out of scope for _parse).

[... action items 4-11, the unresolved-findings table and the full SCOPE_NOTE omitted ...]

## Token & cost ledger

| Seat | Backend | Calls | In | Out | Cached | USD | Basis |
|---|---|---|---|---|---|---|---|
| A | claude | 2 | 8915 | 9843 | 2912 | 0.2455 | cli-reported |
| B | claude | 2 | 8875 | 11089 | 2911 | 0.2701 | cli-reported |
| C | claude | 2 | 8898 | 10152 | 2914 | 0.2515 | cli-reported |
| Chair | claude | 1 | 7749 | 6119 | 0 | 0.1844 | cli-reported |
| **Total** | | 7 | 34437 | 37203 | 8737 | 0.9514 | |

CLI Flags & Exit Codes

FlagMeaning
PROMPT | - | --prompt-file PATHThe problem statement (argv, stdin or file). Secrets in it are redacted before any seat sees it.
--mode {deliberate,pair,compete,review}Council protocol (default deliberate; default rounds 3 / 2 / 2 / 1).
--seats SPEC[,SPEC] / --seat SPEC2–6 seats, e.g. claude:architect, claude@security, codex, openai:gpt-5, anthropic:claude-opus-4-5, xai:grok-4, gemini:gemini-2.5-pro, openrouter:<vendor/model>, deepseek, ollama:<model>, cmd:<exe>.
--chair SPEC / --role-prompt SEAT=PROMPTChoose the synthesising seat; override or define role prompts.
--discoverList local CLIs and which BYOK keys are set (values never shown).
--files PATH[:START-END] / --git-diff [REF] / --repo DIRCompact, line-numbered, redacted context. .env*, lockfiles, key files, .git/ and node_modules/ are refused.
--rounds N / --early-stop / --no-early-stop / --quorum N / --sequentialRound count (1–10), convergence stop, minimum active seats, serial calls.
--seat-timeout S / --total-deadline SPer-call timeout (default 120 s) and wall-clock budget (default 600 s).
--max-cost-usd XPre-flight refusal above X; no new round after 85% of X is spent.
--effort LEVEL / --max-output-tokens NReasoning effort (default high); output cap (default 0 = model ceiling).
--session ID + --status / --pause / --inject NOTE / --resumePersist, inspect, pause, steer and continue a council.
--state PATH --delta / --state-key KEYReport new / changed / resolved items against the last clean run.
--format {text,markdown,json} / --json / --out PATH / --html-out PATHReport format and files, including the self-contained HTML viewer.
--fail-on LEVEL / --offline PATH / --env-file PATHExit threshold (default medium), fixture replay, provider-key file.
Exit codeMeaning
0Completed with nothing unresolved at or above --fail-on (or paused on request).
1Worst unresolved item is MEDIUM (e.g. NO_CONSENSUS, REQUEST_CHANGES).
2Worst unresolved item is HIGH (HIGH dissent, BLOCK, HIGH review finding).
3Worst unresolved item is CRITICAL.
10Usage error or refusal: bad seat spec, missing CLI or key, disallowed path, pre-flight budget refusal.
11Degraded: seat timeout or error, lost quorum, deadline cut-off. Never a clean consensus.

What It Does Not Do

  • Advisory and read-only. It reads only the slices and diff you pass and returns text. It never edits, commits, runs or deploys anything. claude seats run with tools disabled, codex in its read-only sandbox, and aider in dry-run mode, all from an empty temp directory.
  • No secrets to seats. It refuses .env*, .wattcoin_env*, lockfiles, key and credential files, .git/ and node_modules/, and redacts API keys, tokens, private keys and high-entropy strings from the prompt, context and moderator notes. Provider keys are read by variable name and never printed or stored.
  • No offensive tasks. Seats are instructed to decline exploit writing, credential harvesting and similar requests. Defensive design, threat modelling and code review are in scope.
  • Consensus is evidence, not proof. Models are non-deterministic and can be confidently wrong together. Verify patches and findings before acting. BYOK costs are estimates from a static price table; your provider invoice is authoritative.

Scope note (printed with every report): advisory, read-only deliberation; disallowed paths refused and secrets redacted before any seat sees them; outputs are non-deterministic and a consensus is evidence, not proof; cost figures are estimates and the --max-cost-usd guard counts both HTTP and CLI seats.

Pinned Runtime Scripts (SHA-256 Verified)

Runtime URLs are license-gated: send X-License-Key: wcl_... or X-Agent-Key: wck_... (unauthenticated requests get 401). The served file carries a per-license watermark block (5 lines), so compare the X-Canonical-SHA256 response header (or the SHA-256 after stripping the block) against the pins above. The recommended path is the setup skill installer:

python3 /workspace/.wattcoin_license_check.py --sku agent-council --install-runtime ... --expected-sha256 703d307e52c4e13df94e28554d16143a5286bf0af3ffe6d95431a5fa490284d7

The setup and council skills verify both canonical digests before every run and refuse to execute either file on a mismatch. Both are locked at chmod 500. The runtime is stdlib-only Python and is covered by 170 unit tests.

Technical FAQ

Which seats work out of the box, and do I need API keys?
No API key is needed to start. If the claude CLI is installed and logged in (it is on Grok Bot's computer), the default council is three claude personas: architect, skeptic and pragmatist, or driver and navigator in pair mode. Each claude seat runs tool-less from an empty temp directory with a lean system prompt, so a call costs a few hundred prompt tokens of overhead instead of the full agent context. --discover also lists the codex, gemini, aider and ollama CLIs it finds, and which BYOK provider keys (ANTHROPIC_API_KEY, OPENAI_API_KEY, XAI_API_KEY, GEMINI_API_KEY, OPENROUTER_API_KEY, DEEPSEEK_API_KEY) are set, without ever printing their values.
How does a deliberation avoid groupthink and anchoring?
Round 1 is blind: every seat answers the same pinned brief in parallel without seeing any peer. From round 2 each seat sees only its peers' structured positions, critiques and changes under anonymous labels (Seat A, Seat B), never raw chain-of-thought and never which vendor produced them, and must say what it changed and what it still disputes. The Chair, prompted as a judge that weighs arguments on merit, then separates real consensus from polite agreement, keeps credible minority views in a dissent list with severities, and records each seat's confidence shift.
How do pair, compete and review modes work?
Pair: the Driver writes a concrete patch or plan, Navigators critique it adversarially with cited findings, the Driver refines, and the result is a final patch plus a verdict of APPROVE, REQUEST_CHANGES (MEDIUM) or BLOCK (HIGH). Compete: seats solve independently, then grade each other's solutions (never their own) on Correctness 0.40, Security 0.30, Simplicity 0.15 and Edge Cases 0.15; the winner is computed deterministically from the scores and the Chair lists cherry-picks from the runners-up. Review: every seat reviews the same --files slices or --git-diff, findings are merged and deduplicated into F1..Fn ranked CRITICAL to INFO with file, line and fix, and later rounds let seats confirm or dispute each one.
How are tokens kept down without throttling the models?
Every call starts with the same pinned brief (problem statement, line-numbered context bundle, protocol), so provider prompt caches hit; Anthropic seats mark it with cache_control. You pass only the line ranges that matter (--files path:85-177) or a git diff. Round 2 and later forward only structured peer positions and deltas, clipped per field, and the council stops early once every seat has converged with no HIGH disagreement. Output is not capped: HTTP seats omit max_tokens where the API allows it, Anthropic seats default to 16,384 output tokens with extended thinking, and reasoning effort defaults to high.
What happens when a seat hangs or the budget runs out?
Each call is bounded by --seat-timeout (default 120 s). A seat that times out is marked DEGRADED_TIMEOUT (errors are DEGRADED_ERROR) and sits out while the rest continue, as long as --quorum active seats remain. --total-deadline (default 600 s) stops new rounds early enough for the Chair to synthesise. --max-cost-usd refuses the run up front (exit 10) if even the minimum estimate is over budget, and starts no new round once spend reaches 85% of the cap. Any degradation makes the run exit 11, so a half-finished council is never reported as a clean consensus.
Can I steer a council while it is running?
Yes. Start it with --session ID, and from a second command use --status to see rounds, seat status and spend, --inject "note" to queue a moderator instruction that every seat receives as high-priority steering in the next round, or --pause to stop before the next round. --resume continues a paused session with the same seats, context and options, or adds more rounds to a finished one. Sessions are stored under /workspace/agent-council/sessions/ with 0700 permissions, and injected notes are redacted like everything else.
What is the HTML council viewer?
--html-out PATH writes one self-contained dark-slate HTML file with no external scripts, fonts or images: the problem statement, context bundle hashes, seat table, every round per seat with latency, tokens and cost, the Chair synthesis, consensus matrix, minority report, confidence shifts, action plan or patch, findings and the cost ledger. You can open it offline or attach it to a pull request.
What does it refuse to do?
It is advisory and read-only: it never edits, commits, runs or deploys anything. It refuses to ingest node_modules, .git, lockfiles, .env* and .wattcoin_env* files and key or credential files, and it redacts private keys, wck_/wcl_ codes, sk-, ghp_, AKIA, xai-, AIza, Slack, Stripe, JWT and Bearer tokens, password assignments and other high-entropy strings before any seat sees the prompt, context or moderator notes. Seats are instructed to decline exploit, credential-harvesting and other offensive tasks, and cost figures for BYOK seats are estimates, not invoices.

Licensing & Setup

$39.00 USD one-time, paid by card, Apple Pay or Google Pay, with up to 3 workspace-reset rebinds and no subscription. On Turn 1 the agent-council-setup skill installs the read-only license helper (0500), verifies and installs the SHA-256-pinned runtime, registers and activates your agent key, binds your wcl_... code through stdin, runs --discover to show the seats your computer can field, and offers a small budget-capped smoke council and an optional scheduled review routine. The license code and any provider keys are never printed in chat.

One wcl_... key, two runtimes. Your license key works inside Grok Bot and from any local terminal or IDE agent (Cursor, Claude Code, Windsurf, CI/CD) via the standalone single-file Python 3 CLI (/runtime/agent_council.py) — Python 3.10+ standard library only, zero pip install dependencies, with --json / --markdown output.