CORALCORAL
Concepts

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

ComponentTechnology
LanguagePython 3.11+
Build systemHatchling
Package manageruv
Agent runtimesClaude Code, Codex, OpenCode
Web dashboardStarlette (backend) + React/Vite (frontend)
Key dependencyPyYAML

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.