diff --git a/src/runtime/retained-run-binding.ts b/src/runtime/retained-run-binding.ts index 7d60fff1..d79a5709 100644 --- a/src/runtime/retained-run-binding.ts +++ b/src/runtime/retained-run-binding.ts @@ -99,13 +99,14 @@ export function assertInteractionBinding( controlRef: AgentExactRunControlRef, command: InteractionResponseCommand, ): void { + // This digest identifies the interaction request, not the retained turn. + // The provider validates it against its durable interaction record. if ( command.binding.runId !== controlRef.runId || command.binding.provider !== controlRef.provider || command.binding.environmentId !== controlRef.environmentId || command.binding.sessionId !== controlRef.sessionId || - command.binding.executionId !== controlRef.executionId || - command.binding.requestDigest !== controlRef.requestDigest + command.binding.executionId !== controlRef.executionId ) { throw new Error('interaction response command does not target this retained run') } diff --git a/tests/helpers/retained-run-child.ts b/tests/helpers/retained-run-child.ts index 4e17e2eb..a70a8edb 100644 --- a/tests/helpers/retained-run-child.ts +++ b/tests/helpers/retained-run-child.ts @@ -104,6 +104,13 @@ if (phase === 'start') { const events = [] for await (const event of run.events({ after: reference.after })) events.push(event) const statusBefore = await run.status() + const interactionEvent = events.find((event) => event.event.type === 'interaction')?.event + if (interactionEvent?.type !== 'interaction') { + throw new Error('retained provider replayed no interaction request') + } + if (interactionEvent.request.requestDigest === run.controlRef.requestDigest) { + throw new Error('interaction request digest unexpectedly matched the retained turn digest') + } const interactionBinding = { runId: run.controlRef.runId, provider: run.controlRef.provider, @@ -111,7 +118,7 @@ if (phase === 'start') { sessionId: run.controlRef.sessionId, executionId: run.controlRef.executionId, interactionId: 'interaction-1', - requestDigest: run.controlRef.requestDigest, + requestDigest: interactionEvent.request.requestDigest, } const interactionResponse = { id: 'interaction-1', outcome: 'accepted' as const } const interaction = await run.respondToInteraction({