# Multi-Agent Orchestration

Agor supports running multiple AI agents that communicate with each other, coordinate work through a shared task board, and are managed by a hierarchy of specialized roles. This document covers the inter-agent messaging system (btmsg), the task board (bttask), agent roles and system prompts, and the auto-wake scheduler.

---

## Agent Roles (Tier 1 and Tier 2)

### Tier 1 — Management Agents

Defined in `groups.json` under a group's `agents[]` array. Each management agent gets a full ProjectBox in the UI (converted via `agentToProject()`). They have role-specific capabilities, tabs, and system prompts.

| Role | Tabs | btmsg Permissions | bttask Permissions | Purpose |
|------|------|-------------------|-------------------|---------|
| **Manager** | Model, Tasks | Full (send, receive, create channels) | Full CRUD | Coordinates work, creates/assigns tasks |
| **Architect** | Model, Architecture | Send, receive | Read-only + comments | Designs solutions, creates PlantUML diagrams |
| **Tester** | Model, Selenium, Tests | Send, receive | Read-only + comments | Runs tests, monitors screenshots |
| **Reviewer** | Model, Tasks | Send, receive | Read + status + comments | Reviews code, manages review queue |

### Tier 2 — Project Agents

Regular `ProjectConfig` entries in `groups.json`. Each project gets its own Claude session with optional custom context via `project.systemPrompt`. Standard tabs (Model, Docs, Context, Files, SSH, Memory) but no role-specific tabs.

### System Prompt Generation

Tier 1 agents receive auto-generated system prompts built by `generateAgentPrompt()` in `utils/agent-prompts.ts` with 7 sections: Identity, Environment, Team, btmsg docs, bttask docs, Custom context, Workflow.

Tier 2 agents receive only the custom context section (if `project.systemPrompt` is set).

### BTMSG_AGENT_ID

Tier 1 agents receive the `BTMSG_AGENT_ID` environment variable, injected via `extra_env` in AgentQueryOptions. This flows through 5 layers: TypeScript -> Rust -> NDJSON -> JS runner -> SDK env. The CLI tools (`btmsg`, `bttask`) read this variable to identify which agent is sending messages.

### Periodic Re-injection

AgentSession runs a 1-hour timer that re-sends the system prompt when the agent is idle, countering LLM context degradation over long sessions.

---

## btmsg — Inter-Agent Messaging

btmsg lets agents communicate with each other via a Rust backend (SQLite), a Python CLI tool, and a Svelte frontend (CommsTab).

### Database Schema

The btmsg database (`btmsg.db`, `~/.local/share/agor/btmsg.db`) stores all messaging data:

| Table | Purpose | Key Columns |
|-------|---------|-------------|
| `agents` | Agent registry | id, name, role, project_id, status, created_at |
| `messages` | All messages | id, sender_id, recipient_id, channel_id, content, read, created_at |
| `channels` | Named channels | id, name, created_by, created_at |
| `contacts` | ACL | agent_id, contact_id (bidirectional) |
| `heartbeats` | Liveness | agent_id, last_heartbeat, status |
| `dead_letter_queue` | Failed delivery | message_id, reason, created_at |
| `audit_log` | All operations | id, event_type, agent_id, details, created_at |

### CLI Usage (for agents)

```bash
btmsg send architect "Please review the auth module design"
btmsg read
btmsg channel create #architecture-decisions
btmsg channel post #review-queue "PR #42 ready for review"
btmsg heartbeat
btmsg agents
```

### Dead Letter Queue

Messages sent to non-existent or offline agents are moved to the dead letter queue instead of being silently dropped.

---

## bttask — Task Board

bttask is a kanban-style task board sharing the same SQLite database as btmsg (`btmsg.db`).

### Task Lifecycle

```
Backlog -> In Progress -> Review -> Done / Rejected
```

When a task moves to "Review", the system auto-posts to the `#review-queue` btmsg channel.

### Optimistic Locking

To prevent concurrent updates from corrupting task state, bttask uses a `version` column:

1. Client reads task with current version (e.g., version=3)
2. Client sends update with expected version=3
3. Server's UPDATE includes `WHERE version = 3`
4. If another client updated first (version=4), WHERE matches 0 rows -> conflict error

### Role-Based Permissions

| Role | List | Create | Update Status | Delete | Comments |
|------|------|--------|---------------|--------|----------|
| Manager | Yes | Yes | Yes | Yes | Yes |
| Reviewer | Yes | No | Yes (review decisions) | No | Yes |
| Architect | Yes | No | No | No | Yes |
| Tester | Yes | No | No | No | Yes |
| Project (Tier 2) | Yes | No | No | No | Yes |

### Review Queue Integration

The Reviewer agent gets special treatment in attention scoring: `reviewQueueDepth` adds 10 points per review task (capped at 50). ProjectBox polls `review_queue_count` every 10 seconds for reviewer agents.

---

## Wake Scheduler

The wake scheduler automatically re-activates idle Manager agents when attention-worthy events occur (`wake-scheduler.svelte.ts`).

### Strategies

| Strategy | Behavior | Use Case |
|----------|----------|----------|
| **Persistent** | Resume prompt to existing session | Long-running managers |
| **On-demand** | Fresh session | Burst-work managers |
| **Smart** | On-demand when score exceeds threshold | Avoids waking for minor events |

### Wake Signals

| Signal | Weight | Trigger |
|--------|--------|---------|
| AttentionSpike | 1.0 | Project attention score exceeds threshold |
| ContextPressureCluster | 0.9 | Multiple projects >75% context usage |
| BurnRateAnomaly | 0.8 | Cost rate deviates from baseline |
| TaskQueuePressure | 0.7 | Task backlog grows beyond threshold |
| ReviewBacklog | 0.6 | Review queue has pending items |
| PeriodicFloor | 0.1 | Minimum periodic check |

Pure scoring function in `wake-scorer.ts` (24 tests). Types in `types/wake.ts`.

---

## Health Monitoring & Attention Scoring

The health store (`health.svelte.ts`) tracks per-project health with a 5-second tick timer.

### Activity States

| State | Meaning | Visual |
|-------|---------|--------|
| Inactive | No agent running | Dim dot |
| Running | Agent actively processing | Green pulse |
| Idle | Agent finished, waiting for input | Gray dot |
| Stalled | No output for >N minutes | Orange pulse |

Stall threshold is configurable per-project (default 15 min, range 5-60, step 5).

### Attention Scoring

| Condition | Score |
|-----------|-------|
| Stalled agent | 100 |
| Error state | 90 |
| Context >90% | 80 |
| File conflict | 70 |
| Review queue depth | 10/task, cap 50 |
| Context >75% | 40 |

Pure scoring function in `utils/attention-scorer.ts` (14 tests).

### File Conflict Detection

Two types detected by `conflicts.svelte.ts`:

1. **Agent overlap** — Two agents in the same worktree write the same file
2. **External writes** — File modified externally (detected via inotify, 2s timing heuristic)

---

## Session Anchors

Session anchors preserve important conversation turns through Claude's context compaction process.

### Anchor Types

| Type | Created By | Behavior |
|------|-----------|----------|
| **Auto** | System (first compaction) | Captures first 3 turns, observation-masked |
| **Pinned** | User (pin button) | Marks specific turns as important |
| **Promoted** | User (from pinned) | Re-injectable via system prompt |

### Anchor Budget

| Scale | Token Budget | Use Case |
|-------|-------------|----------|
| Small | 2,000 | Quick sessions |
| Medium | 6,000 | Default |
| Large | 12,000 | Complex debugging |
| Full | 20,000 | Maximum preservation |

Re-injection flow: `anchors.svelte.ts` -> `anchor-serializer.ts` -> `AgentPane.startQuery()` -> `system_prompt` -> sidecar -> SDK.
