Metadata-Version: 2.4
Name: symposium-protocol
Version: 1.10.4
Summary: Reference implementation of the Symposium protocol — structured, sequential, adversarial multi-agent deliberation.
Project-URL: Homepage, https://github.com/terrordrummer/symposium
Project-URL: Specification, https://github.com/terrordrummer/symposium/blob/main/docs/specification.md
Project-URL: Repository, https://github.com/terrordrummer/symposium
Author: Roberto Sartori
License:                                  Apache License
                                   Version 2.0, January 2004
                                http://www.apache.org/licenses/
        
           TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
        
           1. Definitions.
        
              "License" shall mean the terms and conditions for use, reproduction,
              and distribution as defined by Sections 1 through 9 of this document.
        
              "Licensor" shall mean the copyright owner or entity authorized by
              the copyright owner that is granting the License.
        
              "Legal Entity" shall mean the union of the acting entity and all
              other entities that control, are controlled by, or are under common
              control with that entity. For the purposes of this definition,
              "control" means (i) the power, direct or indirect, to cause the
              direction or management of such entity, whether by contract or
              otherwise, or (ii) ownership of fifty percent (50%) or more of the
              outstanding shares, or (iii) beneficial ownership of such entity.
        
              "You" (or "Your") shall mean an individual or Legal Entity
              exercising permissions granted by this License.
        
              "Source" form shall mean the preferred form for making modifications,
              including but not limited to software source code, documentation
              source, and configuration files.
        
              "Object" form shall mean any form resulting from mechanical
              transformation or translation of a Source form, including but
              not limited to compiled object code, generated documentation,
              and conversions to other media types.
        
              "Work" shall mean the work of authorship, whether in Source or
              Object form, made available under the License, as indicated by a
              copyright notice that is included in or attached to the work
              (an example is provided in the Appendix below).
        
              "Derivative Works" shall mean any work, whether in Source or Object
              form, that is based on (or derived from) the Work and for which the
              editorial revisions, annotations, elaborations, or other modifications
              represent, as a whole, an original work of authorship. For the purposes
              of this License, Derivative Works shall not include works that remain
              separable from, or merely link (or bind by name) to the interfaces of,
              the Work and Derivative Works thereof.
        
              "Contribution" shall mean any work of authorship, including
              the original version of the Work and any modifications or additions
              to that Work or Derivative Works thereof, that is intentionally
              submitted to Licensor for inclusion in the Work by the copyright owner
              or by an individual or Legal Entity authorized to submit on behalf of
              the copyright owner. For the purposes of this definition, "submitted"
              means any form of electronic, verbal, or written communication sent
              to the Licensor or its representatives, including but not limited to
              communication on electronic mailing lists, source code control systems,
              and issue tracking systems that are managed by, or on behalf of, the
              Licensor for the purpose of discussing and improving the Work, but
              excluding communication that is conspicuously marked or otherwise
              designated in writing by the copyright owner as "Not a Contribution."
        
              "Contributor" shall mean Licensor and any individual or Legal Entity
              on behalf of whom a Contribution has been received by Licensor and
              subsequently incorporated within the Work.
        
           2. Grant of Copyright License. Subject to the terms and conditions of
              this License, each Contributor hereby grants to You a perpetual,
              worldwide, non-exclusive, no-charge, royalty-free, irrevocable
              copyright license to reproduce, prepare Derivative Works of,
              publicly display, publicly perform, sublicense, and distribute the
              Work and such Derivative Works in Source or Object form.
        
           3. Grant of Patent License. Subject to the terms and conditions of
              this License, each Contributor hereby grants to You a perpetual,
              worldwide, non-exclusive, no-charge, royalty-free, irrevocable
              (except as stated in this section) patent license to make, have made,
              use, offer to sell, sell, import, and otherwise transfer the Work,
              where such license applies only to those patent claims licensable
              by such Contributor that are necessarily infringed by their
              Contribution(s) alone or by combination of their Contribution(s)
              with the Work to which such Contribution(s) was submitted. If You
              institute patent litigation against any entity (including a
              cross-claim or counterclaim in a lawsuit) alleging that the Work
              or a Contribution incorporated within the Work constitutes direct
              or contributory patent infringement, then any patent licenses
              granted to You under this License for that Work shall terminate
              as of the date such litigation is filed.
        
           4. Redistribution. You may reproduce and distribute copies of the
              Work or Derivative Works thereof in any medium, with or without
              modifications, and in Source or Object form, provided that You
              meet the following conditions:
        
              (a) You must give any other recipients of the Work or
                  Derivative Works a copy of this License; and
        
              (b) You must cause any modified files to carry prominent notices
                  stating that You changed the files; and
        
              (c) You must retain, in the Source form of any Derivative Works
                  that You distribute, all copyright, patent, trademark, and
                  attribution notices from the Source form of the Work,
                  excluding those notices that do not pertain to any part of
                  the Derivative Works; and
        
              (d) If the Work includes a "NOTICE" text file as part of its
                  distribution, then any Derivative Works that You distribute must
                  include a readable copy of the attribution notices contained
                  within such NOTICE file, excluding those notices that do not
                  pertain to any part of the Derivative Works, in at least one
                  of the following places: within a NOTICE text file distributed
                  as part of the Derivative Works; within the Source form or
                  documentation, if provided along with the Derivative Works; or,
                  within a display generated by the Derivative Works, if and
                  wherever such third-party notices normally appear. The contents
                  of the NOTICE file are for informational purposes only and
                  do not modify the License. You may add Your own attribution
                  notices within Derivative Works that You distribute, alongside
                  or as an addendum to the NOTICE text from the Work, provided
                  that such additional attribution notices cannot be construed
                  as modifying the License.
        
              You may add Your own copyright statement to Your modifications and
              may provide additional or different license terms and conditions
              for use, reproduction, or distribution of Your modifications, or
              for any such Derivative Works as a whole, provided Your use,
              reproduction, and distribution of the Work otherwise complies with
              the conditions stated in this License.
        
           5. Submission of Contributions. Unless You explicitly state otherwise,
              any Contribution intentionally submitted for inclusion in the Work
              by You to the Licensor shall be under the terms and conditions of
              this License, without any additional terms or conditions.
              Notwithstanding the above, nothing herein shall supersede or modify
              the terms of any separate license agreement you may have executed
              with Licensor regarding such Contributions.
        
           6. Trademarks. This License does not grant permission to use the trade
              names, trademarks, service marks, or product names of the Licensor,
              except as required for reasonable and customary use in describing the
              origin of the Work and reproducing the content of the NOTICE file.
        
           7. Disclaimer of Warranty. Unless required by applicable law or
              agreed to in writing, Licensor provides the Work (and each
              Contributor provides its Contributions) on an "AS IS" BASIS,
              WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
              implied, including, without limitation, any warranties or conditions
              of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
              PARTICULAR PURPOSE. You are solely responsible for determining the
              appropriateness of using or redistributing the Work and assume any
              risks associated with Your exercise of permissions under this License.
        
           8. Limitation of Liability. In no event and under no legal theory,
              whether in tort (including negligence), contract, or otherwise,
              unless required by applicable law (such as deliberate and grossly
              negligent acts) or agreed to in writing, shall any Contributor be
              liable to You for damages, including any direct, indirect, special,
              incidental, or consequential damages of any character arising as a
              result of this License or out of the use or inability to use the
              Work (including but not limited to damages for loss of goodwill,
              work stoppage, computer failure or malfunction, or any and all
              other commercial damages or losses), even if such Contributor
              has been advised of the possibility of such damages.
        
           9. Accepting Warranty or Additional Liability. While redistributing
              the Work or Derivative Works thereof, You may choose to offer,
              and charge a fee for, acceptance of support, warranty, indemnity,
              or other liability obligations and/or rights consistent with this
              License. However, in accepting such obligations, You may act only
              on Your own behalf and on Your sole responsibility, not on behalf
              of any other Contributor, and only if You agree to indemnify,
              defend, and hold each Contributor harmless for any liability
              incurred by, or claims asserted against, such Contributor by reason
              of your accepting any such warranty or additional liability.
        
           END OF TERMS AND CONDITIONS
        
           APPENDIX: How to apply the Apache License to your work.
        
              To apply the Apache License to your work, attach the following
              boilerplate notice, with the fields enclosed by brackets "[]"
              replaced with your own identifying information. (Don't include
              the brackets!)  The text should be enclosed in the appropriate
              comment syntax for the file format. We also recommend that a
              file or class name and description of purpose be included on the
              same "printed page" as the copyright notice for easier
              identification within third-party archives.
        
           Copyright [yyyy] [name of copyright owner]
        
           Licensed under the Apache License, Version 2.0 (the "License");
           you may not use this file except in compliance with the License.
           You may obtain a copy of the License at
        
               http://www.apache.org/licenses/LICENSE-2.0
        
           Unless required by applicable law or agreed to in writing, software
           distributed under the License is distributed on an "AS IS" BASIS,
           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
           See the License for the specific language governing permissions and
           limitations under the License.
License-File: LICENSE
Keywords: ai-agents,deliberation,json-schema,llm,multi-agent,protocol,reasoning,specification
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11
Requires-Dist: click>=8.1
Requires-Dist: httpx>=0.27
Requires-Dist: jsonschema>=4.26
Requires-Dist: pydantic>=2.7
Requires-Dist: pyyaml>=6.0
Requires-Dist: referencing>=0.35
Requires-Dist: rfc8785>=0.1.4
Provides-Extra: mcp
Requires-Dist: mcp>=1.2; extra == 'mcp'
Provides-Extra: test
Requires-Dist: mcp>=1.2; extra == 'test'
Requires-Dist: pytest-cov>=5.0; extra == 'test'
Requires-Dist: pytest>=8.0; extra == 'test'
Requires-Dist: respx>=0.21; extra == 'test'
Description-Content-Type: text/markdown

<p align="center">
  <img src="docs/assets/logo.png" alt="Symposium logo" width="180">
</p>

<h1 align="center">Symposium</h1>

<p align="center">
  <em>An opinionated protocol for structured, sequential, adversarial multi-agent deliberation.</em>
</p>

<p align="center">
  <a href="docs/specification.md"><img alt="Spec" src="https://img.shields.io/badge/spec-1.0-1a365d?style=flat-square"></a>
  <a href="docs/schemas/v1.0.0/"><img alt="Schemas" src="https://img.shields.io/badge/JSON%20Schema-v1.0.0-d4a017?style=flat-square"></a>
  <a href="symposium/"><img alt="Reference impl" src="https://img.shields.io/badge/reference%20impl-Python%203.11%2B-3776ab?style=flat-square"></a>
  <a href="https://github.com/terrordrummer/symposium/actions/workflows/validate.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/terrordrummer/symposium/validate.yml?branch=main&label=ci&style=flat-square"></a>
  <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-Apache%202.0-333333?style=flat-square"></a>
</p>

---

## What is this?

Symposium is a **protocol specification** + a **reference Python
runtime** that orchestrates a small panel of LLM-backed agents through
a structured, turn-based deliberation, producing a single, replayable,
schema-validated artifact.

It is **not** a generic agent framework. It enforces exactly one
conversation topology — fixed panel, one primary turn per agent per
round, one structurally-separated coordinator, bounded forks — and
trades topology flexibility for **testable scheduler invariants** and
**byte-identical replay** of any past session.

Two things ship together in this repo:

1. **`docs/specification.md`** — the normative protocol. Implementable
   in any language. The spec is what conformance means.
2. **`symposium/`** — the reference Python runtime. Today: full
   scheduler, persistence, replay, the deterministic `FakeProvider`
   adapter, an OpenAI-shaped HTTP adapter (real OpenAI plus
   self-hosted OpenAI-compatible endpoints), and an Anthropic-shaped
   HTTP adapter (real Anthropic plus self-hosted Anthropic-compatible
   endpoints).

---

## Why one more protocol?

Most multi-agent stacks expose enough flexibility (group chat,
arbitrary handoffs, nested supervisors) that any two implementations
diverge on the parts that matter — when does the conversation stop, what
exactly is replayed, what fails the run, how is delegation routed. Each
implementation invents its own answers, and operators end up debugging
the framework instead of the agents.

Symposium goes the opposite way: **one opinionated topology, sharp
boundaries, closed enums.** What you get in exchange:

| | Symposium |
|---|---|
| **Topology** | Fixed `deliberation_panel`, one `primary_turn` per agent per round, single `coordination_turn` from a structurally-separated `coordinator_agent`. |
| **Inter-agent routing** | Schema-validated `direct_request` only. Inline `@AgentName` in prose is never routing — prompt-injection resistant by construction. |
| **Roles** | Three-way separation: `Selector` chooses *who*, `CoordinatorAgent` recommends *what next* (LLM, no executive power), `OrchestratorRuntime` schedules and terminates (deterministic code, sole party that decides when a session stops). |
| **Failure surface** | Closed 7-value termination-reason enum; closed 12-value adapter `error.kind` enum; closed 3-value `on_agent_failure` policy. |
| **Replayability** | Four distinct contracts documented separately: `transcript_replay` (unconditional byte identity), `execution_replay` (conditional on ten pinning conditions), golden-test byte identity, `fake_provider` determinism. No "it should be deterministic" hand-waving. |
| **Persistence** | Canonical `Artifact` (§5.10) with RFC-8785 JCS-canonicalized `transcript_digest` (SHA-256). Tamper-evident. |
| **Execution mode** | MVP is **batch-only** (ADR-004). Interactive / event-stream / async are explicitly v1+. |

Full discussion in §10 *Competitive Positioning* of the spec.

---

## Quick start

The reference runtime ships three adapters out of the box: the
deterministic `FakeProvider` (for tests and reproducible demos), an
OpenAI-shaped HTTP adapter (for real-model sessions against
`api.openai.com` or any OpenAI-Chat-Completions-compatible endpoint),
and an Anthropic-shaped HTTP adapter (for real-model sessions against
`api.anthropic.com` or any Anthropic-Messages-compatible endpoint).
Every flow produces a persisted, byte-identically replayable artifact.

The distribution name is `symposium-protocol`; the import package is
`symposium` (cf. scikit-learn → sklearn).

```bash
# Stable install (PyPI)
pip install symposium-protocol      # then: import symposium

# Released tag, straight from GitHub (works without PyPI)
pip install "git+https://github.com/terrordrummer/symposium@v1.5.0"

# Development install (editable, from a clone)
git clone https://github.com/terrordrummer/symposium
cd symposium
pip install -e ".[test]"
```

### Fake-driven session (no API key, no network)

```bash
symposium run \
  --config examples/configs/walking-skeleton.yaml \
  --script examples/scripts/walking-skeleton.json \
  --output runs/ \
  examples/problem.md

# Replay (byte-identity check on the stored canonical_transcript)
symposium replay runs/demo-walking-skeleton-001

# Validate the artifact against the v1.0.0 JSON Schemas
symposium validate runs/demo-walking-skeleton-001/artifact.json
```

### OpenAI-driven session

```bash
export OPENAI_API_KEY=sk-...
# Optional: point at a self-hosted OpenAI-compatible endpoint
# export OPENAI_BASE_URL=https://my-llm-proxy.internal/v1

symposium run \
  --config examples/configs/openai.yaml \
  --output runs/ \
  examples/problem.md
```

### Anthropic-driven session

```bash
export ANTHROPIC_API_KEY=sk-ant-...
# Optional: point at a self-hosted Anthropic-compatible endpoint
# export ANTHROPIC_BASE_URL=https://my-llm-proxy.internal/v1

symposium run \
  --config examples/configs/anthropic.yaml \
  --output runs/ \
  examples/problem.md
```

### Selecting the panel

Before round 1 the §4.1 **selector** chooses the active deliberation
panel and binds the coordinator. `Config.selector.strategy` picks one of
three strategies, each emitting a schema-valid `SelectorOutput`
(§5.11) written to `<run_dir>/selector_output.json` on every run:

- **`fixed`** (default, MVP/R3) — degenerate: the panel is the declared
  `default_deliberation_panel` and the coordinator is the declared
  `coordinator_agent`. Makes **no** provider call.
- **`rules`** — pure, deterministic. Matches each agent's persona
  metadata (`reasoning_scope` / `domain_scope`) against the
  `problem_statement` via a transparent keyword table; records dropped
  agents in `excluded_agents`. No provider call, so the same `(config)`
  yields a byte-identical decision (and stays replayable under §7.6).
- **`llm`** — one bounded provider invocation (the §6.2
  `expected_output_schema = null` free-text path, driven by the
  coordinator agent's `provider`/`model`) parsed into a `SelectorOutput`.
  Requires a `selector_budget` (§5.2); its usage is budgeted separately
  and never enters `Artifact.cumulative_usage` or the `transcript_digest`.
  For fake sessions, script the single selector call with
  `--selector-script` (mirrors `--script`).

```bash
# rules: deterministic, no model call
symposium run \
  --config examples/configs/rules-selector.yaml \
  --script examples/scripts/walking-skeleton.json \
  --output runs/

# llm: one bounded selector call (separate fake script) + deliberation
symposium run \
  --config examples/configs/llm-selector.yaml \
  --selector-script examples/scripts/llm-selector.json \
  --script examples/scripts/walking-skeleton.json \
  --output runs/
# → stdout: selector_strategy=… / selected_agents=…
# → <run_dir>/selector_output.json
```

The selector is a distinct ADR-005 role: it chooses *who* deliberates,
emits no `canonical_transcript` message, and an empty/malformed selection
terminates the session with `reason = schema_error` before round 1.

### Inspecting metrics

Every persisted run directory can be analysed offline with `symposium
metrics`, which computes the §7.9 MVP observability set (token / cost
usage per agent and per `(provider, model)`, latency per invocation,
participation per round, branch depth, deferred-queue length, panel
contractions, schema-failure counts, termination reason, the
`usage_estimated` flag) and writes `metrics.json` next to the
artifact:

```bash
symposium metrics runs/demo-walking-skeleton-001
# → runs/demo-walking-skeleton-001/metrics.json (full breakdown)
# → stdout: one-screen human-readable summary
```

The §7.9 set is deliberately MVP — `role_purity_score`,
`disagreement_frequency`, `interaction_graph`,
`delegation_frequency`, per-invocation provider-retry counts and a
live `observability_event` stream are §7.10 v1+ extensions and
formally deferred. The MVP set is fully derivable from the persisted
`artifact.json` alone; no live event bus required.

The CLI resolves each agent's `provider` string through the adapter
registry (§6.11). Built-in registrations: `openai`, `anthropic`, and
— when `--script` is given — `fake`. Plug your own adapter in by
registering a factory before the run.

### Re-running a session

`symposium replay` (above) is the §7.5 **`transcript_replay`** — it
re-renders the *stored* `canonical_transcript` and is byte-identical
unconditionally (no model call). `symposium execution-replay` is the
§7.6 **`execution_replay`** — it *re-runs the orchestrator* against the
original `problem_statement` / `Config` to regenerate a fresh transcript,
and is reproducible only when every non-deterministic source is pinned
(the ten **pinning conditions** of §7.6: runtime, adapter, provider,
model, sampling, cache, tool_env, wallclock, persona, transcript_prefix).

```bash
symposium execution-replay runs/demo-walking-skeleton-001 \
  --script examples/scripts/walking-skeleton.json \
  --output runs/
# → runs/demo-walking-skeleton-001-replay/  (fresh run, distinct session id)
# → digest=match | digest=MISMATCH (first_divergence=…)
```

Before touching the runtime it checks every pinning condition decidable
offline and **aborts** with a `pinning_violation` diagnostic (naming the
exact condition) on the first one that cannot be satisfied — §7.6
forbids silent best-effort replay. Exit codes: `0` digest match, `3`
pinning violation, `4` digest mismatch, `1` any other error.

Reproducibility is conditional, not free (§7.8: *replayable ≠
reproducible*). Two runtime-allocated fields feed the digest but aren't
produced by the provider — `Message.id` (`uuid4`) and `Message.timestamp`
(wall-clock). `execution-replay` pins both to the values recorded in the
original transcript (§7.6 condition #8's *fixed clock source* + §9.4.1's
*deterministic id allocator*), so a deterministic `FakeProvider` run
reproduces its digest exactly — no special recording step required. A
re-execution that genuinely diverges (different content, count, or
routing) desyncs from the recorded sequence and reports a mismatch with
the first diverging message id, never a spurious match. A caller can
override the timestamp source with `fixed_clock` (a library knob).

### Library use

```python
from symposium import Config, FakeProviderScript
from symposium.providers import FakeProvider, default_registry
from symposium.scheduler import run_session

# Fake-driven: pass an explicit per-agent map
artifact = run_session(config, {"default": FakeProvider(script=script)},
                       runs_root="runs/")

# OpenAI-driven: build providers from the registry
providers = default_registry().build_session_providers(config)
artifact = run_session(config, providers, runs_root="runs/")

print(artifact.transcript_digest)        # 64-hex JCS-SHA-256 digest
print(artifact.outcome.kind)             # "synthesis" or "termination"

# §7.6 execution_replay — re-execute under the ten pinning conditions and
# compare the fresh digest. ids/timestamps are replayed from the recording,
# so a deterministic run reproduces its digest with no extra setup.
from symposium.replay import execution_replay, PinningViolation

try:
    result = execution_replay("runs/" + config.session_id,
                              providers={"default": FakeProvider(script=script)})
    print(result.digest_matches)         # True — every pinning condition satisfied
    print(result.conditions_checked, result.conditions_assumed)
except PinningViolation as exc:
    print("aborted on §7.6 condition:", exc.condition)
```

---

## Use in Claude Code (MCP server)

Symposium ships an optional **MCP server** that exposes the runtime as
tools, so a Claude client (Claude Code, Claude Desktop, claude.ai) can
launch a structured deliberation and read back its result, replay status,
and metrics — over the same `run_session(...)` API, with no changes to the
runtime or the protocol.

```bash
# Install with the optional MCP extra
pip install "symposium-protocol[mcp]"
# …or from the released tag:
pip install "symposium-protocol[mcp] @ git+https://github.com/terrordrummer/symposium@v1.6.0"

# Register the stdio server with Claude Code
claude mcp add symposium -- symposium-mcp
```

For **Claude Desktop**, add the server to your `mcpServers` config
(`claude_desktop_config.json`). Set `ANTHROPIC_API_KEY` (or
`OPENAI_API_KEY`) in `env` when you want real-provider deliberations; omit
it for fake-driven, deterministic runs:

```json
{
  "mcpServers": {
    "symposium": {
      "command": "symposium-mcp",
      "env": { "ANTHROPIC_API_KEY": "sk-ant-..." }
    }
  }
}
```

The server exposes six tools:

- **`deliberate(problem, …)`** — build a `Config` from arguments (panel
  persona ids resolved into inline personas exactly as the CLI does), run a
  session, and return `{outcome, synthesis_answer | termination_reason,
  selected_agents, transcript_digest, cumulative_usage, run_dir, rounds}`.
- **`deliberate_streaming(problem, …)`** — same arguments and same final
  result as `deliberate`, but streams each turn **live as the panel
  produces it** (every agent turn, each coordinator verdict, the final
  synthesis) via MCP progress + log notifications, so you can follow the
  discussion as it evolves instead of waiting for the whole session.
- **`deliberate_adaptive(problem, *, experts=None, max_expansions=2, …)`** —
  deliberate with **dynamic agent generation**. *Early-start*: each
  capability in `experts` (free-text needs) becomes a generated domain
  persona added to the panel before the first session. *Runtime*: if a
  session terminates asking for help (`user_input_required` /
  `external_research_required`), a persona is generated for that need and
  the deliberation continues in a fresh session with the augmented panel
  (up to `max_expansions`). Returns `{final, sessions, generated_agents,
  expansions, panel_final}`. Host-orchestrated over the frozen runtime.
- **`generate_persona(need, …)`** — design one new expert `Persona` for a
  capability gap (constrained to the `Persona` JSON Schema, validated) and
  return it, to use as a `panel` member.
- **`get_run_summary(run_dir)`** — load a persisted run, recompute the §7.9
  metrics, verify the §7.5 transcript replay, and return a compact summary.
- **`list_personas()`** — the six built-in personas (R3 default panel +
  coordinator) to use as `panel` / `coordinator` arguments.

A typical `deliberate` call from a Claude client:

```jsonc
// default: route each persona across the installed terminal CLIs — NO API
// key (provider="cli-auto"): visionary → codex, the rest → claude, with
// fallback to whichever CLI is installed
deliberate(problem="Should we adopt a structured deliberation protocol?")

// force a single terminal CLI for all agents
deliberate(problem="…", provider="claude-cli")   // or "codex-cli"

// real HTTP API instead (reads ANTHROPIC_API_KEY from the env)
deliberate(problem="…", provider="anthropic")

// deterministic, network-free (used by the tests and demos)
deliberate(
  problem="demo",
  provider="fake",
  fake_script_path="examples/scripts/walking-skeleton.json"
)
```

**No API key needed.** The default `provider="cli-auto"` runs each panel
turn through a locally-installed terminal CLI, reusing its existing login
(OAuth/keychain) — no `ANTHROPIC_API_KEY`/`OPENAI_API_KEY`. It routes by
persona — the lateral/creative **visionary** to `codex-cli`
(`codex exec --output-schema …`, model **`gpt-5.5`** with reasoning effort
`max`), the technical/systematic personas (logician, engineer, researcher,
critic, coordinator) to `claude-cli` (`claude -p --output-format json
--json-schema …`, model **`opus`** — alias for the latest Opus on the
local CLI, currently 4.7) — and **falls back** to whichever CLI is
actually installed (only `claude` installed → the whole panel runs on
claude, and vice-versa). Force one CLI with `provider="claude-cli"` /
`"codex-cli"`. Per-call timeout is **600s** (was 180s through v1.10.2,
which empirically timed out mid-turn on multi-paragraph technical prompts
that produce 10+ internal iterations); session wallclock defaults to
**1800s** (30 min) for a full 5-agent × 4-round panel to have room to
complete.

**Hosted-inside-Claude-Code safety.** When the Symposium runtime is itself
hosted inside a Claude Code session (eg. via the `symposium-mcp` server
launched as an MCP child), the CLI adapters spawn each turn with a
**headless child environment**: (1) nested-Claude-Code markers
(`CLAUDECODE`, `CLAUDE_CODE_ENTRYPOINT`/`EXECPATH`/`SESSION_ID`/
`PROVIDER_MANAGED_BY_HOST`), effort overrides
(`CLAUDE_CODE_EFFORT_LEVEL` / `CLAUDE_EFFORT`), and bare-mode markers
(`CLAUDE_CODE_SIMPLE`) are stripped before each spawn; (2)
`CLAUDE_CODE_DISABLE_CLAUDE_MDS`, `CLAUDE_CODE_DISABLE_AUTO_MEMORY`,
`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`, and
`CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` are set to `1` to suppress the
child's *own* auto-loads (the CLAUDE.md auto-discovery walk alone can
turn a sub-second deliberation turn into a multi-minute hang against a
populated `~/.claude/` and Workspace tree). The child CLI then takes
its normal headless `-p` / `exec --json` path and does not inherit the
parent's session state or extended-thinking effort. `ANTHROPIC_*`,
`CODEX_HOME`, `PATH`, locale, and proxy / cert vars are preserved. The
codex adapter also passes `--ignore-user-config --ignore-rules` by default
(opt-out via `isolated=False`; requires codex CLI ≥ 0.122.0). The claude
adapter offers an opt-in `bare=True` for full headless mode — off by
default, because `--bare` disables OAuth/keychain and requires an
`ANTHROPIC_API_KEY`.

**Billing.** When a CLI is logged in with a **subscription** (Claude
Pro/Max for `claude`, a ChatGPT plan for `codex`), turns run against that
subscription's usage and **rate limits — not metered, per-token API
billing**. There is no separate dollar charge to an API account; you are
spending subscription quota, so a full panel (≈ one call per turn) and
especially `deliberate_adaptive` (multiple linked sessions) consume that
quota faster and can hit plan limits. The `cost_usd` Symposium records for
a CLI turn is an **API-equivalent reference** (what the tokens would cost
at API rates), reported as estimated — not a bill. (Only if a CLI is
authenticated via an **API key** instead of a subscription login is the
usage metered.) Use `provider="fake"` for free, deterministic, offline
demos. The HTTP adapters (`anthropic`, `openai`) call the metered API and
do read an API key. Both CLI providers also work from the plain CLI:
`provider: claude-cli` / `codex-cli` in a config's agents.

The `mcp` dependency is optional: `import symposium` and the `symposium`
CLI work without it. See `symposium/integrations/mcp_server.py`.

---

## What's in this repo

```
.
├── docs/
│   ├── specification.md          # The protocol (normative, ~6440 lines)
│   ├── repository-strategy.md    # Reference-impl conventions (non-normative)
│   └── schemas/v1.0.0/           # 16 JSON Schemas (Draft 2020-12)
│       └── examples/             # 28 positive + 36 negative fixtures + validators
├── symposium/                    # Reference Python runtime
│   ├── models.py                 # Pydantic models mirroring the JSON Schemas
│   ├── providers/                # ProviderAdapter + registry + Fake/OpenAI/Anthropic/Claude-CLI/Codex-CLI adapters
│   ├── selector/                 # §4.1 selector: fixed / rules / llm strategies
│   ├── scheduler/                # §4.11 pseudocode → executable loop
│   ├── storage/                  # Run directory layout + JCS digest
│   ├── replay/                   # transcript_replay (§7.5) + execution_replay (§7.6)
│   ├── observability/            # §7.9 MVP metric set (offline)
│   ├── personas/                 # MVP default panel (R3)
│   ├── integrations/             # Host integrations — MCP server (`symposium-mcp`)
│   └── cli/                      # `symposium` command
├── examples/                     # Walking-skeleton + rules/llm selector configs + scripts
├── tests/                        # pytest suite (FakeProvider determinism,
│                                 #   scheduler invariants, e2e schema
│                                 #   validation, replay byte-identity)
├── pyproject.toml
├── .github/workflows/             # validate (CI) + release (publish on tag)
├── CONTRIBUTING.md
├── ROADMAP.md                    # thin pointer to spec §12 (normative roadmap)
├── LICENSE                       # Apache 2.0
└── README.md
```

**What's normative**: `docs/specification.md` §1–§9 + the JSON Schemas
under `docs/schemas/v1.0.0/`. A conformant Symposium runtime satisfies
every MUST / MUST NOT there and validates against the schemas. Sections
§10–§13 are positioning, integration, roadmap, and vision (non-binding).
§14 is a thin pointer to the non-normative companion.

**What's reference, not normative**: everything under `symposium/`,
`examples/`, and `tests/`. The Python package is one valid implementation
of the protocol; a different runtime in a different language is equally
valid as long as it conforms to the spec.

---

## Conformance check

Two validators ship with the schemas. Any contributor or implementor
can re-run them locally:

```bash
cd docs/schemas/v1.0.0/examples
pip install "jsonschema==4.26.0" "referencing>=0.35" "rfc8785>=0.1.4"
python3 validate.py            # 28/28
python3 validate_negative.py   # 36/36
```

The reference runtime's own test suite (pytest) cross-checks the
artifact it emits against those same schemas:

```bash
pip install -e ".[test]"
pytest -q
```

CI runs both on every push and every pull request (see badge above).

---

## Reading order

If you only want the gist, the first 200 lines of the spec are enough:
§1 (conformance surface), §2 (vocabulary), §3 (overview + non-goals).

If you intend to implement: §1 → §2 → §4 (runtime + scheduler) →
§5 (schemas) → §6 (provider/tool adapter contract) → §7
(persistence + replay) → §8 (budget + failure + security) →
§9 (testing harness). §4.11 is the canonical pseudocode.

If you want to compare against existing frameworks: §10 covers
AutoGen, CrewAI, LangGraph, and OpenAI Agents SDK.

---

## Status

**v1.0 — specification frozen 2026-05-26.** Ratified by joint adversarial
review (10 passes, bilateral sign-off). The 16 JSON Schemas under
`docs/schemas/v1.0.0/` are pinned at this version. Forward-compatible
changes will publish under `docs/schemas/v1.1.0/` etc., per the
versioning policy in §5.1.

Issues, errata, and discussion: use the GitHub issue tracker.

## License

[Apache 2.0](LICENSE).
