Summon is a dependency-free dispatcher. It routes tasks from one agent CLI to supported CLIs and configured endpoints wherever the host can execute a shell command:
- Coding CLIs: Claude Code, Codex, Cursor CLI, Gemini CLI, Kimi, Antigravity, and ArkCLI.
- T3 Code: install Summon into the Claude, Codex, and Cursor skill roots
T3 discovers (
python install.py --profile t3). Not a native T3 plugin; see the T3 Code setup guide. - AI IDEs: Cursor, Antigravity, or VS Code with an agent extension. The skill installs as a slash command, or the agent invokes the dispatcher.
- Desktop agent apps: the Claude app and the ChatGPT app (formerly Codex), whose agent modes can run the dispatcher and read the skill.
- A plain terminal, where you drive it yourself.
From any of those hosts, you can hand a task to another model, run several at once, convene a council, or start a governed deliberation. It also reaches configured endpoints that implement Summon's supported OpenAI-compatible API subset directly, or through OpenCode's toolful gateway when the agent needs a file/tool loop. OpenRouter, OpenAI, Google-compatible endpoints, and local models (Ollama, LM Studio) are supported examples; endpoint compatibility and account access still vary.
┌──────────────────────┐
any host CLI ────────► │ summon │ ───► claude (Anthropic)
(claude, codex, │ stdlib dispatcher │ ───► codex (OpenAI)
cursor, gemini, kimi, │ one JSON envelope │ ───► cursor-agent (Cursor)
opencode, or terminal) │ no server, no pip │ ───► gemini (Google)
└──────────────────────┘ ───► kimi (Moonshot AI)
├──► agy (Antigravity)
├──► arkcli (BytePlus Coding Plan)
├──► opencode (OpenCode gateway)
├──► zcode (native ZCode preview)
└──► openai-compat (ModelArk / OpenRouter /
Z.AI Coding Plan / OpenAI-compatible gateways / …)
Most multi-agent tools assume one specific CLI is the orchestrator. Summon inverts that:
any CLI can be the boss. Your Codex session can summon Claude for a review. Your Claude
session can summon Codex for an adversarial pass. Your terminal can summon a whole council
to decide something. They run in parallel. Add --worktree to give each editing agent its
own isolated branch, and inspect or branch on the resulting JSON envelopes.
Each backend uses its own login, so Summon can combine Claude, ChatGPT, Cursor, Gemini, Antigravity, ArkCLI, and OpenCode on one task. Each provider keeps its own billing and account boundary.
Who it's for
- Anyone stacking AI subscriptions. If you use Claude Max, ChatGPT, Cursor, or Gemini, Summon can put them on the same task while each provider keeps its own billing boundary. Using T3 Code as the control plane? Summon installs into the skill roots T3's Claude/Codex sessions already load.
- Developers who live in Claude Code, Codex, or Cursor (or any other AI coding tool) and want the other models one command away, without leaving the one they're in.
- Anyone who wants an independent review. Cross-vendor review keeps the model that wrote the work separate from the model that evaluates it.
- People making decisions with AI who need a governed answer: council mode gives
diverse positions and a chaired recommendation;
deliberateadds fixed options, quorum, hard attempt/deadline bounds, durable replay, and explicit human boundaries. - People who want an actual multi-agent room: the authenticated conversation atlas
keeps a persistent, project-grouped session across Codex, Claude Code, Cursor, and
terminal initiators, with human messages and explicit, bounded roster-agent turns that
can inspect history, resume an eligible certified provider session, or fork visibly on
drift. Candidate and unsupported backends refuse continuation rather than implying
that a compatible session exists. Interactive council rounds and the separate
governed-decision view remain context/control-plane boundaries.
See
docs/SUMMON_CONVERSATION_PLAN.md. - Power users running fleets of agents: fan a task across N models in parallel, with per-backend throttling and resumable batches.
- Anyone unifying local + cloud models behind one interface (subscription CLIs and OpenAI-compatible APIs, including self-hosted).
Summon remains a dispatcher first, with a local conversation atlas for brainstorming, interactive council work, and explicitly requested roster-agent turns. The atlas is a dependency-free, Chatpack-informed messenger: searchable project/initiator rooms, grouped human/agent/lifecycle events, a redacted evidence drawer, cursor-aware reconnect, and a composer that separates context from an explicit turn. Turns use the same redacted, durable event contracts and a pre-launch fence; they do not turn ordinary chat into authority or silently promote a conversation into a governed decision. Chatpack itself is not installed or required.
What you can do with it
- Cross-vendor code review:
summon dispatch --agent adversarial-reviewersends your diff to a different vendor than wrote the code. - Race several implementations: three models each build the same spec in isolated git worktrees; you diff the branches and keep the best.
- Decide by council: ask "monorepo or polyrepo?" and four diverse models answer, rank each other anonymously, and a chairman synthesizes a call with confidence and dissents.
- Swarm over documents: a manifest of 40 jobs with per-backend concurrency, resumable if it crashes. Good for reviewing, summarizing, or labeling at scale.
- Structured extraction:
--json-schemavalidates an agent's final JSON and, on a backend that supports resume, spends one corrective retry when it does not match. - Inspect usage and credit evidence safely:
summon usage import --from snapshot.jsonvalidates an operator export,usage example --out FILEcreates a synthetic fixture, andusage export --out FILEwrites a portable redacted snapshot. The first live adapter can read Codex account usage only with an explicit provider allowlist and--allow-account-usage-read; it does not log in, repair authentication, dispatch a model, retry, or change routing. Allowance, API balance, account credit, and rate limits remain separate instead of being collapsed into a misleading score. - Governed deliberation:
summon deliberaterecords a receipt-bound, fixed-option decision policy and journal. The fresh CLI lane can run one bounded round of enforceable read-only subprocess seats after durable receipt/owner fencing; approval, resume, ACP/HTTP, and writable routes remain explicitly gated. The local browser is an observer/control surface and never silently changes the decision policy. - Create a provider-free workspace preview from a plan:
summon workspace create RUN_ID --plan FILE --runs-root DIRvalidates a strict plan, publishes it atomically, and creates only dormant operator-message destinations for inspection and simulated protocol work. It does not delegate to a real provider or attach a worker, and starts no provider, worker, session, server, or background job;workspace openandworkspace inspectverify the copied plan against the durable workspace before reuse. An explicitly configured command policy can be refreshed without browser credentials:workspace open ... --command-policy FILE --control-token-file FILEcreates a protected one-time control-token file, andworkspace refresh RUN_ID --url URL --control-token-file FILEreloads a newer generation through the loopback control surface. The refresh is provider-free, binds the request to the workspace/run, and reports an unknown outcome rather than replaying when a response cannot be reconciled. - Use local + frontier models together: an Ollama model and Claude in the same council.
- Call Astra explicitly:
astrapinsgpt-6-astraat high effort for consequential planning, architecture, research synthesis, and adversarial review. It does not inherit the ambient Codex default, and exact-model workflows still require a provider-reported served identity. - Route named local logins: keep multiple Claude config directories behind private profile names, so a public agent definition never carries a machine path or credential.
The workspace and roster changes above ship in Summon 3.5.0, whose workspace features are a preview: provider-free acceptance covers them, but live adapters are not stable-certified. See the release gates for what each profile certifies. A local test pass does not mean an installed copy contains these changes.
For a minimal provider-free workspace, save this synthetic plan as
workspace-plan.json in a private directory:
{
"schema": "summon.workspace.plan/v1",
"goal": {
"goal_id": "preview-goal",
"objective": "Inspect a dormant task workspace.",
"criteria": [{
"criterion_id": "ready",
"description": "The task is visible for inspection.",
"evidence_requirement": "Workspace inspection succeeds."
}],
"constraints": ["No provider or worker execution."],
"active_priority": "main-task",
"unresolved_decisions": []
},
"tasks": [{
"task_id": "main-task",
"role": "main",
"outcome": "A task ready for inspection.",
"scope": "This workspace preview.",
"depends_on": [],
"criterion_ids": ["ready"],
"return_condition": "The task can be inspected.",
"escalation_trigger": "The plan cannot be validated.",
"limits": {
"max_duration_ms": 60000,
"max_attempts": 1,
"max_context_bytes": 1024
}
}],
"operator_message_targets": [{"target": "main", "task_id": "main-task"}]
}
Replace PRIVATE_RUNS_DIR with a dedicated private directory outside the source
checkout; use a new run ID. Run these from the directory containing the plan
(summon.cmd on Windows):
summon workspace create preview-run --plan workspace-plan.json --runs-root PRIVATE_RUNS_DIR --json
summon workspace open preview-run --runs-root PRIVATE_RUNS_DIR --port 8765
Creation validates and copies the plan without starting a server or worker.
Open requires an available explicit port from 1 to 65535; 8765 is an example,
and there is no automatic fallback. Run open in a private interactive terminal
with stderr attached and without --json. Visit the printed loopback URL and
enter the one-time bootstrap code shown privately on stderr; the URL itself
contains no code. Keep that terminal running: the server is owned by the
foreground command, and Ctrl+C stops it.
From a second terminal, inspect the durable workspace:
summon workspace inspect preview-run --runs-root PRIVATE_RUNS_DIR --json
The plan defines dormant message destinations. Message delivery and browser
bootstrap do not grant command authority: disposition controls require a
separate explicit private --command-policy on open. If a later command or
message returns an unknown outcome, retain the exact request and operation key
and use workspace request ... --lookup before another send. For an unknown
policy refresh, use workspace refresh-status with the same --request-id
before another refresh; changing the key is not recovery.
Messaging an existing session: addressed Summon messages are durable context
for an eligible recipient. Delivering into an already-running Claude Code,
Claude Desktop, Codex or Antigravity session requires a verified adapter for
that specific operation. At the current preview boundary, governed continuation
is certified only for the named-profile Claude subprocess lane after its evidence
and ownership checks pass; other backends are candidates or unsupported and may
refuse before provider contact. The workspace preview demonstrates simulated
workers; it does not provide universal native-session attachment. jobs steer
queues guidance for a later eligible continuation, not live mid-turn injection.
Council recommendations and agent messages remain separate from permissions,
approvals and deliberation ballots.
Install
Pick the path that matches your host. All three install the skills/summon/ skill tree and
the thin sibling /council and /deliberate companions; only the destination differs.
Those companions reuse Summon's scripts and canonical references. There is no second runtime.
Agent plugin (Cursor, VS Code, Copilot, and Codex)
For clients that support the Agent Plugins standard (Cursor Marketplace, VS Code agent extensions, GitHub Copilot agent plugins, Codex with plugin support):
- From a marketplace: install the summon plugin from your client's plugin UI.
- From a checkout (local dev): copy or symlink this repo into your client's local
plugin directory. On Cursor that is
~/.cursor/plugins/local/summon/withplugin.jsonat the plugin root (this repo already ships that layout). Reload the window after copying.
The plugin bundles skills/ as-is, including the thin council and deliberate companions. No
install.py step is required for plugin hosts.
Skills registry (npx skills add)
Use one command to install the skill into your agent:
npx skills add Nafjan/summon
Your AI agent now has the summon skill. Ask it to "summon a cross-vendor review of my last
commit" or "convene a council on monorepo versus polyrepo." Add -g to install globally (every project), or
-a <agent> to target a specific one. Works with any skills-compatible agent: Claude Code,
Codex, Cursor, Gemini, Antigravity, and claw-likes like openclaw and hermes. Powered by the
open skills registry.
You need Node (for npx), Python 3.10+, and at least one AI CLI you're logged into.
After installing, ask your agent to run summon's doctor check and it lists what's ready and
what's missing. On Windows, call scripts\summon.cmd rather than invoking run_subagent.py
directly: it selects a compatible Python through py -3 and avoids a stale .py file
association. If the install reports a symlink permission error, run it again with --copy.
Multi-host installer (python install.py)
Install into every AI CLI on your machine at once (multi-host, ownership-safe):
git clone https://github.com/Nafjan/summon && cd summon
python summon.py doctor # which backends are ready? what's missing?
python install.py # install the skill into every detected AI CLI
Expired login recovery
Provider logins expire independently. If a dispatch fails with an authentication error, Summon returns a safe, vendor-specific repair plan instead of silently retrying or switching models. Check a backend without launching a task:
python summon.py auth status --cli kimi
python summon.py auth status --cli arkcli --probe
If the caller explicitly authorizes a login flow, Summon can start the vendor command (which may open a browser), but it never captures credentials and never retries the failed task:
python summon.py auth repair kimi --allow-auth-repair
# finish browser approval, then retry the original command explicitly
Without that authorization, run the vendor command yourself (kimi login, arkcli auth login, or the command shown in the error). A successful login command is not proof that a
model was served; inspect the next dispatch envelope's model.served and
served_model_evidence fields, and require named_model_verified: true for an exact pin.
Keep the model roster fresh
The model catalog supplies editorial names and roles, not service guarantees. Refresh provider rosters when onboarding, before a high-stakes review, or after a vendor announces a model:
python summon.py models --refresh
python summon.py models --cli arkcli --refresh
source: live is a fresh provider response, source: cache is a cached roster, source: config is a local CLI default, and source: static is documentation only. Codex does not
expose a complete enumeration command, so its configured default and catalog candidates are
advisory. Treat a candidate as verified only after a real dispatch returns reported
served evidence and named_model_verified: true; a display label, task name, or inferred
model.served value does not prove an exact pin.
The exact-model contract applies to provenance-required named seats across providers. Summon
emits one canonical selector where the backend supports it, refuses conflicting selectors
before provider contact, and blocks an exact seat when the provider does not return an
authoritative terminal served-model receipt. A handshake target, output-token estimate, or
catalog entry is not proof that the requested model was served. Claude may report auxiliary
models in model.models_used; aggregate token counts do not identify the lead. A flat
terminal model, an unambiguous single-model usage record, or root assistant metadata bound
to the exact terminal response establishes identity. Mixed usage without that binding
remains unverified, not a claimed fallback. Use --require-exact-model or
model-policy: exact for a custom seat. See docs/SUMMON_3.2_PLAN.md
for the routing and chat acceptance gates. The fixed-shell chat atlas is still preview-only
until its rendered-browser and owner-lifecycle gates pass.
This does not make any backend preview-only. Ordinary dispatch remains a supported
first-class path; only exact named-model claims are fail-closed. For example, if the
sol-review seat completes without an authoritative terminal identity, Summon returns
status: "blocked", error_kind: "served_model_unverified", and model.served: null.
That means “the requested model was not certified,” not “Luna ran instead.” Summon does not
infer or silently reroute the turn. The certification path is a provider-authored terminal
receipt plus parser coverage for match, mismatch, and missing-evidence cases; a fresh live
receipt is still required before a named seat can be called certified.
For a release or support bundle, generate a provider-inert evidence manifest after running the fixed release-test registry:
python tools/release_gates.py --require-clean --output "${RUNNER_TEMP:-${TMPDIR:-/tmp}}/summon-release-evidence.json"
python tools/release_manifest.py \
--evidence-file "${RUNNER_TEMP:-${TMPDIR:-/tmp}}/summon-release-evidence.json" \
--output "${RUNNER_TEMP:-${TMPDIR:-/tmp}}/summon-release-manifest.json" \
--expected-version 3.5.0 --check
The runner executes the fixed suites, records output digests, strips backend credentials and
proxies, and writes an atomic evidence file without contacting a provider. Release evidence must
be generated from a clean checkout (--require-clean); a dirty local run is diagnostic only.
Keep both evidence and manifest outside the checkout. Otherwise, creating them can make the
source tree dirty before the manifest verifies Git cleanliness.
The --check option is the GA gate. It requires a clean tree, converged owned installs, and
every named release gate recorded as pass. A diagnostic run with missing gates is not release
evidence and must not be presented as certification.
The unreleased provider-free workspace slice has a separate explicit
--profile workspace-preview check. That profile still requires every fixed
suite and every non-live gate to pass and accepts only the redacted
live_provider_evidence_missing boundary; it produces preview evidence and
cannot be used as stable/public-release evidence. A blocked or invalid live
receipt never selects this profile implicitly.
The installer preserves unmanaged host copies and reports local drift through doctor; it does
not overwrite those copies automatically. The version, migration, compatibility, and rollback
contract is documented in
docs/PHASE1_MIGRATION_ROLLBACK.md. The older
docs/VERSIONING_AND_3.0.md is retained as historical
3.0/3.1 release evidence.
install.py stages atomically, never touches an agent file you already have, and uninstalls
cleanly (python install.py --uninstall). Migrating from the old name? --with-alias adds a
thin /sub-agents alias.
T3 Code: T3 discovers Claude, Codex, and Cursor skills. It has no Summon host entry of its own, so target those roots in one step:
python install.py --profile t3
python summon.py --doctor # look for the "t3 code" section
Full smoke checklist: the T3 Code setup guide.
Let your AI agent set it up (it adapts to your machine)
Paste this into your favorite AI CLI (Claude Code, Codex, Cursor, Gemini, …) in a scratch folder:
Set up "summon" for me (github.com/Nafjan/summon), a cross-vendor AI sub-agent dispatcher.
1. Clone https://github.com/Nafjan/summon and cd into it.
2. Run `python summon.py doctor` and tell me which backends are installed (claude, codex,
cursor-agent, gemini, kimi, agy, arkcli) and which are missing. That check reads versions only -- if I
approve a small live call per backend, run `doctor --probe` to verify sign-in and
account eligibility too.
3. Run `python install.py` to install the summon skill into every AI CLI on this machine
(it auto-detects ~/.claude, ~/.codex, ~/.cursor, ~/.gemini, ~/.copilot and never
overwrites my own agents). Add `--with-alias` only if I ask for the legacy /sub-agents name.
4. Run `python summon.py doctor` again and confirm what's now ready.
5. Read README.md and SKILL.md, then summarize: what I can do now, and ONE example command
using a backend I actually have. If a backend I want is missing, tell me exactly how to
install and log into its CLI.
6. Offer to add the "Delegating to summon" snippet from README.md to my host config
(CLAUDE.md / AGENTS.md / GEMINI.md / .cursor/rules) so you reach for summon on purpose:
cross-vendor review before merge, --council for decisions, --manifest for fan-out. Only
add it if I say yes.
You can also skip the skill install entirely and run the script directly:
python summon.py dispatch --agent reviewer --prompt "…" --cwd "$PWD".
For a second local Claude login, define it in the private
~/.agents/summon-profiles.json registry and select it with
--profile <name> (or profile: <name> in a local agent definition). Summon records the
profile name and integrity digests, not the config path. See
private backend profiles.
For governance-controlled dispatches, add --strict-agents-dir alongside
--agents-dir. A missing role then fails closed instead of falling through to the
bundled or plugin roster; ordinary dispatches keep the convenience fallback.
For operator-owned names that must survive roster changes, use the experimental private
role registry: summon role propose ALIAS TARGET, then summon role approve ALIAS.
Dispatch an approved alias only with --enable-roles; exact agent names still win, and
target/approval hash changes fail closed. The registry lives outside the repository at
~/.claude/summon/roles.json and receipts carry only names and digests.
Staying current: the installed skill is a copy and never self-updates. Re-install or
update via your Agent Plugin client's UI (for plugin installs), run npx skills update
(for skills add installs), or re-run python install.py after a git pull (for
installer installs). Every dispatch envelope carries
summon.scripts_sha256, so a stale or divergent copy is detectable from any single
result; the version string alone is not enough.
Your first run
# from any project directory (use an absolute --cwd)
python summon.py dispatch --agent reviewer \
--prompt "Review the diff on this branch for correctness bugs" --cwd "$PWD"
Or, once the skill is installed, just tell your AI CLI:
"Summon the adversarial reviewer on my last commit and give me the findings."
Command surface
Git-style subcommands. The old flat --flag form still works too:
| Command | Does |
|---|---|
summon dispatch --agent N --prompt … --cwd D | run one agent (the default action) |
summon list | list available agents |
summon agents validate [--cwd D] [--agents-dir D] | validate provider-inert custom-agent manifests and print redacted identity/digest evidence |
summon models [--cli B] [--refresh] | invocable models per backend, with a source per entry; refresh live provider rosters explicitly |
| `summon auth status | repair BACKEND` |
summon doctor [--json] | backend / setup health check (run this first) |
summon manifest FILE | run a batch fan-out (per-backend concurrency, resumable) |
| `summon swarm create | status |
summon council --question "…" | explore and synthesize diverse positions |
| `summon chat open | post |
summon chat turn SESSION AGENT --message "…" | explicit bounded roster-agent turn; CLI waits for durable finish, browser turns are cancellable and can run in parallel across participants |
summon chat cancel SESSION AGENT | append a durable cancel command and stop that participant's active turn when reachable; it never changes a ballot |
summon chat message SESSION FROM TO --message "…" · chat inbox SESSION AGENT | durable addressed context between admitted participants (or the human); inbox reads are local-native and never control authority |
summon chat recover SESSION AGENT --chat-confirm | human-attested close for an unmatched turn; records indeterminate spend and never retries |
summon chat fork SESSION AGENT --message "…" | create a new context lineage without provider contact |
summon deliberate --question "…" --seats A,B --options X,Y | fixed-option, quorum-controlled, replayable decision |
summon deliberate status|replay|recover|cancel RUN_ID | inspect, repair, or queue a typed command without provider work |
summon deliberate open RUN_ID | open/reuse the local browser ledger (provider-inert) |
summon agent new|set NAME --set k=v | scaffold / retune an agent definition |
summon role propose|approve|list|resolve … | manage private, opt-in role aliases |
summon jobs list|status [ID] · jobs wait ID | inspect or wait for background jobs (--json on list/status). status is a redacted, typed projection; wait returns the complete private terminal envelope |
summon jobs extend ID --duration 30m · jobs cancel ID | extend an active adaptive job's soft and hard deadlines (bounded to seven days from job start), or request process-tree cancellation |
summon jobs steer ID --message "…" · jobs resume ID --message "…" | queue authenticated guidance for a later eligible continuation, then explicitly create one governed successor; this is not claimed as live mid-turn injection |
summon telemetry enable|disable|status|clear | manage local opt-in diagnostics; clear does not disable |
summon usage status|import|refresh|export|example … | inspect, refresh, or exchange bounded usage evidence. Live refresh requires an explicit provider allowlist and account-read consent; usage remains advisory and cannot reroute an exact request |
summon result project --kind dispatch|job --from PRIVATE.json --repo-root DIR | derive an experimental redacted compatibility receipt without contacting a provider; only authenticated terminal job records are accepted for job |
summon result validate PORTABLE.json · result consume PORTABLE.json --adapter reference | strictly validate or authority-freely consume a portable receipt; chat, council, deliberate, and swarm projection currently refuse rather than inventing common semantics |
summon fleet propose LANE --seats A,B | create a sealed provider-inert fleet draft; this does not approve, select, dispatch, or authorize spend |
summon fleet validate|inspect FILE | validate against the current roster, or inspect every declared constraint without consulting a roster |
summon fleet explain FILE LANE | compare roster candidates with the sealed constraints; report unknowns but deliberately select no route |
summon fleet approval status|list | inspect the private approval store through a redacted, provider-inert projection |
summon fleet approval approve FILE LANE --expires-in 24h --expect-generation N | record authenticated, expiring local authority for the exact compiled lane; this still cannot select or dispatch |
summon fleet approval inspect APPROVAL_ID | inspect one recorded approval without mutation |
summon fleet approval revoke APPROVAL_ID --expect-generation N [--out FILE] | explicitly revoke recorded authority with a generation-bound mutation |
summon dispatch --lane LANE --fleet-file FILE --fleet-approval-id ID --fleet-data-proof PROOF … | consume one exact approval for one foreground, single-seat, single-attempt launch; no retry, fallback, repair, resume, background, worktree, or authority expansion |
summon bug-report … | generate a sanitized report; review it before the separate GitHub submission command |
summon version · summon help | version · usage |
manifest remains Summon's batch-fan-out surface. The local swarm coordinator
now provides durable owner/lease/claim/cancellation state and explicit
uncertain-spend recovery. It is not yet an automatic attachment to a
host-native IDE swarm; external adapters must authenticate a worker connection
and pass the protocol conformance/process-tree gates before they can launch
providers. The boundary is documented in
the swarm protocol.
summon (no args) prints the command list. Everything below is documented in
the Summon skill instructions.
For a copy-paste path through fleet approval, usage evidence, context compilation, adaptive jobs, and portable results, use the Phase 1 operator workflow. Upgrade and rollback state is covered by the Phase 1 migration contract.
Portable result receipts are compatibility views, not replacements for private execution
envelopes and not dispatch capabilities. They omit prompts, response text, transcripts,
sessions, local paths, account facts, and raw diagnostics. A reported exact model identity
is verified only when requested, targeted, and served values agree; inferred or absent
evidence stays unverified. The schema remains experimental while consumers validate the
supported dispatch and authenticated-job surfaces. The shipped
examples/phase1/consume_portable_result.py golden imports no Summon modules; it
demonstrates interoperability but is not a claim of independent adoption.
Fleet documents are drafts, not dispatch capabilities by themselves. propose returns a compiled
projection bound to the current project directory object and a sanitized roster-catalog
digest; --out persists only the sealed draft and refuses to replace an existing file.
Fleet catalogs admit only active seats. A deprecated seat remains available for an
explicit compatibility dispatch with a warning, while a retired seat fails before any
provider contact and can name a distinct successor.
validate recompiles that relationship against the current roster. inspect needs only
the sealed draft, so it remains useful when a roster has changed or is unavailable and
shows every candidate's priority. explain lists matching and losing constraints,
provenance, and unresolved evidence; it never chooses a winner. Here, provider means
the account or endpoint authority bound to the executed route: a named API registry key,
a singleton backend, or an explicit OpenCode declaration verified against its selector.
Inline endpoints and undeclared gateways remain unknown; a model prefix alone never
becomes provider proof. The approval surface records authenticated, expiring local
authority bound to the sealed fleet, compiled plan, project, catalog, lane, operation,
and authority ceilings. Mutations require the current store generation. Public receipts
omit private store and actor identities, authentication material, and paths, and say
recorded_not_activated: recording alone cannot select, reserve, retry, resume, dispatch,
or contact a provider. A separate dispatch --lane command may consume that exact
approval for one single-candidate foreground subprocess attempt after revalidating the
fleet, roster, project, prompt/data proof, authority ceiling, spend boundary, and launch.
It has no retry, fallback, repair, resume, background, or worktree path. Repeating an
active approval with the same scope and requested lifetime is
idempotent; changing the requested lifetime creates a distinct issuance under the current
generation. Because an exact replay does not mutate the store, it returns the existing
receipt—even near expiry—and does not extend its lifetime; this remains true when its
supplied expected generation is stale. Each approval projection reports both its issuance
generation and the current store_generation, so the latter can be used for the next
explicit compare-and-swap. Expired and revoked records remain visible until
the next approval mutation, which compacts them before writing new authority. The store
is bounded to 4 MiB and 4,096 active records and reserves byte and generation capacity to
revoke every active approval.
Summon checks an explicit approval-receipt --out target before recording authority.
An occupied or unsafe target records nothing. If a later publication race loses after
the authenticated write, the error reports recorded_receipt_undelivered; recover the
redacted receipt with fleet approval list or fleet approval inspect.
The default private store is
~/.agents/summon/fleet-approvals.json; its sibling .key file is separate. Summon
requires owner-only paths (POSIX 0700/0600, or a protected owner-only Windows ACL),
and path overrides must be absolute. Summon hardens a pre-existing directory only when it
is empty; filenames alone never prove that a nonempty directory is Summon-owned. Create
a dedicated owner-only directory instead. On a generation conflict, run fleet approval status
and deliberately retry with its current generation. If clock rollback is detected, correct
the system clock before retrying; no approval is consumed. The one-time launch contract is
implemented, separately reviewed, and remains intentionally narrower than ordinary dispatch.
How to use it effectively
- Pick the right agent, not just the right model. Agents bundle a model, a persona,
and a report contract.
reviewer(Codex) reviews;planner(Opus) plans;pair(Sonnet) does everyday work.summon listshows them;summon agent newmakes your own. - Chain with
handoff. Every result that satisfies the report contract carriesreport.handoff(an error, timeout or malformed reply may not, which is whatreport_oktells you). Paste it into the next dispatch instead of re-explaining; that's how multi-step work stays cheap. - Trust the envelope, not the prose. Branch on
status: a self-reportedBLOCKED, and a recognised approval request in the run's final output, are downgraded toblocked. Approval detection matches known markers rather than reading intent, so also treatsuspect: trueas unverified rather than assuming every stalled run is caught. Checkmodel.servedtogether withserved_model_evidence: a non-null identity can be inferred, andnullmeans no usable served identity was established. Exact-model proof requiresreportedevidence and matching requested, targeted, and served IDs. - Review across vendors. Send code written by one vendor to a reviewer on another.
docs/PROTOCOL.mdhas the rule and the named patterns (debate, async build, competing hypotheses, consensus). - Put big inputs in files. For long prompts, write a packet under
--cwdand pass a short "read X and follow it" prompt (avoids arg-length limits and sandboxed reads). - Fan out with
manifest; choose the decision surface deliberately. Independent tasks → a manifest swarm; cross-examination plus a chairman →council; fixed options, quorum, hard physical bounds, and replay →deliberate. Readskills/summon/references/deliberation.mdbefore choosing it.
Full playbook: the dispatcher protocol.
Teach your agent to reach for it (CLAUDE.md / AGENTS.md)
summon is invoked by your coding agent, so it only gets used well if the agent knows
when to reach for it. The skill's description triggers it, but a few lines in your host
config make the agent orchestrate on purpose. Drop this into your CLAUDE.md, AGENTS.md,
GEMINI.md, or .cursor/rules (whatever your CLI reads):
## Delegating to summon (cross-vendor sub-agents)
When a task is heavy, parallelizable, or would benefit from another vendor's eyes,
dispatch it with the **summon** skill instead of doing everything yourself:
- **Cross-vendor review before merge (house rule).** Never merge a substantive change
reviewed only by the model that wrote it; it shares that model's blind spots. Route
claude/cursor-written code to codex (`reviewer` / `adversarial-reviewer`); route
codex-written code to a claude reviewer (`quick-reviewer`).
- **Open-ended judgment → `--council`.** Convene a vendor-diverse council and let a
chairman synthesize. Disagreement that survives round 2 is worth taking seriously.
- **Fixed-option governed decisions → `--deliberate`.** Supply the question, named
seats, options, quorum, rounds, attempt budget, absolute deadline, and human-approval
policy explicitly. Never infer a missing policy field or silently fall back to council.
- **Independent work → `--manifest`.** Fan several jobs out with per-backend
concurrency; each writes its own result envelope you can inspect.
- **Use the curated model bands deliberately.** The catalog places
Astra, Fable, Sol, Opus, Kimi, DeepSeek V4 Pro GA, and Gemini Flash 3.8 in the
editorial frontier lane for
maximum-thinking coding work. It places Grok 4.6, Gemini Flash 3.7, GLM 5.2, and
DeepSeek V4 Flash in a near-frontier/value lane. These are editorial labels, not benchmark
results or availability guarantees. Flash 3.7 remains separately labeled for older
explicit requests and receipts.
The Ark entries use exact versioned IDs (`deepseek-v4-pro-ga-260813`,
`deepseek-v4-flash-ga-260731`, and `glm-5-2-260617`) from the 2026-08-18 marketplace
check. These are editorial routing labels; the model catalog and UI tooltips show the
role/name/version. Check `model.served` and its provenance; only `reported` evidence
can establish served identity, and exact pins also require `named_model_verified: true`.
- **Escalate the hardest problems** to a frontier-lane seat when the task justifies it.
Billing and quota depend on the provider account and route; Summon does not infer a plan's
allowance. Review the warning and envelope before you continue. Keep councils and swarms
diverse so that independent reviewers can expose different failure modes.
- **Use Gemini Flash 3.8 for fast vision, research, and review.** The bundled
`flash-reviewer`, `researcher`, `frontend`, `docs-writer`, and `antigravity` seats target
`gemini-3.8-flash-high` through agy. Flash reviewer is the recommended advisory
secondary voice for a cross-vendor council. AGY 1.1.22 reports the targeted model,
session, activity, and terminal usage, but not authoritative `model.served`; treat the
named-model vote as advisory. AGY cannot enforce read-only, so keep this seat in a
disposable research/review lane when a hard filesystem boundary matters.
The older `researcher` seat retains its exact-model contract: absent authoritative
served identity, it returns `blocked` with `result_usable:false`, even if useful
report text exists. Use `flash-reviewer` for ordinary advisory work, not to bypass
a workflow that requires certified identity.
Use separate persona passes for different review angles, not as a substitute for
cross-model consensus. Verify media delivery before claiming image/video inspection.
Direct coding remains useful in disposable copies, with checkpoints and tests under
the original dispatch directory to catch AGY working-directory drift. Cost and quota
are account-specific; no route assumes free or unlimited use.
- **Use Grok 4.6 as a near-frontier candidate, not a blind default.** Probe it
with `--cli cursor-agent --model grok-4.6`, require `reported` served evidence and
`named_model_verified: true`,
and keep Gemini pinned until a local smoke proves eligibility, evidence quality, and the
required permission/retention contract. Never silently fall back to another Cursor model.
Verify, don't trust: branch on the returned `status`; a `report_ok:false` or
`suspect:true` result needs review. Check typed errors, provider contact, spend, and
`retryable` before another attempt; suspicion alone does not authorize a retry or
fallback. Read `warnings` (model fallback, premium model cost, or an agy read-only
dispatch refused/advisory-only). Served identity requires `reported` evidence;
an inferred or absent identity cannot certify an exact named model.
Preview a paid fan-out with `--dry-run`, pass `--json-schema` when you need structured
output, chain via `report.handoff` into the next call, and pass `--out` on any
council you cannot afford to lose (the envelope is checkpointed each phase).
Tune it to your workflow. The point is that your agent reaches for summon on purpose (dispatch, review across vendors, open-ended council, or fixed-option deliberate) instead of forgetting it exists. The agent-led installer above can add a snippet like this for you.
Orchestration practices that hold up
A few habits that keep multi-agent work fast, cheap, and trustworthy:
- Verify across vendors, not within. A model reviewing its own output shares its blind spots. This is the habit that pays off most, and summon puts the other vendor one command away.
- Adversarial-verify findings before you act on them. Have a second (ideally different) model try to refute a claim; a finding that survives is worth trusting. Don't merge on one pass.
- Decide by council, converge by chairman. For a judgment call, N diverse positions
plus anonymized peer ranking plus a synthesis beats one model iterated.
--councildoes exactly that. - Keep the orchestrator's context clean. Delegate the heavy reading and searching to
sub-agents and keep only their
report.handoff. That's how long chains stay affordable. - Prefer structured output for anything you branch on.
--json-schema+parse_okremoves brittle "find the JSON" heuristics from your side entirely. - Isolate parallel edits.
--worktreegives each concurrent agent its own branch, reducing ordinary checkout collisions; you still review, diff, and merge the winner.
Pairs well with your other skills
summon coordinates dispatch and governed decision workflows. It doesn't try to reimplement the thinking-discipline that dedicated skills already do well; it composes with whatever your CLI has installed. Some categories that pair well (use what your ecosystem offers):
- Adversarial code review: a skill that forces real perspective shifts pairs well with cross-vendor dispatch. summon sends the diff to a different vendor; the review skill makes that vendor actually critical.
- Coding discipline: Karpathy-style guidelines (surface assumptions, keep it simple, surgical changes) applied by each sub-agent keep a swarm from over-building.
- Deep-research harnesses: fan-out, fetch, and verify for the findings, with summon running the cross-vendor verification pass.
- Planning / spec-driven workflows: a plan or spec skill decomposes the work; summon
fans the pieces out (
--manifest) and reviews them across vendors before merge. - Project memory / knowledge graph: a durable-memory skill writes
.agents/memory.md, which summon auto-injects into every sub-agent so they never re-learn your conventions.
Rule of thumb: let specialist skills think, and let summon route that thinking across vendors.
What a dispatch returns
{
"status": "blocked",
"execution_status": "not_run",
"attempts": 0,
"attempt_status": "not_run",
"provider_contacted": false,
"result": "",
"report": null,
"environment_handoff": { "declared": false, "left_behind": null },
"report_ok": null,
"model": { "requested": "<requested-model-or-null>",
"targeted": "<targeted-model-or-null>",
"served": null, "resolved": null },
"served_model_evidence": "absent",
"model_match": null,
"named_model_verified": false,
"raw_backend_exit_code": null,
"normalized_exit_code": null,
"exit_code": null,
"summon": { "version": "3.5.0", "scripts_sha256": "<sha256>" },
"permission": "safe-edit", "permission_flags": ["--permission-mode", "acceptEdits"],
"usage": { "input_tokens": 12038, "output_tokens": 981 }, "cost_usd": 0.084,
"billing": { "source": "subscription", "note": "Claude login" },
"elapsed_ms": 0,
"resume": { "cli": "claude", "session_id": null }
}
The object above is a safe structural-refusal example, not a success template.
Successful dispatches must populate these fields from the actual terminal envelope;
callers must never copy report_ok, model proof, attempt counts, or exit codes from
an example. In particular, attempts:1 and model_match:true are valid only for
an actually executed, provider-reported exact-model success; they are never valid
values for a structural not_run refusal.
report.handoff→ the context to pass to the next call.environment_handoff→ resources the child created and intentionally left behind. It can cover temporary paths, processes, servers, VMs, or container resources; the caller, not summon, decides whether to retain or clean them.declared: falsemeans no account was made.report_ok: falseon a "success" → also getssuspect: true. Agents that skip their contract don't get believed.model.served→ the served-model identity or a bounded inference, distinguished byserved_model_evidence.nullmeans no usable served identity was established, even if other activity or usage was observed.targetedis the session's target.model_match/named_model_verified→ exact-model proof, not a guess. The tri-statemodel_matchistrueonly for a trusted backend/provider completion record showing equality of requested, targeted, and served IDs; it isfalsefor a reported mismatch andnullfor inferred/absent evidence.named_model_verifiedistrueonly whenmodel_matchis true.- For an exact named-model pin,
status: "blocked"witherror_kindsuch asmodel_selection_conflict,target_model_mismatch,served_model_mismatch, orserved_model_unverifiedis a terminal trust result. It is not automatically retried or rerouted, andresult_usableis false. The envelope'smodel.exact_requiredandmodel.exact_sourceexplain why the gate applied. served_model_evidence→reportedfor trusted backend/provider completion evidence,inferredfor a non-authoritative model observation or bounded telemetry inference, orabsentwhen no usable served identity was established. Missing provenance does not make a usable success retryable; an empty terminal result is instead a typed non-retryable error.model.evidence_source→ the bounded source of a served-model observation; the source label alone does not make it authoritative. Kimi 0.38 observations can come from assistant stdout or positive-outputusage.recordentries with a completed-turn marker in Summon's fresh isolated per-call profile. Both channels are writable by the child, so their identity isinferred, never authoritative named-model proof. Request and configuration records do not establish served identity; missing usable observations leavemodel.servednull and provenanceabsent.tool_failure→ a safe, typed missing-executable diagnostic. On Windows, userg, PowerShell, or Python when a child cannot run a POSIX convenience command such asgrep; a complete report is preserved and the raw backend exit remains visible.raw_backend_exit_codeandnormalized_exit_code→ explicit child and Summon outcome codes. The legacyexit_coderemains for compatibility but is ambiguous after report normalization, so automation should use the explicit fields.timeout→ the timeout budget, whether partial output survived, and the raw stage or reason the execution path established. ACP can name a protocol stage; generic CLI timeouts can usebackend-executionor a specific adaptive/liveness reason such asadaptive_attention_timeout,adaptive_hard_timeout,generation_idle_timeout, orfinalization_timeout. The separatelivenesssnapshot records observed progress. Opt-in telemetry normalizes these into a finitetimeout_stagevocabulary: adaptive and finalization reasons map tobackend_execution, and generation-idle reasons tostream. That projection does not replace the raw receipt or identify a vendor's internal reasoning/tool phase.- Situational fields appear only when they apply:
exit_history+original_exit(a corrective resume superseded an earlier attempt; every superseded attempt is kept in order),result_from_repair(the first attempt produced no text, so the repaired text is the answer),result_path_conflict(the envelope found at a shared--results-dirpath answers a different request and was refused rather than served), andgate,gate_correction_refusedorgate_repair_refusedunder--gate-with. A gate's own retained-resource declaration is nested atgate.environment_handoff. summon.scripts_sha256+agent_def.sha256→ provenance: which dispatcher build and which agent definition produced this envelope.billing.source→ did this draw from a subscription or metered api credits.resume.session_id→ a candidate session handle, not continuation authority. Use--resumeonly when the route is eligible and its identity, profile, permissions, and history remain compatible. Governed job continuation also requires authenticated source evidence and fresh spend consent. Otherwise preserve the handoff and history in an explicit fork where supported, or an explicitly authorized fresh task.
Costs are estimates.
cost_usd/usageare the CLI's own list-price figures, not a bill. On a subscription they don't equal money spent, andbilling.sourceis a best-effort guess. Know your plan's inclusions and limits, and check your provider's latest billing and model notices directly.
Council mode: decide by consensus
summon council --question "Adopt a monorepo or keep polyrepos?" \
--members planner,reviewer,researcher,pair --chairman fable --rounds 2 --cwd "$PWD"
A vendor-diverse council answers independently. With --rounds 2 they see all positions
anonymized, refine, and rank them; votes aggregate (Borda) into consensus_ranking, and
the chairman returns a decision, a confidence, the agreements, the named dissents, and a
next action. It's the llm-council pattern, run over real cross-vendor CLIs instead of one
API's models.
OpenCode gateway and custom models
When a compatible provider needs a real tool/file loop, route it through OpenCode instead of using the direct text seat:
---
run-agent: opencode
provider: openrouter
model: openrouter/z-ai/glm-5.3-flash
permission: yolo
---
Authenticate OpenCode and verify the live roster with opencode auth login and
opencode models. The OpenCode path still respects the provider's context,
output, quota, and model limits; put large inputs in the workspace and ask the
agent to read them. The old Ox seat is retired and remains pinned to its historical
identity; the distinct successor targets paid z-ai/glm-5.3-flash. Pricing, discounts,
availability, naming, and routing can change without a Summon release; refresh the live
OpenCode roster and provider usage evidence before selecting it. Summon
requires --worktree or --isolated-lane before it can run: use a
disposable clone/worktree, inspect workspace_evidence, the diff, and tests,
then keep or discard the result. If Summon must bridge a private provider key
into a yolo OpenCode child, add --isolated-lane and
--allow-tool-credentials only after choosing a separate clone/Git directory,
OS account, container, or VM; a worktree alone does not protect credentials. Use
safe-edit or an enforcing backend when the
checkout is shared or sensitive. See the OpenCode backend reference.
For a disposable worktree that is itself inside a separately isolated OS boundary, make both boundaries explicit:
summon dispatch --agent openrouter-glm-5-3-flash-opencode --worktree glm-review `
--isolated-lane --allow-tool-credentials --cwd <project> `
--prompt "Inspect and test the change."
Use --isolated-lane instead of --worktree when the checkout is already a
separate disposable copy. The credential flag is intentionally not a default;
use it only with a separate OS boundary when arbitrary shell tools must not be
able to reach the normal account or credential store.
Headless Summon dispatches disable OpenCode project configuration, external plugins, external skills, and Claude-compatible project discovery for the child. This prevents repository-controlled startup code from retargeting the provider or seeing a credential bridged for that one turn.
OpenRouter's routers are available through the same gateway. Use the exact
selectors shown by opencode models openrouter:
---
run-agent: opencode
model: openrouter/openrouter/auto # task-aware paid routing
permission: safe-edit
---
The free router is openrouter/openrouter/free; pin a concrete :free model
when you need reproducible behavior. Fusion is
openrouter/openrouter/fusion and accepts a bounded preset setting:
---
run-agent: opencode
model: openrouter/openrouter/fusion
permission: safe-edit
openrouter_options: '{"plugins":[{"id":"fusion","preset":"general-budget"}]}'
---
Fusion presets are general-high, general-budget, and general-fast. They
run a panel and judge, so expect higher cost and latency than a single model.
Always inspect model.served and provider evidence: aliases and live roster
entries do not identify the model that answered.
The direct openai-compat path remains useful for a stateless text seat:
---
run-agent: openai-compat
provider: openrouter # or openai / anthropic / google / groq / ollama / lmstudio
model: anthropic/claude-3.5-sonnet
---
Built-in providers, plus your own in providers.json (or inline base_url + api_key_env,
empty key for local servers). Same envelope, same manifest/council. This is how you add
local models and multi-model API access, and how a council becomes a genuine multi-vendor
board. Summon classifies non-Coding-Plan direct API routes as API billing by default; actual
credits, subscriptions, invoices, and no-cost local operation depend on the endpoint and
account and are not universally observable (see the provider terms).
The starter roster
Frontier planning and review on OpenAI (astra), planning/architecture on Claude
(planner, architect, deep-debugger, security-auditor, fable), implementation + adversarial review on Codex (implementer,
reviewer, adversarial-reviewer, debugger, test-author), coding on Cursor (coder,
bug-fixer), advisory research/review on Gemini Flash 3.8 through agy (flash-reviewer), docs/frontend on
Antigravity (docs-writer, frontend), and balanced lanes on Sonnet 5 (pair, editor,
quick-reviewer, pr-prep).
Each is a plain .md file: edit, delete, or add your own with summon agent new.
install.py never overwrites an agent you already have.
Design boundaries
Summon is a local dispatcher and durable coordination layer, not a hosted dashboard. It provides structured envelopes, cross-vendor dispatch, council and deliberation contracts, bounded fan-out, and authenticated local browser surfaces. It does not replace a provider's native streaming UI, account controls, or session manager. Provider capabilities vary; for example, Gemini CLI sessions cannot currently be resumed through Summon's headless route.
System requirements
- Python 3.10+ (3.11+ recommended). Standard library only, so no
pip installfor the dispatcher itself. The default agy path (a stream-json proxy) is standard library too. Only the legacy opt-in agy PTY wrapper needspywinptyandpyte(tested withpywinpty 3.0.3andpyte 0.8.2). Contributors running the complete release and Phase 0/1 verification registry also needpytest>=8,<9; this is a test-only dependency and is not installed with Summon. - At least one backend: a vendor CLI installed and logged in (
claude,codex,cursor-agent,gemini,kimi,agy, oropencode), an API key for anopenai-compatprovider, or a local Ollama/LM Studio server.summon doctortells you which are installed;doctor --probespends a small live call per backend to confirm sign-in and eligibility. - AGY 1.1.22 or newer for AGY seats: Summon preflights the provider-inert
--print-timeoutcapability before copying credentials or launching a turn, then binds that timeout to the remaining adaptive hard budget. Older AGY builds fail with an upgrade instruction instead of an unknown-flag backend error. gitif you use--worktree.- A host that can run a shell command: a coding CLI, an AI IDE, a desktop agent app, or
a plain terminal. Anything that can invoke
pythonand read the skill can drive it. - OS: Windows runs every backend. Linux and macOS run all of them except agy out of the box. CI covers Ubuntu and Windows.
- Headless Windows behavior: Summon launches its dispatcher, utility, detached, and
nested backend processes with hidden startup state plus
CREATE_NO_WINDOW; routine dispatches do not open terminal windows. A vendor CLI or custom wrapper that explicitly creates its own GUI remains outside Summon's process-launch boundary. - If a popup persists: the calling agent should invoke Summon directly, leave
AGY_PTY_WRAPPERunset so the bundledagy_stream_proxy.pyis used, and avoid wrapping the call inStart-Processorcmd /c start. If a PowerShell helper must useStart-Process, pass-WindowStyle Hidden; the legacy winpty wrapper (agy_pty_pyte.py) is disabled on Windows unlessAGY_ALLOW_LEGACY_PTY=1is set deliberately. A custom wrapper must hide its own children and be reported in the handoff.
You bring model access. Summon orchestrates the CLIs and APIs you already use.
Security, permissions, and terms
- Permissions map to real CLI behavior. Each agent's
permission:(read-only/safe-edit/yolo) maps to that CLI's flags, and the envelope records the exact mapping. Useyolofor Kimi, OpenCode/Ox, agy/Antigravity, and similar toolful agents when the work is inside a disposable clone or isolated worktree and you will inspect the diff, tests, and mutation evidence before integrating. This is how code, UI, research, and review lanes get the capability they need without making the active checkout the blast radius. - Kimi Code uses full-authority prompt mode. Its non-interactive runner auto-handles
tools and rejects
read-onlyandsafe-edit; Summon refuses those labels rather than misrepresenting the boundary.kimi-workerandkimi-coderpin K3 at maximum thinking, whilekimi-k27-coderis the explicit lower-context K2.7 seat. Use them in isolated worktrees, monitor their mutations, and keep or discard the result after verification. For a review-only Kimi job, use--worktree, instruct it not to change product files, and inspect the worktree before accepting the report or removing it: the review request is not an enforceable read-only boundary. Kimi may expose a served-model observation in child stdout or its isolated runtime journal, but both channels are writable by the child and are therefore labeledinferred, never authoritative named-model proof. Its local profile and requested K3 target are not provider evidence. A successful report with absent or inferred identity is useful advisory output, not a certified named-model review. - agy/Antigravity has no enforceable
read-onlytier. Itssafe-editis the same full bypass asyolo, and declaredread-onlyis refused unless explicitly waived. For a disposable worktree, useyolodeliberately; for a shared or sensitive checkout, use an enforcing backend instead.SUMMON_ALLOW_UNENFORCED_READONLY=1marks a caller-declared read-only run advisory; it never overrides a clamp or governance-imposed restriction. - A worktree is mutation isolation, not a security sandbox. A Git worktree can share repository metadata, the operator account, environment variables, and other resources visible to the child. If credentials, private/client data, shared Git state, or a live resource must be protected, use a sanitized packet in a separate clone with its own Git directory, OS account, container, or VM, or choose a backend with an enforceable boundary.
- Treat the whole
--cwdas trusted. Files under it,.agents/memory.md(auto-injected into agent context), and manifestprompt_files are trusted operator input. Every bundled agent also carries an "untrusted content: data, not instructions" guard as defense-in-depth. Don't run summon in a repository you don't trust. - Secrets. The agy backend copies OAuth tokens into a per-invocation profile locked to
your user (icacls /
0700) and isolated from your real profile.openai-compatreads API keys from env (or the documented local OpenRouter credential fallback) and redacts them from any error output. OpenCode uses its own auth/configuration. In restricted tiers, Summon keeps the optional OpenRouter bridge child-scoped; in yolo mode it scrubs inherited provider credentials and refuses a private-key bridge unless the caller explicitly supplies--isolated-laneplus--allow-tool-credentials;--worktreemay additionally provide mutation isolation but never replaces the OS-boundary acknowledgement. The key is never recorded in an envelope, telemetry, prompt, or public agent definition. - Terms of service. Summon drives each vendor's official CLI (built for scripted use) on your accounts, which is the intended path for personal and dev work. Don't share accounts, build a product on subscription auth, or hammer parallel volume; use API-key backends for commercial or high-volume work. Providers can change programmatic-billing rules. Read the full guidance in the provider terms.
- Prompt size depends on the backend transport and OS. On CLI routes that pass the
prompt through
argv, Windows caps the whole assembled command line at 32767 characters and reports the overflow as a missing file, which summon used to relay as a bogusCLI not found; POSIX caps a single argument at 128 KiB and the total (including your environment) atARG_MAX. Summon now measures the real, serialized line before spawning and refuses with an error that names argv as the cause.--prompt-fileprotects prompt input at Summon's launcher; it is not a universal argv-free backend transport. When a backend still receives the content on its command line, those limits apply. For material that large, write it to a file under--cwdand ask the agent to read it. - Windows batch transport is fail-closed.
summon.cmdmarks the batch path and refuses every raw--promptbefore any roster/backend work. Batch expansion occurs before Python receives argv, so surviving bytes cannot prove that even apparently simple text was not rewritten. Put the prompt in a UTF-8 file and pass--prompt-file; the refusal envelope reportsattempts: 0,attempt_status: not_run, andprovider_contacted: false. - Diagnostics are opt-in and local. Summon does not collect telemetry by default. When
enabled, it records bounded, allow-listed metadata locally and omits prompt text, result
text, raw output, credentials, and absolute paths. It may retain deterministic fingerprints
for local correlation; see local diagnostics and telemetry for storage,
clearing, and report-submission details. The setting and spool belong to the operator
profile, not to each installed skill copy: updating or reinstalling a host copy does not
enable telemetry, disable it, or transmit anything. Use
summon telemetry statusto inspect the effective local setting.
FAQ
What happens when a vendor ships a new model? Nothing breaks. Model strings pass
through verbatim; aliases like opus and sonnet float, summon models shows what's
available, and the envelope pairs model.served with served_model_evidence
(resolved is the legacy field). Inferred or absent evidence cannot certify a named
model; exact proof requires named_model_verified: true. Aliases can lag a launch,
so use the explicit ID when you need a particular model.
Does it need API keys? For the eight CLI backends, no. It drives the logins you already
have, and it strips OPENAI_API_KEY from codex children so you're not silently billed at
API rates. The openai-compat backend uses your API key by design; OpenCode uses the
provider credentials configured for OpenCode (with the optional private OpenRouter bridge).
Is it safe to let an agent install it for me? The agent-led prompt clones the repo, runs
doctor (read-only), and runs install.py, which preserves files outside the owned payload.
Review install.py before you run it if you need to understand the ownership boundary.
Why not MCP? Summon's core path is a local subprocess or HTTP dispatch, so it does not need a server or a session layer. An optional MCP facade may be added later without changing the envelope.
Contributing
Contributions are welcome. New backends, agents, and providers are the easy wins.
A new backend is one entry in a registry
(the backend contribution guide);
a new agent is a .md file. See the contribution guide for development setup, ground rules (stdlib only,
every change tested, secrets redacted), and the PR checklist. Run
python skills/summon/scripts/test_discovery.py and python tests/test_install.py before a PR.
Roadmap
The release-facing product plan, readiness matrix, test gates, and live-provider roadmap are maintained in the product roadmap.
The roadmap records validated requests and their current status. It is ordered by priority and is not a delivery commitment.
Shipped since this roadmap was written: council quorum + --chairman-fallback +
per-stage timeouts; the background job registry read path (jobs list / status / wait
with nonce-verified results); install-drift detection in doctor and install.py;
--gate-with approval gating across every execution path; and the argv preflight that
turned an OS command-line overflow from a bogus CLI not found into an accurate error.
The bundled roster now also includes explicit target seats for Sol, Terra, and Luna reviews;
the dispatch receipt must carry reported evidence and named_model_verified: true
before an exact served-model claim is accepted. --list --json shows each
seat's declared model and effort. Luna is deliberately separate from Sol and Terra, so a
cost-efficient Luna turn cannot be mistaken for a Sol review.
Next (scoped):
- Honest fan-out rollups: a durable attempt journal (already present for councils)
extended to manifests, so
usage/cost_usdtotals count every round, retry, and correction instead of undercounting after a crash. - Destructive job registry:
jobs cancel/jobs reap+ heartbeats + orphan envelopes, gated on real OS process identity (start-time via ctypes //proc) so a reused PID is never killed by mistake.
Later:
- Error taxonomy +
doctor --live: distinct statuses (transport_unreachable,sandbox_network_denied,authentication_failed,quota_exhausted, …) that fail fast instead of retrying, plus a live doctor that probes reachability/auth and warns when a sibling install has drifted (using the envelope'ssummon.scripts_sha256). - Layered roster resolution: merge
--agents-dir/SUB_AGENTS_DIR> project.agents> user~/.agents> bundled, with asourceper agent, plus neutral model-tier seats for additional providers and model families to layer task personas on. - Spend governance:
--max-cost-usd/--max-tokensaccumulated caps with stop-before-chair behavior. (Pre-dispatch cost estimates are declined: summon has no pricing table and won't guess a bill.) --verify-no-mutations: hash git status/diff before and after a read-only agent and fail the envelope if it changed anything, backstopping theyolo+ "do not modify" pattern.- Capability-aware rosters: declare
repo-read/vision/web/enforces-read-onlycapabilities so a council can reject an unsuitable member before spending time. The original motivation (agy cannot read--cwd) is obsolete -- agy is repo-capable atsafe-edit-- but a sharper one replaced it: agy cannot enforceread-only, so a governed review roster needs to express "this role requires a tier the backend will actually honour" rather than trusting the label. - Session forking:
--fork-session/--resume-if-compatibleso resuming a failed Fable session can fall back to Opus instead of re-pinning the unavailable model. - Multi-root input bundles and a
--specrequest file for work spanning several repos and for reproducible, Windows-friendly invocations. - POSIX PTY wrapper for the agy backend; Gemini resume once its CLI exposes a
stable session id; an optional MCP facade (the envelope won't change); envelope
v2 to retire the legacy
model.resolvedin favor oftargeted/served.
Known limitation: the durable-run owner lock has a sub-millisecond stale-break/release
window that pure-stdlib cross-platform file operations cannot fully close. For COUNCIL runs,
generation namespacing bounds the worst case to a single duplicate stage dispatch (wasted
spend, not corrupted output), and it requires a process suspended past its lease resuming
inside that exact window; single-machine use does not hit it.
This does not extend to manifests. Two manifest runs sharing one --results-dir are not
serialized by anything: measured with two real processes, one parent read and reported the
other’s answer. summon now refuses an envelope whose request_sha256 does not match the job
being run (result_path_conflict), but that is a safety net, not a lock -- give each
concurrent run its own --results-dir. Closing it fully would need OS advisory
locks (with their own NFS / suspended-process gaps).
Open the public deliberation observer in a browser
After a durable deliberation run exists, use:
summon deliberate open RUN_ID
This is public, local, provider-inert preview functionality. Summon keeps one authenticated loopback surface per run and reuses its URL on later
invocations. --browser auto prefers an IDE bridge configured through
SUMMON_BROWSER_BRIDGE (also accepts CODEX_BROWSER_BRIDGE, VSCODE_BROWSER_BRIDGE,
CURSOR_BROWSER_BRIDGE, or ANTIGRAVITY_BROWSER_BRIDGE) and otherwise asks the system
browser to reuse an existing window. On Codex/IDE hosts advertising the optional iab
backend, auto uses browser-harness to reuse a matching tab or open one. Use
--browser builtin to require that path, --browser link for SSH/CI, --browser ide
to require the executable bridge, or --browser system to skip both. The bridge is
passed one URL argument with shell=False; it cannot execute a shell command. This is
an observer and typed-cancel handoff only. It does not enable live provider execution.
Credits
Summon was informed by agent-bridge, CCB, claude-codex-collab, cc-fleet, MCO, swarms, Omnigent, and Karpathy's llm-council. The project keeps the useful patterns from those tools while preserving a small, inspectable dispatcher.
License
MIT. See the provider terms for provider terms and limitations.