You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/workflow-supervisor-implementation-plan.md
+29-2Lines changed: 29 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -116,13 +116,40 @@ bundle, and the HTTP debug endpoint cannot drift.
116
116
- Supervisor cost attributed through the existing cost tracking so `nodetool costs` sees it (PRD open question 3 resolved: attributed to the run, tagged `supervisor`).
117
117
- Docs: CLI section in root `CLAUDE.md` + `docs/cli.md`.
Three things the plan did not anticipate, all forced by the websocket half.
124
+
125
+
A `supervise` flag alone cannot start a supervisor: something has to name the
126
+
model. The run request therefore carries an optional `supervisor`
127
+
(`SupervisorRunOptions`: provider, model, the three bounds, cost cap) next to
128
+
the flag, falling back to the connection's configured default model and then to
129
+
`NODETOOL_SUPERVISOR_PROVIDER` / `NODETOOL_SUPERVISOR_MODEL` — the last exists
130
+
because trigger-driven headless runs have no connection defaults at all. A
131
+
request that asks for supervision it cannot get runs **unsupervised** rather
132
+
than failing, which is the same fail-closed rule every other supervisor failure
133
+
follows.
134
+
135
+
The trigger flag is a real column (`trigger_registrations.supervise`, default
136
+
`0`, migration `20260801_000001`), read by the dispatcher into the headless run.
137
+
Registration sync mutates existing rows in place, so re-syncing a workflow never
138
+
resets it.
139
+
140
+
The supervisor gets a **dedicated provider instance** (`getProvider`, not the
141
+
context's cached one) and a listener-free context copy: per-turn spend is
142
+
reconciled from the provider's own running cost, so a second caller on the same
143
+
instance would corrupt the dollar cap, and the decision's own provider traffic
144
+
is not the run's message stream. The escalation and the verdict still cross the
145
+
websocket — they are emitted by the kernel on the run's context.
146
+
147
+
`ExecutionSessionOptions.supervisor` is PR 4's deliverable and landed here
148
+
because PR 5 needs it; the two branches carry the same three-line change.
149
+
123
150
-`AgentOptions.graph?: GraphData | { workflowId: string }`; fourth branch in `Agent._executeImpl`: hydrate, run through `ExecutionSession` with self as supervisor, forward messages, `getResults()` returns run outputs. The branch adopts the common `AgentPolicy` object (`packages/agents/src/agent-policy.ts`); it does not add a fifth ad-hoc policy.
124
151
- Websocket: `supervise` flag on run requests; forward `supervisor_*` messages to clients. Trigger rows carry the flag but it **defaults to off** — the flip to default-on belongs to PR 8's gate, nowhere earlier.
125
-
- Tests: `Agent({graph})` returns identical outputs to a bare runner on a clean graph; interventions surface in the message stream.
152
+
- Tests: `Agent({graph})` returns identical outputs to a bare runner on a clean graph; interventions surface in the message stream. Plus what makes the branch trustworthy: a scripted `skip` completes a run that otherwise fails and a scripted `fail` does not, a clean supervised run emits no `supervisor_*` message at all, an aborted signal cancels the run, and `createRunSupervisor` returns no handle without an explicit flag and a resolvable model.
0 commit comments