The agent roster¶
The pipeline tools in the API reference are
deterministic Python — they don't decide anything. Decisions (which tool to
call, when a step is done, whether a result passes review) are made by a
roster of prose-prompt opencode agents in
.opencode/agents/ — the agent's name is its filename, there is no
separate registry. Only @cosmotron is user-facing; every other agent is a
subagent dispatched by it.
| Agent | Role |
|---|---|
cosmotron |
Primary orchestrator — the entry point |
session_bootstrapper |
Creates the session via bootstrap_session |
literature_scout |
Light ADS/arXiv context lookup |
planner |
Drafts the analysis plan — the human is the plan gate |
data_ingestor |
Standardises each catalogue via ingest_to_session |
analysis_coder |
Runs spectra/covariance/SACC/plot tools in sequence |
systematics_checker |
Systematics cross-correlation, deprojection, B-mode null tests |
inference |
Builds the Firecrown config, launches/polls CosmoSIS |
reviewer |
Judges the deterministic evidence block, emits PASS/FAIL |
plot_reviewer |
Advisory vision agent — reads result PNGs |
Static reference material the agents read (NaMaster API, the LSS pipeline
domain, plotting conventions, workspace layout, CosmoSIS samplers) lives in
.opencode/skills/ — see Skills.
How a run flows¶
@cosmotron is the hub — every arrow below is a delegation to/from it, never
subagent-to-subagent. The human plan gate and the systematics/review gates
are the two points where a run can stop and wait rather than proceed:
%%{init: {"sequence": {"useMaxWidth": false}}}%%
sequenceDiagram
actor User
participant C as cosmotron
participant SB as session_bootstrapper
participant PL as planner
participant DI as data_ingestor
participant AC as analysis_coder
participant INF as inference
participant SC as systematics_checker
participant RV as reviewer
User->>C: task (@cosmotron / /cosmotron)
C->>SB: bootstrap session
SB-->>C: session_context.json
C->>PL: draft plan
PL-->>C: plan.json
C->>User: plan for approval
User-->>C: human gate: approve
loop per catalogue
C->>DI: ingest_to_session
DI-->>C: manifest.json
end
C->>AC: compute spectra / covariance / SACC
AC-->>C: results/ + SACC
opt inference requested
C->>INF: build_cosmosis_inference / run_inference
INF-->>C: posterior job
end
C->>SC: systematics gate
SC-->>C: PASS / FAIL / MISSING
C->>RV: build_review_evidence
RV-->>C: REVIEW: PASS / FAIL
alt REVIEW is FAIL (capped at 2 fix-then-re-review cycles)
RV-->>C: root cause
C->>AC: fix & recompute
C->>RV: re-review
end
C->>User: results gate + review verdict
Two things this simplifies: literature_scout isn't shown — it's dispatched
ad hoc for abstracts-only context lookups or citations, not a fixed pipeline
step. plot_reviewer isn't shown either — it's currently parked, not
dispatched by @cosmotron at all (see plot_reviewer).
A NEEDS_INPUT/ERROR signal from any subagent (see
Subagents have no interactive channel
below) routes back through cosmotron to the user at whichever step it
occurs, rather than following this happy path.
Platform conventions¶
These apply across the whole roster and are worth understanding before
editing any .opencode/agents/*.md prompt.
@cosmotron never calls pipeline tools¶
@cosmotron is the only mode: primary agent. It delegates everything via
@mention and calls no pipeline tools itself — enforced by an explicit
per-tool deny in its frontmatter, not a whole-server switch. opencode's
Agent.tools is a flat {tool: bool} map with no "disable this MCP server"
key, so every cosmotron_* tool must be listed false individually except a
fixed allow-list of coordination/read tools (read_memory, append_memory,
audit_memory, get_active_session, read_session_context_tool,
build_review_evidence, write_plan/read_plan/set_plan_step_status,
mark_plan_approved, check_job, list_jobs, cancel_job,
authorise_gate). tests/test_cosmotron_toolmap.py mechanically
enforces this: every @mcp.tool in server.py must have a corresponding
cosmotron_<name>: true|false line in cosmotron.md's frontmatter, and only
the allow-list above may be true. A new tool added to server.py without
a matching false line in cosmotron.md leaks to the orchestrator and fails
this test.
authorise_gate additionally carries permission: ask in cosmotron.md's
frontmatter — the only tool gated this way. Being true in the tool map
just makes it reachable; ask is what makes it unforgeable, by suspending the
call for a real runtime confirmation dialogue before it runs. See
Human gates.
Subagents have no interactive channel¶
opencode TUI bug #7654 means a nested subagent's free-form question never surfaces to the user. So subagents never end a turn with a question — instead they emit exactly one terminal signal:
@cosmotron routes NEEDS_INPUT to the user and caps retries at 2 attempts
per step. Any edit to a subagent prompt must preserve this protocol.
Model choice¶
The orchestrator needs a non-thinking instruct model — a per-agent
model: override pins this. Confirmed failures: thinking variants spiral and
never reach @planner; qwen3-coder-* variants autocomplete code well but
follow the non-interactive/tool-first/no-fabrication operating contract
poorly. Subagents use the global (thinking-capable) model. See
Configuration for the full local-model rationale
(small models only — this runs on a DGX Spark shared with the numerical
pipeline).
Tool-first¶
Agents call the MCP tools for any step one already covers — never raw
pymaster/healpy/sacc/pyccl for something a tool does. analysis_coder
in particular has run_analysis_script as its one sanctioned escape hatch
for a genuinely uncovered non-plotting step, and even that mechanically
rejects plotting code. See
Development.