Skip to content

feat: kyora council — summon other model families over MCP - #8

Merged
eliahilse merged 1 commit into
mainfrom
feat/council
Jul 30, 2026
Merged

feat: kyora council — summon other model families over MCP#8
eliahilse merged 1 commit into
mainfrom
feat/council

Conversation

@eliahilse

Copy link
Copy Markdown
Owner

Your agent is one lineage with one set of blind spots. This gives it a way to ask the others — mid-work, on the subscriptions you already pay for.

The MCP server

tool
council_convene one question → several model families in parallel, independent takes back
council_convene_async same, backgrounded; collect with council_result while you keep working
council_ask one specific family's perspective, read-only
council_task delegate concrete work to one family — write: true permits file edits
council_result collect a background council or task
council_status who can be summoned now, with live remaining quota

Backed by the same engine table as kyora-review, so every member is its vendor's own CLI under your own login. Seating is quota-aware — highest remaining quota first, never an engine that's cooling down or spent, and size caps a council so one question doesn't drain every subscription. The prompts push members to disagree rather than defer, and the summary tells the caller to treat disagreement as the signal rather than averaging votes.

Engines gained write-capable invocations for delegation (codex workspace-write, claude/kimi/glm/qwen with edit tools restored but CI suites and destructive git still denied). The review package now exports ./engines, ./usage, ./extract, ./types.

The high-stakes watcher

Optional PostToolUse hook: a cheap model reads the transcript tail and the pending action, and when it judges the moment genuinely consequential — schema migration, auth change, force push, irreversible op — it injects a note nudging the agent to consult the council before committing.

Built to be cheap and quiet, since a noisy or expensive watcher is one you'd turn off: a keyword/size pre-filter runs in-process so most tool calls never reach a model, classification is rate-limited (2m default), nudges harder (15m default), and every failure path exits silently so it can never block or break the agent. Model is any OpenAI-compatible endpoint — defaults to glm-4.5-air or qwen3.6-plus depending on which key is present.

Verification

  • MCP handshake + all six tools registered (stdio round-trip)
  • Live council with glm + grok on a real design question in this repo — both read the actual source and cited specific lines; seating correctly ordered glm (99% quota) ahead of claude (41%)
  • 6 unit tests for the watcher's pre-filter and verdict parsing; types clean across the workspace

Follow-ups (not in this PR)

  • Kimi still needs a Moonshot key to validate its probe and seat
  • The watcher classifies text only; wiring vision for screenshot-bearing transcripts is a natural next step

🤖 Generated with Claude Code

https://claude.ai/code/session_01CQy3ZJ5MyUxo4qjZwA93Na

MCP server exposing council_convene (sync + async), council_ask,
council_task (read or write), council_result, and council_status,
backed by the review engine table so every member runs as its vendor's
own CLI on the user's subscription. Seating is quota-aware: highest
remaining quota first, never an engine that is cooling down or spent.

Adds an optional PostToolUse hook that watches the agent with a cheap
model and nudges it to consult the council at high-stakes moments —
keyword pre-filter, rate-limited classification and nudges, silent on
every failure path so it can never block work.

Engines gain write-capable invocations for delegated tasks; the review
package now exports its engine, usage, and extract modules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQy3ZJ5MyUxo4qjZwA93Na
@eliahilse
eliahilse merged commit a061bf3 into main Jul 30, 2026
2 checks passed
@eliahilse

Copy link
Copy Markdown
Owner Author

Added the plain subagent shape plus model/effort control:

  • agent_spawn — delegate to another model family without naming one; the least-spent capable family is chosen automatically (prefer is a hint, ignored when that family has no quota). Read-only by default, write: true for edits, background: true for a job id.
  • agent_fanout — several different tasks in parallel, one per family, so independent workstreams spread across subscriptions instead of draining one. Assignment logic is pure and unit-tested (pinned-first, one family each, reuse only when families run out, and a task pinned to an unavailable family is reported rather than silently rerouted).
  • council_models — lists which families are summonable and the models/efforts each accepts.
  • model and effort on every delegation tool, applied per engine as CLI flags (codex -m + -c model_reasoning_effort, grok -m + --reasoning-effort, claude --model) or the model env var for endpoint-routed families. A caller-supplied effort replaces the engine's built-in flag rather than duplicating it.

Two bugs this surfaced, both fixed:

  1. Council calls inherited the review path's --output-schema and passed it an empty schema — codex 400'd on every ask. Added a chat mode so free-form answers use unconstrained invocations.
  2. The codex model list I first wrote was invented and rejected by the account. It now reads the model from your own ~/.codex/config.toml (here: gpt-5.6-sol), and the other families list only ids actually run in testing.

Verified live: codex chat with effort: low answers correctly in 10s, glm honors model: glm-5.2 through the env route, all 9 tools register over stdio, 11 unit tests green.

eliahilse added a commit that referenced this pull request Jul 31, 2026
Follow-up to #8 — these commits were pushed to `feat/council` after it
squash-merged, so main has the council without them.

## Plain subagents, not just councils

- **`agent_spawn`** — delegate to another model family *without naming
one*: the least-spent capable family is chosen automatically (`prefer`
is a hint, ignored when that family has no quota). Read-only by default,
`write: true` for edits, `background: true` for a job id. This is the
subagent shape — hand it work, get a worker from another lineage on a
separate subscription.
- **`agent_fanout`** — several *different* tasks in parallel, one per
family, so independent workstreams spread across subscriptions instead
of draining one. Assignment is pure and unit-tested: pinned-first, one
family each, reuse only once families run out, and a task pinned to an
unavailable family is reported rather than silently rerouted.

The split is now clean: `council_*` gathers opinions on one question,
`agent_*` does work.

## Model and effort control

- **`council_models`** lists which families are summonable and the
models/efforts each accepts.
- **`model` and `effort`** on every delegation tool, applied per engine
as real flags (codex `-m` + `-c model_reasoning_effort`, grok `-m` +
`--reasoning-effort`, claude `--model`) or the model env var for
endpoint-routed families. A caller-supplied effort replaces the engine's
built-in flag rather than duplicating it.

## Two bugs this surfaced

1. **Council asks were broken on codex.** They inherited the review
path's `--output-schema` and passed it an empty schema, so every codex
consultation 400'd — present in the merged #8. Added a **chat mode** so
free-form answers use unconstrained invocations.
2. **The codex model list was invented.** My first pass shipped
plausible-looking ids the account rejected outright. It now reads the
model from the user's own `~/.codex/config.toml` (here `gpt-5.6-sol`),
and other families list only ids actually run in testing. Models pass
straight through to the vendor CLI, so newer ids work before this
package knows them — the list is a hint, not a gate.

## Verification

- codex chat at `effort: low` answers correctly in 10s (was a hard 400
before the fix)
- glm honors `model: glm-5.2` through the env route
- all 9 tools register over stdio; 11 council tests + 34 review tests
green, types clean

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01CQy3ZJ5MyUxo4qjZwA93Na

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant