{"id":50248277,"url":"https://github.com/terrordrummer/symposium","last_synced_at":"2026-05-29T01:00:57.892Z","repository":{"id":360318530,"uuid":"1247821401","full_name":"terrordrummer/symposium","owner":"terrordrummer","description":"An opinionated protocol for structured, sequential, adversarial multi-agent deliberation. Normative specification + v1.0.0 JSON Schemas.","archived":false,"fork":false,"pushed_at":"2026-05-26T23:38:54.000Z","size":1325,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-27T00:20:51.567Z","etag":null,"topics":["ai-agents","deliberation","json-schema","llm","multi-agent","protocol","reasoning","specification"],"latest_commit_sha":null,"homepage":"https://github.com/terrordrummer/symposium/blob/main/docs/specification.md","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/terrordrummer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-23T20:34:49.000Z","updated_at":"2026-05-26T23:38:57.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/terrordrummer/symposium","commit_stats":null,"previous_names":["terrordrummer/symposium"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/terrordrummer/symposium","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrordrummer%2Fsymposium","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrordrummer%2Fsymposium/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrordrummer%2Fsymposium/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrordrummer%2Fsymposium/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/terrordrummer","download_url":"https://codeload.github.com/terrordrummer/symposium/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrordrummer%2Fsymposium/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33632271,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-28T02:00:06.440Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","deliberation","json-schema","llm","multi-agent","protocol","reasoning","specification"],"created_at":"2026-05-27T00:01:30.136Z","updated_at":"2026-05-29T01:00:57.874Z","avatar_url":"https://github.com/terrordrummer.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/logo.png\" alt=\"Symposium logo\" width=\"180\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eSymposium\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cem\u003eAn opinionated protocol for structured, sequential, adversarial multi-agent deliberation.\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"docs/specification.md\"\u003e\u003cimg alt=\"Spec\" src=\"https://img.shields.io/badge/spec-1.0-1a365d?style=flat-square\"\u003e\u003c/a\u003e\n  \u003ca href=\"docs/schemas/v1.0.0/\"\u003e\u003cimg alt=\"Schemas\" src=\"https://img.shields.io/badge/JSON%20Schema-v1.0.0-d4a017?style=flat-square\"\u003e\u003c/a\u003e\n  \u003ca href=\"symposium/\"\u003e\u003cimg alt=\"Reference impl\" src=\"https://img.shields.io/badge/reference%20impl-Python%203.11%2B-3776ab?style=flat-square\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/terrordrummer/symposium/actions/workflows/validate.yml\"\u003e\u003cimg alt=\"CI\" src=\"https://img.shields.io/github/actions/workflow/status/terrordrummer/symposium/validate.yml?branch=main\u0026label=ci\u0026style=flat-square\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/badge/license-Apache%202.0-333333?style=flat-square\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## What is this?\n\nSymposium is a **protocol specification** + a **reference Python\nruntime** that orchestrates a small panel of LLM-backed agents through\na structured, turn-based deliberation, producing a single, replayable,\nschema-validated artifact.\n\nIt is **not** a generic agent framework. It enforces exactly one\nconversation topology — fixed panel, one primary turn per agent per\nround, one structurally-separated coordinator, bounded forks — and\ntrades topology flexibility for **testable scheduler invariants** and\n**byte-identical replay** of any past session.\n\nTwo things ship together in this repo:\n\n1. **`docs/specification.md`** — the normative protocol. Implementable\n   in any language. The spec is what conformance means.\n2. **`symposium/`** — the reference Python runtime. Today: full\n   scheduler, persistence, replay, the deterministic `FakeProvider`\n   adapter, an OpenAI-shaped HTTP adapter (real OpenAI plus\n   self-hosted OpenAI-compatible endpoints), and an Anthropic-shaped\n   HTTP adapter (real Anthropic plus self-hosted Anthropic-compatible\n   endpoints).\n\n---\n\n## Why one more protocol?\n\nMost multi-agent stacks expose enough flexibility (group chat,\narbitrary handoffs, nested supervisors) that any two implementations\ndiverge on the parts that matter — when does the conversation stop, what\nexactly is replayed, what fails the run, how is delegation routed. Each\nimplementation invents its own answers, and operators end up debugging\nthe framework instead of the agents.\n\nSymposium goes the opposite way: **one opinionated topology, sharp\nboundaries, closed enums.** What you get in exchange:\n\n| | Symposium |\n|---|---|\n| **Topology** | Fixed `deliberation_panel`, one `primary_turn` per agent per round, single `coordination_turn` from a structurally-separated `coordinator_agent`. |\n| **Inter-agent routing** | Schema-validated `direct_request` only. Inline `@AgentName` in prose is never routing — prompt-injection resistant by construction. |\n| **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). |\n| **Failure surface** | Closed 7-value termination-reason enum; closed 12-value adapter `error.kind` enum; closed 3-value `on_agent_failure` policy. |\n| **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. |\n| **Persistence** | Canonical `Artifact` (§5.10) with RFC-8785 JCS-canonicalized `transcript_digest` (SHA-256). Tamper-evident. |\n| **Execution mode** | MVP is **batch-only** (ADR-004). Interactive / event-stream / async are explicitly v1+. |\n\nFull discussion in §10 *Competitive Positioning* of the spec.\n\n---\n\n## Quick start\n\nThe reference runtime ships three adapters out of the box: the\ndeterministic `FakeProvider` (for tests and reproducible demos), an\nOpenAI-shaped HTTP adapter (for real-model sessions against\n`api.openai.com` or any OpenAI-Chat-Completions-compatible endpoint),\nand an Anthropic-shaped HTTP adapter (for real-model sessions against\n`api.anthropic.com` or any Anthropic-Messages-compatible endpoint).\nEvery flow produces a persisted, byte-identically replayable artifact.\n\nThe distribution name is `symposium-protocol`; the import package is\n`symposium` (cf. scikit-learn → sklearn).\n\n```bash\n# Stable install (PyPI)\npip install symposium-protocol      # then: import symposium\n\n# Released tag, straight from GitHub (works without PyPI)\npip install \"git+https://github.com/terrordrummer/symposium@v1.5.0\"\n\n# Development install (editable, from a clone)\ngit clone https://github.com/terrordrummer/symposium\ncd symposium\npip install -e \".[test]\"\n```\n\n### Fake-driven session (no API key, no network)\n\n```bash\nsymposium run \\\n  --config examples/configs/walking-skeleton.yaml \\\n  --script examples/scripts/walking-skeleton.json \\\n  --output runs/ \\\n  examples/problem.md\n\n# Replay (byte-identity check on the stored canonical_transcript)\nsymposium replay runs/demo-walking-skeleton-001\n\n# Validate the artifact against the v1.0.0 JSON Schemas\nsymposium validate runs/demo-walking-skeleton-001/artifact.json\n```\n\n### OpenAI-driven session\n\n```bash\nexport OPENAI_API_KEY=sk-...\n# Optional: point at a self-hosted OpenAI-compatible endpoint\n# export OPENAI_BASE_URL=https://my-llm-proxy.internal/v1\n\nsymposium run \\\n  --config examples/configs/openai.yaml \\\n  --output runs/ \\\n  examples/problem.md\n```\n\n### Anthropic-driven session\n\n```bash\nexport ANTHROPIC_API_KEY=sk-ant-...\n# Optional: point at a self-hosted Anthropic-compatible endpoint\n# export ANTHROPIC_BASE_URL=https://my-llm-proxy.internal/v1\n\nsymposium run \\\n  --config examples/configs/anthropic.yaml \\\n  --output runs/ \\\n  examples/problem.md\n```\n\n### Selecting the panel\n\nBefore round 1 the §4.1 **selector** chooses the active deliberation\npanel and binds the coordinator. `Config.selector.strategy` picks one of\nthree strategies, each emitting a schema-valid `SelectorOutput`\n(§5.11) written to `\u003crun_dir\u003e/selector_output.json` on every run:\n\n- **`fixed`** (default, MVP/R3) — degenerate: the panel is the declared\n  `default_deliberation_panel` and the coordinator is the declared\n  `coordinator_agent`. Makes **no** provider call.\n- **`rules`** — pure, deterministic. Matches each agent's persona\n  metadata (`reasoning_scope` / `domain_scope`) against the\n  `problem_statement` via a transparent keyword table; records dropped\n  agents in `excluded_agents`. No provider call, so the same `(config)`\n  yields a byte-identical decision (and stays replayable under §7.6).\n- **`llm`** — one bounded provider invocation (the §6.2\n  `expected_output_schema = null` free-text path, driven by the\n  coordinator agent's `provider`/`model`) parsed into a `SelectorOutput`.\n  Requires a `selector_budget` (§5.2); its usage is budgeted separately\n  and never enters `Artifact.cumulative_usage` or the `transcript_digest`.\n  For fake sessions, script the single selector call with\n  `--selector-script` (mirrors `--script`).\n\n```bash\n# rules: deterministic, no model call\nsymposium run \\\n  --config examples/configs/rules-selector.yaml \\\n  --script examples/scripts/walking-skeleton.json \\\n  --output runs/\n\n# llm: one bounded selector call (separate fake script) + deliberation\nsymposium run \\\n  --config examples/configs/llm-selector.yaml \\\n  --selector-script examples/scripts/llm-selector.json \\\n  --script examples/scripts/walking-skeleton.json \\\n  --output runs/\n# → stdout: selector_strategy=… / selected_agents=…\n# → \u003crun_dir\u003e/selector_output.json\n```\n\nThe selector is a distinct ADR-005 role: it chooses *who* deliberates,\nemits no `canonical_transcript` message, and an empty/malformed selection\nterminates the session with `reason = schema_error` before round 1.\n\n### Inspecting metrics\n\nEvery persisted run directory can be analysed offline with `symposium\nmetrics`, which computes the §7.9 MVP observability set (token / cost\nusage per agent and per `(provider, model)`, latency per invocation,\nparticipation per round, branch depth, deferred-queue length, panel\ncontractions, schema-failure counts, termination reason, the\n`usage_estimated` flag) and writes `metrics.json` next to the\nartifact:\n\n```bash\nsymposium metrics runs/demo-walking-skeleton-001\n# → runs/demo-walking-skeleton-001/metrics.json (full breakdown)\n# → stdout: one-screen human-readable summary\n```\n\nThe §7.9 set is deliberately MVP — `role_purity_score`,\n`disagreement_frequency`, `interaction_graph`,\n`delegation_frequency`, per-invocation provider-retry counts and a\nlive `observability_event` stream are §7.10 v1+ extensions and\nformally deferred. The MVP set is fully derivable from the persisted\n`artifact.json` alone; no live event bus required.\n\nThe CLI resolves each agent's `provider` string through the adapter\nregistry (§6.11). Built-in registrations: `openai`, `anthropic`, and\n— when `--script` is given — `fake`. Plug your own adapter in by\nregistering a factory before the run.\n\n### Re-running a session\n\n`symposium replay` (above) is the §7.5 **`transcript_replay`** — it\nre-renders the *stored* `canonical_transcript` and is byte-identical\nunconditionally (no model call). `symposium execution-replay` is the\n§7.6 **`execution_replay`** — it *re-runs the orchestrator* against the\noriginal `problem_statement` / `Config` to regenerate a fresh transcript,\nand is reproducible only when every non-deterministic source is pinned\n(the ten **pinning conditions** of §7.6: runtime, adapter, provider,\nmodel, sampling, cache, tool_env, wallclock, persona, transcript_prefix).\n\n```bash\nsymposium execution-replay runs/demo-walking-skeleton-001 \\\n  --script examples/scripts/walking-skeleton.json \\\n  --output runs/\n# → runs/demo-walking-skeleton-001-replay/  (fresh run, distinct session id)\n# → digest=match | digest=MISMATCH (first_divergence=…)\n```\n\nBefore touching the runtime it checks every pinning condition decidable\noffline and **aborts** with a `pinning_violation` diagnostic (naming the\nexact condition) on the first one that cannot be satisfied — §7.6\nforbids silent best-effort replay. Exit codes: `0` digest match, `3`\npinning violation, `4` digest mismatch, `1` any other error.\n\nReproducibility is conditional, not free (§7.8: *replayable ≠\nreproducible*). Two runtime-allocated fields feed the digest but aren't\nproduced by the provider — `Message.id` (`uuid4`) and `Message.timestamp`\n(wall-clock). `execution-replay` pins both to the values recorded in the\noriginal transcript (§7.6 condition #8's *fixed clock source* + §9.4.1's\n*deterministic id allocator*), so a deterministic `FakeProvider` run\nreproduces its digest exactly — no special recording step required. A\nre-execution that genuinely diverges (different content, count, or\nrouting) desyncs from the recorded sequence and reports a mismatch with\nthe first diverging message id, never a spurious match. A caller can\noverride the timestamp source with `fixed_clock` (a library knob).\n\n### Library use\n\n```python\nfrom symposium import Config, FakeProviderScript\nfrom symposium.providers import FakeProvider, default_registry\nfrom symposium.scheduler import run_session\n\n# Fake-driven: pass an explicit per-agent map\nartifact = run_session(config, {\"default\": FakeProvider(script=script)},\n                       runs_root=\"runs/\")\n\n# OpenAI-driven: build providers from the registry\nproviders = default_registry().build_session_providers(config)\nartifact = run_session(config, providers, runs_root=\"runs/\")\n\nprint(artifact.transcript_digest)        # 64-hex JCS-SHA-256 digest\nprint(artifact.outcome.kind)             # \"synthesis\" or \"termination\"\n\n# §7.6 execution_replay — re-execute under the ten pinning conditions and\n# compare the fresh digest. ids/timestamps are replayed from the recording,\n# so a deterministic run reproduces its digest with no extra setup.\nfrom symposium.replay import execution_replay, PinningViolation\n\ntry:\n    result = execution_replay(\"runs/\" + config.session_id,\n                              providers={\"default\": FakeProvider(script=script)})\n    print(result.digest_matches)         # True — every pinning condition satisfied\n    print(result.conditions_checked, result.conditions_assumed)\nexcept PinningViolation as exc:\n    print(\"aborted on §7.6 condition:\", exc.condition)\n```\n\n---\n\n## Use in Claude Code (MCP server)\n\nSymposium ships an optional **MCP server** that exposes the runtime as\ntools, so a Claude client (Claude Code, Claude Desktop, claude.ai) can\nlaunch a structured deliberation and read back its result, replay status,\nand metrics — over the same `run_session(...)` API, with no changes to the\nruntime or the protocol.\n\n```bash\n# Install with the optional MCP extra\npip install \"symposium-protocol[mcp]\"\n# …or from the released tag:\npip install \"symposium-protocol[mcp] @ git+https://github.com/terrordrummer/symposium@v1.6.0\"\n\n# Register the stdio server with Claude Code\nclaude mcp add symposium -- symposium-mcp\n```\n\nFor **Claude Desktop**, add the server to your `mcpServers` config\n(`claude_desktop_config.json`). Set `ANTHROPIC_API_KEY` (or\n`OPENAI_API_KEY`) in `env` when you want real-provider deliberations; omit\nit for fake-driven, deterministic runs:\n\n```json\n{\n  \"mcpServers\": {\n    \"symposium\": {\n      \"command\": \"symposium-mcp\",\n      \"env\": { \"ANTHROPIC_API_KEY\": \"sk-ant-...\" }\n    }\n  }\n}\n```\n\nThe server exposes six tools:\n\n- **`deliberate(problem, …)`** — build a `Config` from arguments (panel\n  persona ids resolved into inline personas exactly as the CLI does), run a\n  session, and return `{outcome, synthesis_answer | termination_reason,\n  selected_agents, transcript_digest, cumulative_usage, run_dir, rounds}`.\n- **`deliberate_streaming(problem, …)`** — same arguments and same final\n  result as `deliberate`, but streams each turn **live as the panel\n  produces it** (every agent turn, each coordinator verdict, the final\n  synthesis) via MCP progress + log notifications, so you can follow the\n  discussion as it evolves instead of waiting for the whole session.\n- **`deliberate_adaptive(problem, *, experts=None, max_expansions=2, …)`** —\n  deliberate with **dynamic agent generation**. *Early-start*: each\n  capability in `experts` (free-text needs) becomes a generated domain\n  persona added to the panel before the first session. *Runtime*: if a\n  session terminates asking for help (`user_input_required` /\n  `external_research_required`), a persona is generated for that need and\n  the deliberation continues in a fresh session with the augmented panel\n  (up to `max_expansions`). Returns `{final, sessions, generated_agents,\n  expansions, panel_final}`. Host-orchestrated over the frozen runtime.\n- **`generate_persona(need, …)`** — design one new expert `Persona` for a\n  capability gap (constrained to the `Persona` JSON Schema, validated) and\n  return it, to use as a `panel` member.\n- **`get_run_summary(run_dir)`** — load a persisted run, recompute the §7.9\n  metrics, verify the §7.5 transcript replay, and return a compact summary.\n- **`list_personas()`** — the six built-in personas (R3 default panel +\n  coordinator) to use as `panel` / `coordinator` arguments.\n\nA typical `deliberate` call from a Claude client:\n\n```jsonc\n// default: route each persona across the installed terminal CLIs — NO API\n// key (provider=\"cli-auto\"): visionary → codex, the rest → claude, with\n// fallback to whichever CLI is installed\ndeliberate(problem=\"Should we adopt a structured deliberation protocol?\")\n\n// force a single terminal CLI for all agents\ndeliberate(problem=\"…\", provider=\"claude-cli\")   // or \"codex-cli\"\n\n// real HTTP API instead (reads ANTHROPIC_API_KEY from the env)\ndeliberate(problem=\"…\", provider=\"anthropic\")\n\n// deterministic, network-free (used by the tests and demos)\ndeliberate(\n  problem=\"demo\",\n  provider=\"fake\",\n  fake_script_path=\"examples/scripts/walking-skeleton.json\"\n)\n```\n\n**No API key needed.** The default `provider=\"cli-auto\"` runs each panel\nturn through a locally-installed terminal CLI, reusing its existing login\n(OAuth/keychain) — no `ANTHROPIC_API_KEY`/`OPENAI_API_KEY`. It routes by\npersona — the lateral/creative **visionary** to `codex-cli`\n(`codex exec --output-schema …`, model **`gpt-5.5`** with reasoning effort\n`max`), the technical/systematic personas (logician, engineer, researcher,\ncritic, coordinator) to `claude-cli` (`claude -p --output-format json\n--json-schema …`, model **`opus`** — alias for the latest Opus on the\nlocal CLI, currently 4.7) — and **falls back** to whichever CLI is\nactually installed (only `claude` installed → the whole panel runs on\nclaude, and vice-versa). Force one CLI with `provider=\"claude-cli\"` /\n`\"codex-cli\"`. Per-call timeout is **600s** (was 180s through v1.10.2,\nwhich empirically timed out mid-turn on multi-paragraph technical prompts\nthat produce 10+ internal iterations); session wallclock defaults to\n**1800s** (30 min) for a full 5-agent × 4-round panel to have room to\ncomplete.\n\n**Hosted-inside-Claude-Code safety.** When the Symposium runtime is itself\nhosted inside a Claude Code session (eg. via the `symposium-mcp` server\nlaunched as an MCP child), the CLI adapters spawn each turn with a\n**headless child environment**: (1) nested-Claude-Code markers\n(`CLAUDECODE`, `CLAUDE_CODE_ENTRYPOINT`/`EXECPATH`/`SESSION_ID`/\n`PROVIDER_MANAGED_BY_HOST`), effort overrides\n(`CLAUDE_CODE_EFFORT_LEVEL` / `CLAUDE_EFFORT`), and bare-mode markers\n(`CLAUDE_CODE_SIMPLE`) are stripped before each spawn; (2)\n`CLAUDE_CODE_DISABLE_CLAUDE_MDS`, `CLAUDE_CODE_DISABLE_AUTO_MEMORY`,\n`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`, and\n`CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` are set to `1` to suppress the\nchild's *own* auto-loads (the CLAUDE.md auto-discovery walk alone can\nturn a sub-second deliberation turn into a multi-minute hang against a\npopulated `~/.claude/` and Workspace tree). The child CLI then takes\nits normal headless `-p` / `exec --json` path and does not inherit the\nparent's session state or extended-thinking effort. `ANTHROPIC_*`,\n`CODEX_HOME`, `PATH`, locale, and proxy / cert vars are preserved. The\ncodex adapter also passes `--ignore-user-config --ignore-rules` by default\n(opt-out via `isolated=False`; requires codex CLI ≥ 0.122.0). The claude\nadapter offers an opt-in `bare=True` for full headless mode — off by\ndefault, because `--bare` disables OAuth/keychain and requires an\n`ANTHROPIC_API_KEY`.\n\n**Billing.** When a CLI is logged in with a **subscription** (Claude\nPro/Max for `claude`, a ChatGPT plan for `codex`), turns run against that\nsubscription's usage and **rate limits — not metered, per-token API\nbilling**. There is no separate dollar charge to an API account; you are\nspending subscription quota, so a full panel (≈ one call per turn) and\nespecially `deliberate_adaptive` (multiple linked sessions) consume that\nquota faster and can hit plan limits. The `cost_usd` Symposium records for\na CLI turn is an **API-equivalent reference** (what the tokens would cost\nat API rates), reported as estimated — not a bill. (Only if a CLI is\nauthenticated via an **API key** instead of a subscription login is the\nusage metered.) Use `provider=\"fake\"` for free, deterministic, offline\ndemos. The HTTP adapters (`anthropic`, `openai`) call the metered API and\ndo read an API key. Both CLI providers also work from the plain CLI:\n`provider: claude-cli` / `codex-cli` in a config's agents.\n\nThe `mcp` dependency is optional: `import symposium` and the `symposium`\nCLI work without it. See `symposium/integrations/mcp_server.py`.\n\n---\n\n## What's in this repo\n\n```\n.\n├── docs/\n│   ├── specification.md          # The protocol (normative, ~6440 lines)\n│   ├── repository-strategy.md    # Reference-impl conventions (non-normative)\n│   └── schemas/v1.0.0/           # 16 JSON Schemas (Draft 2020-12)\n│       └── examples/             # 28 positive + 36 negative fixtures + validators\n├── symposium/                    # Reference Python runtime\n│   ├── models.py                 # Pydantic models mirroring the JSON Schemas\n│   ├── providers/                # ProviderAdapter + registry + Fake/OpenAI/Anthropic/Claude-CLI/Codex-CLI adapters\n│   ├── selector/                 # §4.1 selector: fixed / rules / llm strategies\n│   ├── scheduler/                # §4.11 pseudocode → executable loop\n│   ├── storage/                  # Run directory layout + JCS digest\n│   ├── replay/                   # transcript_replay (§7.5) + execution_replay (§7.6)\n│   ├── observability/            # §7.9 MVP metric set (offline)\n│   ├── personas/                 # MVP default panel (R3)\n│   ├── integrations/             # Host integrations — MCP server (`symposium-mcp`)\n│   └── cli/                      # `symposium` command\n├── examples/                     # Walking-skeleton + rules/llm selector configs + scripts\n├── tests/                        # pytest suite (FakeProvider determinism,\n│                                 #   scheduler invariants, e2e schema\n│                                 #   validation, replay byte-identity)\n├── pyproject.toml\n├── .github/workflows/             # validate (CI) + release (publish on tag)\n├── CONTRIBUTING.md\n├── ROADMAP.md                    # thin pointer to spec §12 (normative roadmap)\n├── LICENSE                       # Apache 2.0\n└── README.md\n```\n\n**What's normative**: `docs/specification.md` §1–§9 + the JSON Schemas\nunder `docs/schemas/v1.0.0/`. A conformant Symposium runtime satisfies\nevery MUST / MUST NOT there and validates against the schemas. Sections\n§10–§13 are positioning, integration, roadmap, and vision (non-binding).\n§14 is a thin pointer to the non-normative companion.\n\n**What's reference, not normative**: everything under `symposium/`,\n`examples/`, and `tests/`. The Python package is one valid implementation\nof the protocol; a different runtime in a different language is equally\nvalid as long as it conforms to the spec.\n\n---\n\n## Conformance check\n\nTwo validators ship with the schemas. Any contributor or implementor\ncan re-run them locally:\n\n```bash\ncd docs/schemas/v1.0.0/examples\npip install \"jsonschema==4.26.0\" \"referencing\u003e=0.35\" \"rfc8785\u003e=0.1.4\"\npython3 validate.py            # 28/28\npython3 validate_negative.py   # 36/36\n```\n\nThe reference runtime's own test suite (pytest) cross-checks the\nartifact it emits against those same schemas:\n\n```bash\npip install -e \".[test]\"\npytest -q\n```\n\nCI runs both on every push and every pull request (see badge above).\n\n---\n\n## Reading order\n\nIf you only want the gist, the first 200 lines of the spec are enough:\n§1 (conformance surface), §2 (vocabulary), §3 (overview + non-goals).\n\nIf you intend to implement: §1 → §2 → §4 (runtime + scheduler) →\n§5 (schemas) → §6 (provider/tool adapter contract) → §7\n(persistence + replay) → §8 (budget + failure + security) →\n§9 (testing harness). §4.11 is the canonical pseudocode.\n\nIf you want to compare against existing frameworks: §10 covers\nAutoGen, CrewAI, LangGraph, and OpenAI Agents SDK.\n\n---\n\n## Status\n\n**v1.0 — specification frozen 2026-05-26.** Ratified by joint adversarial\nreview (10 passes, bilateral sign-off). The 16 JSON Schemas under\n`docs/schemas/v1.0.0/` are pinned at this version. Forward-compatible\nchanges will publish under `docs/schemas/v1.1.0/` etc., per the\nversioning policy in §5.1.\n\nIssues, errata, and discussion: use the GitHub issue tracker.\n\n## License\n\n[Apache 2.0](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterrordrummer%2Fsymposium","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fterrordrummer%2Fsymposium","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterrordrummer%2Fsymposium/lists"}