mints a fresh provider per delivery, for the same reason the dispatcher does: deliveries run outside any request and concurrently with task execution, so sharing one provider would share one transaction scope across unrelated work.
Posts the roll-up as an AI-role message in the graph's conversation.
Never throws. The dispatcher calls this inside the compare-and-swap that marks a completion delivered; an error escaping would either abort that guard or leave the graph looking undelivered and re-notifying on every later sweep.
Starts the submitting agent a fresh turn carrying the graph's outcome.
Never throws, for the same reason PostMessage does not: the dispatcher calls this inside the
compare-and-swap that marks a completion delivered.
The new run records ReinvokeDepth + 1 so the chain is bounded. The dispatcher has already
refused to call this when the cap is reached — it degrades to PostMessage — so arriving here
means there is budget left, and stamping the depth is what keeps that true for the next hop.
Delivers a finished graph's outcome — as a conversation message, or by starting the submitting agent a fresh turn.
The chain is bounded, and that is what took a schema change to make true. A graph may declare
continuation: 'reinvoke', and the agent it restarts can emit another graph, which can reinvoke again. The guard for that (MAX_REINVOKE_DEPTH) shipped in Phase 3, but the number it compared was permanently zero:TaskGraphService.SubmitreadsReinvokeDepthfrom its caller, and a reinvoked agent had no way to know it was a continuation.AIAgentRun.ContinuationDepthcloses that loop — this stamps depth + 1 on the run it starts,BaseAgentpasses it into any graph that run submits, and the cap finally compares against something real.