Architecture
How CORAL orchestrates autonomous coding agents.
CORAL follows a simple loop: spawn agents → agents read instructions → commit changes → eval → repeat.
System overview
┌─────────────────────────────────────────┐
│ coral start │
│ │
│ 1. Create .coral/ shared state │
│ 2. Create per-agent git worktrees │
│ 3. Spawn grader daemon │
│ 4. Generate CORAL.md instructions │
│ 5. Spawn agent subprocesses │
└────────────────────┬────────────────────┘
│
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌─────────────────┐
│ Agent 1 │ │ Agent 2 │ │ Grader Daemon │
│ │ │ │ │ │
│ Edit code│ │ Edit code│ │ Poll pending │
│ commit │ │ commit │ │ git worktree │
│ write │ │ write │ │ run grader │
│ pending │ │ pending │ │ write score │
│ poll... │ │ poll... │ │ cleanup │
└──────────┘ └──────────┘ └─────────────────┘
│ │ ▲
└──────────────┴──────────────┘
.coral/public/attempts/
(pending → scored JSONs)Agents and the grader daemon communicate entirely through the filesystem — there is no RPC, no sockets, no message queue. Agents write pending attempt JSON files; the daemon reads them, grades, and writes back the results. Agents poll the same files until the score appears.
Directory layout
When you run coral start, the following structure is created:
results/<task-name>/<timestamp>/
├── .coral/ # Shared state directory
│ ├── config.yaml # Task configuration (copy)
│ ├── public/ # Visible to all agents
│ │ ├── attempts/ # JSON records of each eval
│ │ ├── notes/ # Agent-written insights
│ │ ├── skills/ # Reusable tools/scripts
│ │ ├── logs/ # Agent session logs
│ │ ├── heartbeat/ # Heartbeat action configs
│ │ ├── steering/ # Stopped-run dashboard steering queue
│ │ ├── eval_count # Global eval counter
│ │ ├── grader_daemon.pid # Daemon process ID
│ │ └── grader_daemon_heartbeat # Daemon liveness timestamp
│ └── private/ # Hidden from agents
│ ├── grader_venv/ # Isolated venv running the grader entrypoint
│ └── grader_checkouts/ # Ephemeral worktrees for grading
│
└── agents/
├── agent-1/ # Git worktree for agent 1
│ ├── .coral_dir # Points to shared .coral/
│ ├── .coral_agent_id # This agent's ID
│ ├── CORAL.md # Generated instructions
│ └── <task files> # Seeded from workspace.repo_path
│
└── agent-2/ # Git worktree for agent 2
└── ...Tech stack
| Component | Technology |
|---|---|
| Language | Python 3.11+ |
| Build system | Hatchling |
| Package manager | uv |
| Agent runtimes | Claude Code, Codex, OpenCode |
| Web dashboard | Starlette (backend) + React/Vite (frontend) |
| Key dependency | PyYAML |
Dashboard steering
The dashboard can steer a stopped run through .coral/public/steering/.
POST /api/steer validates that the manager is not alive, then either queues a
continue_from action or marks an attempt as user-best. coral resume is the
only place queued continue_from actions are applied: the manager finds every
agent worktree whose current HEAD descends from the selected commit, resets
those worktrees to the selected commit, composes the queued instruction with any
operator-provided resume instruction, and marks the action applied.
The CLI uses the same manager path without the queue: coral resume --from <hash> -i "..." creates an in-memory resume steering action for the selected
attempt and composes it with the resume instruction.
This keeps ownership clear. Live agents own their worktrees while running; the dashboard only mutates worktrees during resume, after the previous manager has stopped.
