Agent Fleet
CORE runs its own agents on its own model. Two numbers describe the fleet, and both are correct:
- Thirteen
agents/binaries undergrpc/agents/:compliance,curator,datagov,deployer,eval,fixer,judge,opsdoctor,recon,reviewer,risk,selfheal,triage. Each is a stdlib-only Go module (its owngo.mod, no SDKs), built from source per run. - Seventeen entries on the console roster (
GET /api/agents,operators/core/internal/console/agents.go). These are the thirteen, plus four with noagents/directory:resolver(a workflow aroundcore session),forger(core-forge-run.yml),users(core-agent-users.yml) andsession(thecore sessionCLI).TestRosterCoversTheShippedFleetfails if one is dropped.
Before you build a new agent, read these. Several have nearly been reimplemented by people who did not know they existed. Each is one main.go you can read in one sitting.
The roster
| Roster name | Delivery | Trigger (from the workflow) | What it produces |
|---|---|---|---|
reviewer | core-code-review.yml | pull_request opened/synchronize; a PR comment containing @core_review, @core_check, @code_review or @review; repository_dispatch: core-review from the org-wide sweep | a ✔️ ack comment and core-review label, then PR review comments; findings set review:findings-open |
fixer | core-agent-fixer.yml (and inline in the review) | runs inline on every finding; a @core_fix PR comment; workflow_dispatch -f pr= | a draft correction PR onto the reviewed branch. Never merges |
resolver | core-agent-resolver.yml | repository_dispatch: core-resolve; cron 17 */3 * * *; workflow_dispatch | a core session on the PR head, then a draft PR onto it |
triage | core-agent-triage.yml | issues: opened; workflow_dispatch | a triage comment plus labels |
self-heal (agents/selfheal) | core-agent-selfheal.yml | workflow_run: completed on eight named workflows; workflow_dispatch -f run_id= | one root-cause comment on the PR. Never pushes code |
risk | core-agent-risk.yml | cron 23 5 * * *; workflow_dispatch; repository_dispatch: core-playbook | the living “🛡️ Dependency risk report” issue from core scan --json |
compliance | core-agent-compliance.yml | cron 13 1 * * *; workflow_dispatch; repository_dispatch: core-playbook | the living “📋 Compliance status” issue, a control-evidence artifact, and a customer-safe block for release notes |
curator | core-curate.yml | cron 17 6 * * *; a core @curate / @curate comment; workflow_dispatch; repository_dispatch: core-playbook | release notes (docs/release-notes.md), doc fixes, audits and test scenarios as a curator/<sha>-<runid> PR |
deployer | core-agent-deployer.yml | an @core_deploy issue comment; workflow_dispatch -f issue= | the finished deliverable posted back on the issue |
datagov | core-agent-datagov.yml | cron 11 7 * * *; @core_datagov; workflow_dispatch; repository_dispatch: core-playbook | the living “🗃️ Data governance status” issue and POST /api/data-governance-findings. No model |
judge | core-agent-judge.yml | cron 29 8 * * *; @core_judgement; workflow_dispatch; repository_dispatch: core-playbook | the living “⚖️ Judgement status” issue and POST /api/judgements |
recon | core-agent-recon.yml | cron 37 9 * * *; @core_recon; workflow_dispatch; repository_dispatch: core-playbook | POST /api/rules-recon/report, and the “🧭 Rules reconciliation status” issue when GITHUB_TOKEN/GH_REPO are set |
opsdoctor | k8s CronJob | every 30 minutes (infrastructure/apps/github-runners/kustomize/opsdoctor/cronjob.yaml) | comments on one tracking issue; its one repair is deleting a wedged runner pod |
eval | CLI, plus core-inference-bench.yml | manual: score, replay, regress, model, bench | a trajectory + outcome report and a gate exit code; bench prints TTFT and decode tok/s |
users | core-agent-users.yml | an issue labelled add-users (the core @add_users form), opened by an org member | patches spec.users on a ClientInstance, or rebuilds the demo allowlist |
forger | core-forge-run.yml | cron 41 3,9,15,21 * * *; workflow_dispatch | a core session against the oldest open forge brief, as a draft PR. Disarmed by default |
session | CLI | core session start | see Coding Sessions |
The roster also carries a family (delivery or governance) and a delivery kind (workflow, cli, cronjob). The governance screens take their population from the family. risk, compliance, datagov, judge and recon are governance.
Models and budgets
All thirteen binaries default their model field to the literal "default". The reviewer and fixer workflows set REVIEW_MODEL=coder. Every model-calling harness agent goes through cmd/modelrouter, which is the one admission queue in front of the engines, on the background lane. Two stay direct to the engine on purpose: opsdoctor (it must not depend on the hop it reports on) and eval bench (it measures the engine itself).
Agent cost is decode-seconds, not runner-minutes. The model plane serves one request at a time. Every budget derives from one configured rate, INFERENCE_DECODE_TOK_S. Each agent’s budget.go defaults it to 3.4 tok/s, and the workflows pass vars.INFERENCE_DECODE_TOK_S. answerBudget(windowSeconds) derives max_tokens from the deadline rather than declaring it separately. At that rate a 2,000-token answer is about ten minutes of pure decode.
Switches
| Variable (Actions variable of the same name) | Default | Effect |
|---|---|---|
CORE_FIXER_JUDGEMENT, CORE_SELFHEAL_JUDGEMENT, CORE_TRIAGE_JUDGEMENT | on | the shared plan gate (inference/judgement.JudgePlan) judges the agent’s own proposal before it acts. Only off, false, 0, no or disabled turns one off |
CORE_FAST_JUDGEMENT | on | the judgement fast path (judgefast) runs in front of the LLM for judge and the three plan gates |
CURATOR_CRON_DRY_RUN | unset means dry | the scheduled curator publishes only when this is the literal string false |
CORE_FORGE_ENABLED | off | arms the forger |
With the plan gate, a dissent blocks the action. The fixer pushes nothing and reports unresolved, self-heal posts a “withheld” notice, and triage posts the classification with labels withheld. Unable-to-judge does not block: the fixer’s draft is titled [not verified by the judge], and self-heal and triage say NOT VERIFIED. Every run prints a line beginning PLAN-GATE: (off, empty, concur, dissent or unable) with the tally.
CURATOR_CRON_DRY_RUN means dry.Started by Atlas playbooks
Six agents accept repository_dispatch event type core-playbook: datagov, compliance, risk, judge, recon and curator. Each job runs only when client_payload.agent names its own agent. The payload is validated by .github/scripts/playbook-context.sh and reaches the agent as PLAYBOOK_ID, PLAYBOOK_RUN_ID, PLAYBOOK_STEP_ID and PLAYBOOK_CHAIN_DEPTH. The job’s last step reports the outcome to POST /api/playbook-runs/step-report. A curator started by a playbook is treated exactly like the scheduled run. See Playbooks.
Pairs that look like duplicates and are not
| Pair | The boundary |
|---|---|
curator security audit vs risk | The curator reads first-party code committed since its last run (CWE/OWASP, model-judged). risk runs govulncheck over dependencies (known CVEs, reachable). |
curator compliance audit vs compliance | The curator starts from a diff and asks which controls it touches. compliance starts from the control index in docs/COMPLIANCE.md, checks every citation still exists, and deep-reads three controls. |
selfheal vs opsdoctor | selfheal needs a job that ran and failed. opsdoctor sees jobs that never run and runner pods that crash, from a CronJob outside Actions. |
agents/selfheal vs mesh/selfheal | The agent diagnoses failing CI runs. mesh/selfheal is the circuit-breaker/remediator library the apps link. |
agents/judge vs agents/eval’s judge | eval/judge.go scores our agents’ run traces against a golden set. agents/judge assesses someone else’s finding against its evidence. |
Behaviours worth knowing
opsdoctormust never become a workflow. It heals the CI plane, so it cannot depend on it. It is the only agent that ships as an image (agents/has exactly one Dockerfile).complianceproposes and cannot apply. Its workflow holdscontents: read.datagovholds no credential and dials nothing. It assesses data quality and PII exposure only from what Resolve’s Explore recorded, read throughGET /api/data-governance-estate. A source nobody explored stays unassessable. See Data governance.judgeabstains rather than agreeing. Its outcomes are concur, dissent and unable-to-judge. As deployed its docket stays empty unlessCORE_JUDGEMENT_INGEST_TOKENis set, becausePOST /api/judgement/submissionsrefuses everything while it is unset. See Judgements.reconcalls an ungoverned rule Shadow, so a fresh workspace is mostly Shadow. That is by design.- A model failure is loud.
reviewer,triageandselfhealpost a degraded notice when the model is unreachable instead of exiting green.
Managing schedules from the console
GET /api/agent-schedules lists fleet cadence and enablement, and which of it is editable. PUT /api/agent-schedules/{name} arms or disarms an agent with a body carrying at least one of enabled, dryRun or schedule. It is a privileged write gated by CONSOLE_AGENT_ADMINS and audited. In the console this is Agent runs › Runs, “Schedules & arming” tab (?tab=agentSchedules).