repromptOnUnmet and the provider execution path disagree about what a re-prompt is. For a bridge-placed root the disagreement is masked. For a provider-placed root it silently destroys the run's continuity.
The two halves
Half one — the re-prompt believes it is continuing a session. supervisor-agent.ts:479:
A re-prompt reuses the retry path: same scope, same coordination server, same live children, same budget/deadline/abort/attempt bounds.
driver-retry.ts:44:
reprompt.maxReprompts re-enters the SAME live session with the unmet items
and DriverRetryRun.drive:
reentry is present only for a re-prompt: run the SAME session on reentry.steer instead of the original task.
defaultUnmetContractSteer is written for that reader. Its last line is:
Do not restate work you already did.
Half two — the provider path mints a new execution. retained-scope-owner.ts:63:
return `${args.nodeId}:input:${state.inputSequence}`
inputSequence is the seq of the latest execution-input, and a re-prompt writes a new one. So executionId changes per re-prompt, and environment-provider.ts derives the create key and the turn id from it:
idempotencyKey: `runtime:${args.executionId}`,
turn: { ...turn, turnId: `${args.executionId}:turn:0` },
A new idempotency key is a new environment. Every re-prompt therefore starts a fresh sandbox at turn 0, with no conversation history, and the steer tells that fresh agent not to repeat work it has no record of doing.
The bridge backend does not have this problem: supervise.ts:1591 says it "reattaches the harness session by its durable execution id."
Measured
mech-interp-foundations-pi-20260915k, a sandbox-placed root on 0.225.6, four attempts, from its spawn journal:
intent key: runtime:...-20260915k:input:1 turnId ...:input:1:turn:0 sandbox-9ce8df04513b
intent key: runtime:...-20260915k:input:6 turnId ...:input:6:turn:0 sandbox-2689acf486c6
intent key: runtime:...-20260915k:input:11 turnId ...:input:11:turn:0 sandbox-1570fa62f005
intent key: runtime:...-20260915k:input:16 turnId ...:input:16:turn:0 (no environment issued)
Three complete turns, three different sandboxes, every one at turn:0. Receipt and journal: discovery-lab#767.
The provider is not the limitation. @tangle-network/agent-provider-tangle declares retainedControl, and environment-provider.ts:1197 takes the retained path when it is present. The retained path still creates, because the key it creates under is new.
Why this matters beyond one run
In the pursuit that produced this run, every one of its 595 knowledge pages came from a bridge-placed root, which keeps its session across turns. A fleet-placed root has produced zero pages across fourteen presses. Each of those presses was previously attributed to an infrastructure failure; this is the structural reason underneath.
The failure is also invisible from the outside. The run does not error. It completes turns, spends tokens, and settles no-winner, which reads as a research result rather than a lost session.
What a fix has to decide
Either:
- A re-prompt reuses the committed execution id, so the provider reconnects to the retained run and the conversation continues. That matches every doc comment quoted above and makes the steer's last line true.
- A re-prompt is defined as a new execution, in which case
defaultUnmetContractSteer must carry forward what the previous turn did, and the doc comments claiming the same session should be corrected.
Option 1 looks right to me because the retained-control machinery already exists and the bridge path already behaves this way, but the choice belongs to this repo.
Adjacent, same root
repromptOnUnmet with a provider backend also multiplies environments: three turns created three sandboxes. Under any per-account concurrency limit each re-prompt competes for a slot with its own predecessors' teardown.
repromptOnUnmetand the provider execution path disagree about what a re-prompt is. For a bridge-placed root the disagreement is masked. For a provider-placed root it silently destroys the run's continuity.The two halves
Half one — the re-prompt believes it is continuing a session.
supervisor-agent.ts:479:driver-retry.ts:44:and
DriverRetryRun.drive:defaultUnmetContractSteeris written for that reader. Its last line is:Half two — the provider path mints a new execution.
retained-scope-owner.ts:63:inputSequenceis the seq of the latestexecution-input, and a re-prompt writes a new one. SoexecutionIdchanges per re-prompt, andenvironment-provider.tsderives the create key and the turn id from it:A new idempotency key is a new environment. Every re-prompt therefore starts a fresh sandbox at turn 0, with no conversation history, and the steer tells that fresh agent not to repeat work it has no record of doing.
The bridge backend does not have this problem:
supervise.ts:1591says it "reattaches the harness session by its durable execution id."Measured
mech-interp-foundations-pi-20260915k, a sandbox-placed root on 0.225.6, four attempts, from its spawn journal:Three complete turns, three different sandboxes, every one at
turn:0. Receipt and journal: discovery-lab#767.The provider is not the limitation.
@tangle-network/agent-provider-tangledeclaresretainedControl, andenvironment-provider.ts:1197takes the retained path when it is present. The retained path still creates, because the key it creates under is new.Why this matters beyond one run
In the pursuit that produced this run, every one of its 595 knowledge pages came from a bridge-placed root, which keeps its session across turns. A fleet-placed root has produced zero pages across fourteen presses. Each of those presses was previously attributed to an infrastructure failure; this is the structural reason underneath.
The failure is also invisible from the outside. The run does not error. It completes turns, spends tokens, and settles
no-winner, which reads as a research result rather than a lost session.What a fix has to decide
Either:
defaultUnmetContractSteermust carry forward what the previous turn did, and the doc comments claiming the same session should be corrected.Option 1 looks right to me because the retained-control machinery already exists and the bridge path already behaves this way, but the choice belongs to this repo.
Adjacent, same root
repromptOnUnmetwith a provider backend also multiplies environments: three turns created three sandboxes. Under any per-account concurrency limit each re-prompt competes for a slot with its own predecessors' teardown.