Skip to content

v1.9.1 — Symphony-inspired orchestration

Choose a tag to compare

@ianborders ianborders released this 04 May 09:29
· 107 commits to main since this release

Lifts four well-shaped patterns from the Symphony spec (OpenAI's draft v1 orchestration spec) into KyberBot's fleet orchestration layer. All additive and backward-compatible — existing identity.yaml deployments keep working unchanged.

Highlights

Run-attempt phase state machine

Eleven named phases per heartbeat run (PreparingWorkspace → BuildingPrompt → LaunchingAgent → InitializingSession → StreamingTurn → Finishing → Succeeded/Failed/TimedOut/Stalled/CanceledByReconciliation). Persisted as phase + phase_history columns on heartbeat_runs (with backfill); the next desktop release surfaces them in the run inspector.

Reconciliation pass

Runs at the top of every CEO heartbeat tick:

  • Stall detection — runs without a phase transition for heartbeat_stall_timeout_ms (default 5min) get marked Stalled and the issue checkout is released
  • External state refresh — pluggable ExternalStateSource interface; issues that go terminal externally have their runs canceled with RunPhase.CanceledByReconciliation

Per-agent concurrency

New optional identity.yaml fields:

concurrency:
  max_concurrent_runs: 1     # default 1
  max_by_state:
    todo: 3
    in_progress: 1

Worker dispatch is gated by canDispatch() before any work begins.

Worker run loop + 1s post-exit retry

  • New worker_max_turns (default 5) — when a turn ends with STATUS: IN_PROGRESS, the worker re-prompts with the previous output's tail as context
  • When a clean run hits the loop cap, queueWorkerHeartbeat schedules a fresh session 1s later (Symphony §8.4) — chains until the agent emits a terminal STATUS, the issue moves out from under the agent, or concurrency/failure gates fire

Hooks

hooks:
  before_run: pnpm install --frozen-lockfile
  after_run: git status --short
  timeout_ms: 60000

Run as bash -lc <script> with KYBERBOT_ISSUE_ID / KYBERBOT_AGENT / KYBERBOT_RUN_STATUS env vars. before_run failure is fatal; after_run is best-effort and runs even on failure paths.

Snapshot API at /api/v1/*

  • GET /api/v1/state — fleet-wide snapshot (counts, agents, running runs, recent terminal runs, reconcile timestamps)
  • GET /api/v1/agents/:name — agent-scoped detail (workspace, recent failure count, current run with phase + last events, last error)
  • POST /api/v1/refresh — queue an immediate reconcile tick (5s coalesced)

Pairs with KyberBot Desktop v1.7.7, which exposes these via IPC under window.kyberbot.fleet.v1.*.

identity.yaml hot-reload

fs.watchFile-based polling watcher per agent (1s cadence). Saves to identity.yaml invalidate the cached config; the next dispatch picks up new values for hooks / concurrency / heartbeat_stall_timeout_ms / worker_max_turns. In-flight runs finish on their original config. Invalid YAML keeps the previous config and surfaces the parse error.

Breaking changes

None. All new fields are optional. Existing identity.yaml continues to work.

Migration

None required. To opt into new fields, add them to the agent's identity.yaml.

Tests

50+ new tests across run-phases, reconcile, hooks, identity-watcher, worker-loop, and api/v1. Full suite: 492/493 pass; the one failure is a pre-existing web-api.test.ts issue from before this work.