Autonomous loop that routes events to ticket and incident pipelines with voice notifications
Orchestrator
The Orchestrator is the autonomous loop at the heart of Overseer. It wires together event watching, decision making, silent ticket execution, incident barge-in, and voice notifications into a single system that runs continuously.
Architecture
Events (webhooks, Redis, cron)
|
EventWatcher
|
DecisionEngine ──> execute_silent ──> TicketPipeline ──> silent work
| └── NotificationSink (inbox/toast)
|
└──> barge_in ──> IncidentPipeline ──> VoiceNotifier ──> barge-in voice
|
└──> notify ──> VoiceNotifier ──> notification
|
└──> queue ──> TicketPipeline queue
|
└──> ignoreAll state is stored in the SharedStateStore, which provides a real-time view of what Overseer is doing for user sessions and dashboards.
Installation
import {
Orchestrator,
createOrchestrator,
SharedStateStore,
TicketPipeline,
IncidentPipeline,
TaskBridge,
DecisionEngine,
EventWatcher,
VoiceNotifier,
} from "@codmir/overseer";Quick Start
import { createOrchestrator } from "@codmir/overseer";
import { defaultOverseerConfig } from "@codmir/overseer";
const orchestrator = createOrchestrator({
overseer: {
...defaultOverseerConfig,
organizationId: "org_abc",
projectIds: ["proj_1", "proj_2"],
autoWork: {
enabled: true,
maxTasksPerWakeUp: 3,
requireApproval: true,
approvalTimeout: 30,
},
},
taskBridge: {
taskRunnerUrl: "https://task.codmir.com",
authToken: process.env.TASK_RUNNER_TOKEN,
maxConcurrent: 5,
executionTimeout: 600_000,
},
eventWatcher: {
redisUrl: process.env.REDIS_URL,
pollInterval: 30_000,
alertRules: [
{
id: "error-spike",
name: "Error Rate Spike",
enabled: true,
condition: { type: "error_rate", threshold: 10, windowSeconds: 300 },
severity: "critical",
cooldownSeconds: 300,
},
{
id: "service-down",
name: "Service Down",
enabled: true,
condition: { type: "service_down", service: "api", checkIntervalSeconds: 30 },
severity: "critical",
cooldownSeconds: 60,
},
],
},
defaultRepoUrl: "https://github.com/codmir/codmir",
defaultBranch: "development",
});
// Set notification sink (inbox, toast, push)
orchestrator.setNotificationSink({
sendNotification: async (userId, title, body, data) => {
await inboxService.create(userId, { title, body, ...data });
},
});
// Start the loop
await orchestrator.start();Orchestrator
createOrchestrator(config): Orchestrator
Factory function. Returns a fully wired orchestrator instance.
createOrchestrator(config: OrchestratorConfig): OrchestratorOrchestratorConfig
interface OrchestratorConfig {
overseer: OverseerConfig;
taskBridge?: Partial<TaskBridgeConfig>;
eventWatcher?: Partial<EventWatcherConfig>;
defaultRepoUrl?: string;
defaultBranch?: string;
}Lifecycle
start(): Promise<void>
Starts the orchestrator. Begins event watching, ticket queue processing (every 30s), and heartbeat (every 10s).
await orchestrator.start();stop(): void
Stops the orchestrator. Halts event watching, cancels all active task bridge tasks, and clears intervals.
orchestrator.stop();Client Integration
registerClient(client): () => void
Registers a connected client for voice notifications. Returns an unsubscribe function. Call this when a user connects via WebSocket.
const unregister = orchestrator.registerClient({
userId: "user_123",
sessionId: "sess_abc",
platform: "desktop",
capabilities: ["voice", "notification"],
onNotification: async (title, body, data) => {
socket.emit("notification", { title, body, data });
},
onVoiceStart: async (incident, persona) => {
socket.emit("voice:barge-in", { incident, persona });
return true; // accepted
},
onVoiceMessage: async (message, priority) => {
socket.emit("voice:speak", { message, priority });
},
onVoiceEnd: async (reason) => {
socket.emit("voice:end", { reason });
},
});
// On disconnect:
unregister();setNotificationSink(sink): void
Sets the notification delivery mechanism for the ticket pipeline.
interface NotificationSink {
sendNotification(
userId: string,
title: string,
body: string,
data?: Record<string, unknown>,
): Promise<void>;
}setVoiceChannel(channel): void
Sets the voice channel for incident barge-in. The default adapter bridges the VoiceNotifier to all online clients, but you can provide a custom implementation.
interface VoiceChannel {
bargeIn(notification: VoiceNotification): Promise<boolean>;
speak(message: string, priority?: "normal" | "urgent"): Promise<void>;
listen(timeoutMs?: number): Promise<string | null>;
disconnect(): Promise<void>;
isActive(): boolean;
}Status
getStatusSummary(): string
Returns a human-readable summary of what Overseer is currently doing. Use this when a user asks "what are you working on?" in voice mode.
const summary = orchestrator.getStatusSummary();
// "Working on 2 tickets: INC-A7X9 (fixing checkout error), TASK-B2C3 (implementing dark mode)"getState(): OverseerSharedState
Returns the full shared state for dashboards and monitoring.
interface OverseerSharedState {
activities: OverseerActivity[];
recentCompletions: OverseerActivity[];
activeIncident: IncidentContext | null;
lastHeartbeat: Date;
status: "idle" | "working" | "incident" | "sleeping";
}isWorkingOn(ticketId): boolean
Checks if Overseer is already working on a specific ticket. Prevents duplicates when a user manually starts work that Overseer is handling silently.
if (!orchestrator.isWorkingOn("TICKET-42")) {
// Safe to start manual work
}Manual Triggers
injectEvent(event): Promise<void>
Manually inject an event for testing or admin triggers.
await orchestrator.injectEvent({
trigger: "ticket_created",
source: "manual",
context: {
ticketId: "TICKET-42",
title: "Fix login form validation",
description: "Email field accepts invalid formats",
priority: "high",
repo: "https://github.com/codmir/codmir",
branch: "development",
},
});processWebhook(provider, payload): Promise<void>
Process an incoming webhook from GitHub, Vercel, Railway, etc.
app.post("/webhooks/:provider", async (req, res) => {
await orchestrator.processWebhook(req.params.provider, req.body);
res.sendStatus(200);
});Sub-Components
The orchestrator exposes its internal components as readonly properties for advanced use.
orchestrator.store -- SharedStateStore
In-memory state store that tracks all activities, recent completions, and the active incident. Provides getStatusSummary(), heartbeat(), and isWorkingOn().
orchestrator.bridge -- TaskBridge
Dispatches tasks to the external task runner service. Manages concurrent task limits and execution timeouts.
interface TaskBridgeConfig {
taskRunnerUrl: string;
authToken?: string;
maxConcurrent: number; // default: 5
executionTimeout: number; // default: 600000 (10 min)
}orchestrator.decisions -- DecisionEngine
Evaluates incoming events and produces a DecisionResult:
interface DecisionResult {
action: "execute_silent" | "barge_in" | "notify" | "queue" | "ignore";
pipeline: "ticket" | "incident";
priority: "critical" | "high" | "medium" | "low";
reason: string;
requiresApproval: boolean;
}Routing rules:
- Incident triggers (
alert,build_failed,deploy_failed,error_spike,latency_spike,service_down) always route to the incident pipeline.critical/fatalseverity triggersbarge_in(immediate voice interruption).warningseverity triggersnotify(silent notification).
- Ticket triggers (
ticket_created,ticket_updated,scheduled,standup,mention) route to the ticket pipeline.- Disabled triggers are ignored.
- Capacity limits cause queuing.
- Duplicate tickets (already working on) are ignored.
The engine also evaluates alert rules against metrics:
orchestrator.decisions.evaluateAlertRule(
{
id: "error-spike",
name: "Error Rate Spike",
enabled: true,
condition: { type: "error_rate", threshold: 10, windowSeconds: 300 },
severity: "critical",
cooldownSeconds: 300,
},
{ errorRate: 25 },
);
// => { triggered: true, source: { provider: "overseer", ... } }orchestrator.events -- EventWatcher
Listens for events from Redis pub/sub, webhooks, and cron-based polling. Normalizes events and forwards them to the decision engine.
interface EventWatcherConfig {
redisUrl?: string;
webhookEndpoints?: string[];
pollInterval: number;
alertRules: AlertRule[];
}orchestrator.tickets -- TicketPipeline
Handles silent autonomous execution. Accepts ticket events, dispatches them via the task bridge, and notifies via the notification sink on completion or failure.
orchestrator.incidents -- IncidentPipeline
Handles incident detection, investigation, and voice barge-in. When a critical incident occurs, it uses the voice channel to interrupt the user.
orchestrator.voice -- VoiceNotifier
Manages connected clients and delivers voice notifications. Handles barge-in (interrupting a user's session), speak (sending TTS messages), and notify (sending toast/inbox notifications).
Types
OrchestratorEventType
type OrchestratorEventType =
| "ticket_picked_up"
| "ticket_executing"
| "ticket_completed"
| "ticket_failed"
| "incident_detected"
| "incident_barge_in"
| "incident_investigating"
| "incident_resolved"
| "incident_escalated"
| "voice_initiated"
| "voice_ended"
| "approval_requested"
| "approval_received"
| "state_sync";TicketTrigger
type TicketTrigger =
| "ticket_created"
| "ticket_updated"
| "scheduled"
| "standup"
| "mention";IncidentTrigger
type IncidentTrigger =
| "alert"
| "build_failed"
| "deploy_failed"
| "error_spike"
| "latency_spike"
| "service_down";AlertRule
interface AlertRule {
id: string;
name: string;
enabled: boolean;
condition: AlertCondition;
severity: "warning" | "critical" | "fatal";
cooldownSeconds: number;
lastTriggered?: Date;
}AlertCondition
type AlertCondition =
| { type: "error_rate"; threshold: number; windowSeconds: number; service?: string }
| { type: "latency"; thresholdMs: number; percentile: "p50" | "p95" | "p99"; service?: string }
| { type: "status_code"; code: number; countThreshold: number; windowSeconds: number }
| { type: "service_down"; service: string; checkIntervalSeconds: number }
| { type: "deploy_failed"; provider: "vercel" | "railway" | "github_actions" }
| { type: "custom"; evaluator: string };VoiceNotification
interface VoiceNotification {
id: string;
mode: "notification" | "barge_in" | "conversation";
priority: "low" | "normal" | "urgent" | "critical";
message: string;
incident?: IncidentContext;
targetUserId?: string;
targetSessionId?: string;
persona?: string;
}ConnectedClient
interface ConnectedClient {
userId: string;
sessionId: string;
platform: string;
capabilities: string[];
onNotification: (title: string, body: string, data?: Record<string, unknown>) => Promise<void>;
onVoiceStart: (incident: IncidentContext, persona?: string) => Promise<boolean>;
onVoiceMessage: (message: string, priority?: "normal" | "urgent") => Promise<void>;
onVoiceEnd: (reason: string) => Promise<void>;
}