NEXUS Orchestrator
NEXUS is the central coordinator of the OpenFlows system. It runs as a controller process inside a dedicated
per-tenant Coder workspace (openflows-nexus-[tenant]) and owns all coordination logic.
Unlike the worker agents, NEXUS does not use an LLM for routing decisions - it uses a deterministic
rule-based loop that requires no model calls.
Coder-only design
exec() phase. This simplifies the controller,
reduces latency, and removes the need for model credentials in the orchestrator.
Responsibilities
- Ticket Assignment - Fetches GitHub issues, creates tickets in SharedStore, assigns to idle workers
- Worker Provisioning - Creates Coder workspaces for FORGE/SENTINEL workers on demand via Coder API
- Recovery - Monitors for crashed workspaces, orphaned tickets, stale workers, unmerged PRs
- Team Coordination - Routes work between agents based on phase transitions
- Heartbeat Monitoring - Tracks worker liveness via Redis heartbeats
Decision Loop
The NEXUS controller runs a tight loop every 15 seconds. Each iteration follows a three-phase pattern:
The NEXUS controller implements a three-phase pattern: prep() syncs state from external systems,
exec() performs rule-based routing decisions, and post() executes those decisions.
The run() method orchestrates these phases in a tight loop every 15 seconds.
Phase Details
| Phase | Operations |
|---|---|
prep() |
Sync GitHub issues → create tickets in Redis Check worker health from heartbeats Load current Redis state (tickets, workers, dispatches) |
exec() |
Rule-based routing: • Unassigned tickets → assign to idle FORGE • Stale workers → mark tickets for re-assignment • Ready PRs → handoff to SENTINEL • Approved PRs → handoff to VESSEL |
post() |
Execute decision: • Create Coder workspace via API • Write dispatch to Redis • Send kickoff message via Coder Chat |
Redis Key Schema
| Key Pattern | Description |
|---|---|
tickets | Sorted set of all ticket IDs |
ticket:{id}:status | Current status: open | assigned | working | review_ready | awaiting_human | merged |
ticket:{id}:dispatch | Task payload: { issue, repo, phase, contract_path } |
ticket:{id}:contract | CONTRACT.md content for SENTINEL review |
worker_slots | Map: forge-1 → { status, workspace_id, last_heartbeat } |
ns:{[tenant]}:heartbeat:{worker} | Unix timestamp of last heartbeat |
ns:{[tenant]}:event_ring | Ring buffer of last 1000 events for TUI |
ns:{[tenant]}:flow_recovery | Recovery state and inconsistencies detected |
Inspecting NEXUS state
redis-cli to inspect live state:
redis-cli --scan --pattern 'ns:my-team:*'
redis-cli GET ns:my-team:ticket:123:status
redis-cli HGETALL ns:my-team:worker_slots
Recovery Behaviors
The reconcile() method runs on every loop iteration and handles:
- Orphaned tickets - Ticket assigned to worker that no longer exists → reassign
- Stale workers - Worker heartbeat older than 90s → mark ticket for reassignment
- Unmerged PRs - PR merged but ticket not marked → complete ticket
- Completed without PR - Worker finished but no PR opened → investigate
- SENTINEL rejection loop - Same segment rejected > 3 times → escalate to
AwaitingHuman
Configuration
NEXUS is configured in registry.json with workspace_provider: "coder", AI gateway routing, and the NEXUS agent definition.
NEXUS does not use LLM in Coder-only mode
provider and model fields for NEXUS are ignored in the current architecture.
NEXUS routing is entirely rule-based via exec(). These fields are reserved for future
LLM-assisted routing features.
Startup Script
The NEXUS workspace auto-starts the controller via startup_script in the Coder template:
The NEXUS workspace auto-starts via a startup script that:
- Installs the
openflows-harnessbinary from the releases repository - Starts the heartbeat daemon to write worker health signals to Redis
- Executes the NEXUS controller with the tenant configuration
Monitoring
- Logs -
/tmp/openflows-controller.logon NEXUS workspace - TUI -
cargo run -p openflows-tuifor real-time dashboard - Doctor -
openflows doctor --tenant my-teamfor health checks - Metrics - Controller exposes
:8080/metrics(Prometheus format)