Parallel tool calls that both hit an ask permission rule leave one prompt invisible and the turn hanging #12

Closed
opened 2026-10-15 16:39:29 +02:00 by omp-deck · 0 comments
Collaborator

Observed

In a chat session the agent issued two bash calls in the same turn, running in parallel: bun test src/prompts/system-prompt.test.ts and bun run typecheck. The typecheck finished in about 7 s. The test call didn't run: the turn appeared stuck for about 6 minutes until the user cancelled, and the tool result was Tool call denied … Permission request cancelled. On retry, the same command, issued on its own, passed in 1.6 s.

Likely cause (from the code, sequence not reproduced)

The server supports several pending prompts per session, but the web client keeps only one:

  • apps/server/src/bridge/permission-filter.ts: pending / pendingFrames are Maps keyed by toolCallId, so each concurrent call gets its own pending prompt and waits for a tool_permission_response for that exact toolCallId.
  • apps/server/src/bridge/permission-filter.ts getPendingFrame() returns only the first pending frame for the session snapshot.
  • apps/web/src/lib/store.ts: pendingPermissionPrompts is Record<sessionId, frame>. A second tool_permission_prompt frame for the same session overwrites the first (case "tool_permission_prompt"), and respondToPermission deletes the session's entry after answering one.
  • apps/web/src/components/chat/ToolPermissionDialog.tsx renders pendingPermissionPrompts[activeId], so at most one dialog is shown.

Result: when two calls hit an ask rule at the same time, one prompt is never shown. Its tool call blocks until the turn is aborted. This also happens after a reload, because the snapshot carries only one frame.

Expected

Every pending permission prompt is visible and answerable: queued one after another, or shown together. Answering one must not drop the others, and a reload must restore all of them.

Acceptance

  • Two parallel tool calls that both match an ask rule produce two answerable prompts. Approving or denying each one resolves its own call.
  • Reloading the page while both are pending shows both again.
## Observed In a chat session the agent issued two `bash` calls in the same turn, running in parallel: `bun test src/prompts/system-prompt.test.ts` and `bun run typecheck`. The typecheck finished in about 7 s. The test call didn't run: the turn appeared stuck for about 6 minutes until the user cancelled, and the tool result was `Tool call denied … Permission request cancelled`. On retry, the same command, issued on its own, passed in 1.6 s. ## Likely cause (from the code, sequence not reproduced) The server supports several pending prompts per session, but the web client keeps only one: - `apps/server/src/bridge/permission-filter.ts`: `pending` / `pendingFrames` are `Map`s keyed by `toolCallId`, so each concurrent call gets its own pending prompt and waits for a `tool_permission_response` for that exact `toolCallId`. - `apps/server/src/bridge/permission-filter.ts` `getPendingFrame()` returns only the first pending frame for the session snapshot. - `apps/web/src/lib/store.ts`: `pendingPermissionPrompts` is `Record<sessionId, frame>`. A second `tool_permission_prompt` frame for the same session overwrites the first (`case "tool_permission_prompt"`), and `respondToPermission` deletes the session's entry after answering one. - `apps/web/src/components/chat/ToolPermissionDialog.tsx` renders `pendingPermissionPrompts[activeId]`, so at most one dialog is shown. Result: when two calls hit an `ask` rule at the same time, one prompt is never shown. Its tool call blocks until the turn is aborted. This also happens after a reload, because the snapshot carries only one frame. ## Expected Every pending permission prompt is visible and answerable: queued one after another, or shown together. Answering one must not drop the others, and a reload must restore all of them. ## Acceptance - Two parallel tool calls that both match an `ask` rule produce two answerable prompts. Approving or denying each one resolves its own call. - Reloading the page while both are pending shows both again.
lucas closed this issue 2026-10-15 17:36:35 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
lucas/omp-deck#12
No description provided.