agent-orchestrator/docs/agents/orchestration.md

7.5 KiB

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)

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.