runtimeConfig.enabled answered two different questions. Every consumer in the
engine reads it as "run this agent's own durable heartbeat loop" — heartbeat
scheduling, error recovery, self-healing, in-process runtime — except the
workflow router, which also read it as "may own a workflow stage".
That conflation caused both failures:
- Built-in owners ship with the heartbeat off, which is CORRECT (they are
invoked by the workflow engine and must not run autonomous loops or auto-claim
work). That silently made every built-in role unroutable and deadlocked the
board.
- Enabling the heartbeat to restore routing then gave four agents autonomous
loops and auto-claiming nobody asked for.
Separate the flag:
- runtimeConfig.enabled governs the heartbeat runtime ONLY
- isWorkflowPrincipalEligible answers routability, and treats the four built-in
role owners as routable structurally — there is no fallback if a role cannot
route, so "unroutable" is not a state an operator can meaningfully select
- provision built-ins { enabled: false, autoClaimRelevantTasks: false }
- paused/errored still outranks the exemption, so it can never resurrect a
broken principal
Removes the earlier write-seam coercion that forced enabled:true — the invariant
is now structural rather than fought for on every write.
Also re-applies the principal-hold backoff ladder (15s -> 5m, checked before
graph entry) into executor/execute-workflow-graph.ts. PR #3317's executor peel
rewrote executor.ts from a pre-change base and dropped it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>