Files
fusion/.changeset/workflow-column-agent-assignment.md
gsxdsm 41f25d5c52 feat(engine): effective column agent becomes the execution principal
U5: action-gating contexts, the heartbeat deferral gate, a two-pass
resumeTaskForAgent, and the reverse-direction agent.taskId guards (via a
new isAgentEffectivelyExecuting callback wired at the in-process runtime)
all consult the column-effective agent; the restart watcher re-resolves
column bindings per tick for bound graph sessions, hot-swapping on
agent-changed and falling back without restart on agent-deleted.
2026-06-05 00:19:13 -07:00

2.1 KiB

@runfusion/fusion
@runfusion/fusion
minor

Add per-column agent assignment for workflow columns, behind the combined experimentalFeatures.workflowColumns + experimentalFeatures.workflowGraphExecutor flags.

A workflow column can now name a permanent agent from the registry plus a mode — defer (the column agent is the default for work in that column that carries no agent/model settings of its own) or override (the column agent supersedes node- and task-level agent/model settings). The binding applies to all session-running work attributable to the column's nodes: custom prompt/gate/script nodes, the execute seam's coding session, and step-execute sessions. Precedence is resolved by one shared @fusion/core resolver (resolveColumnAgentBinding + resolveEffectiveAgent) consumed by every reader, with defer/override expressed as explicit named rules and defer granularity all-or-nothing (an own agent identity OR a complete modelProvider+modelId pair suppresses the column agent). The binding keys off the node's declared IR column; foreach template nodes inherit the enclosing foreach node's column. A missing/deleted agent at resolution time logs and falls back to normal resolution — a live session is never aborted. The built-in default workflow carries no column agents and stays byte-identical (parity oracle); with either flag off, column agents are inert.

The effective column agent is also the principal for the subsystems that previously assumed the running agent is always task.assignedAgentId: action gating (buildActionGateContext / buildPermanentAgentGatingContext) is computed for the agent actually running; heartbeat serialization honors it in both directions (the execute deferral gate, a second resumeTaskForAgent pass that re-dispatches tasks whose effective column agent matches, and a reverse-direction heartbeat-scheduler guard so an allowParallelExecution=false column agent never heartbeats concurrently with its own session); and a workflow-definition edit or agent runtimeConfig change that re-keys the column-effective agent/model hot-swaps the running graph session, while an agent deleted mid-session falls back without a restart.