Skip to content

ACP: no tool_call session update before request_permission #21783

@codefromthecrypt

Description

@codefromthecrypt

What happened?

In ACP mode, when a tool requires confirmation, runTool() sends session/request_permission but never sends a preceding tool_call session update. The if/else in runTool treats them as mutually exclusive:

  • If confirmationDetails is truthy: sends request_permission only (no tool_call)
  • If confirmationDetails is falsy: sends tool_call only (no request_permission)

After permission is granted, it sends tool_call_update (completed), but the client never saw a tool_call (pending) to associate it with.

This is easiest to reproduce with MCP tools from session/new. Since ACP doesn't pass trust to MCPServerConfig, MCP tools always need confirmation via the policy engine. The debug log shows the expected path:

[MESSAGE_BUS] publish: {"type":"tool-confirmation-request",...}
[PolicyEngine.check] toolCall.name: mcp_lookup_get_code, stringifiedArgs: {}
[PolicyEngine.check] NO MATCH - using default decision: ask_user

But the client only sees:

{"sessionUpdate": "tool_call_update", "status": "completed", "toolCallId": "mcp_lookup_get_code-..."}

No tool_call with status pending or in_progress is ever emitted.

What did you expect to happen?

Per the ACP tool calls spec, the Agent SHOULD report a tool_call session update when the model requests a tool invocation. This should happen before requesting permission, so the client can track the tool call lifecycle:

tool_call (pending) -> request_permission -> tool_call_update (completed)

The fix is to send tool_call in both branches of the if/else, not just the else. Something like:

// Always notify the client about the tool call first
await this.sendUpdate({
  sessionUpdate: 'tool_call',
  toolCallId: callId,
  status: confirmationDetails ? 'pending' : 'in_progress',
  title: invocation.getDescription(),
  content: [],
  locations: invocation.toolLocations(),
  kind: toAcpToolKind(tool.kind),
});

if (confirmationDetails) {
  // then request permission...
}

Note: #14957 shows tool_call with in_progress was being emitted for MCP tools in earlier versions, so this may be a regression from the confirmation refactor.

Client information

Client Information

Built from source, commit 1fd4280.

Platform: macOS (Darwin, aarch64)

Login information

Google account.

Anything else we need to know?

How to validate:

  1. Start gemini in ACP mode with an MCP server via session/new
  2. Prompt to use an MCP tool
  3. Observe: client receives session/request_permission but no preceding tool_call session update
  4. After approval, client receives tool_call_update (completed) with no matching tool_call

Related: #14957 (tool_call title issue, which shows MCP tools were emitting tool_call in earlier versions), #17952 (30s confirmation delay, same code path)

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority/p1Important and should be addressed in the near term.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions