Skip to content

fix(server): classify ACP Task tool calls as collab agent tool calls - #8443

Open
NoahLinckeScout wants to merge 1 commit into
pingdotgg:mainfrom
NoahLinckeScout:fix/acp-task-tool-classification
Open

fix(server): classify ACP Task tool calls as collab agent tool calls#8443
NoahLinckeScout wants to merge 1 commit into
pingdotgg:mainfrom
NoahLinckeScout:fix/acp-task-tool-classification

Conversation

@NoahLinckeScout

@NoahLinckeScout NoahLinckeScout commented Aug 27, 2026

Copy link
Copy Markdown

What Changed

canonicalItemTypeFromAcpToolKind in AcpCoreRuntimeEvents.ts (the helper shared by the Cursor and Grok adapters) now recognises Task tool calls and classifies them collab_agent_tool_call instead of falling through to its dynamic_tool_call default.

A Task call is recognised by rawInput._toolName === "task" (case-insensitive) or a title matching /^task:/i. Every other kind is unchanged. One helper plus its single call site, and tests.

Why

A thread on an ACP-backed provider launched several subagents through its Task tool. All of them ran to completion. The timeline showed them as anonymous tool rows, indistinguishable from ordinary tool noise.

The launches are never dropped. Over ACP a Task launch arrives as a plain background tool call:

  • session/updatetool_call / tool_call_update, kind: "other"
  • title: "Task: ..."
  • rawInput: { _toolName: "task" }, rawOutput: { isBackground: true }

canonicalItemTypeFromAcpToolKind keys only off kind, and has no Task branch, so kind: "other" lands in the dynamic_tool_call default.

This is an inconsistency between adapters, not a new policy. Every other adapter already classifies the same work as collab_agent_tool_call:

  • ClaudeAdapter.classifyToolItemTypenormalized === "task" || normalized.includes("agent") || ...
  • OpenCodeAdapternormalized.includes("task") || normalized.includes("agent") || ...
  • CodexAdaptertype.includes("collab")

The shared ACP helper was the only one without it, so Cursor and Grok were the odd ones out. This brings them in line.

Repro: start a thread on an ACP-backed provider (Cursor or Grok), ask it to delegate something via its Task tool, and watch the timeline. Before this change the launches render with the generic tool icon; projection_thread_activities shows tool.completed rows with itemType: dynamic_tool_call and a Task: ... summary.

Known limitation

ACP carries no model, agent type, or subagent prompt for these calls, so per-subagent attribution still is not possible for these providers. The row now at least reports that it was agent work.

UI Changes

No UI code is touched, but the reclassification does change how these rows render, via two existing call sites:

  • MessagesTimeline.tsx:2475 — icon goes from hammer (dynamic_tool_call) to bot (collab_agent_tool_call)
  • MessagesTimeline.logic.ts:413 — group summary kind goes from dynamic-tool to agent-tool

I have not attached before/after screenshots: reproducing the row requires a live Cursor or Grok session that actually delegates through its Task tool, which I could not capture cleanly. The rendering delta above is the whole of the visible change, and it comes entirely from those two existing branches rather than from anything in this diff. Happy to add screenshots if you want them before reviewing.

Tests

Added to the existing AcpCoreRuntimeEvents.test.ts: three Task spellings (both recognizers, plus one with no title) assert collab_agent_tool_call, with negative controls (_toolName: "mcp__x"dynamic_tool_call, kind: "search"web_search) so the new branch cannot swallow unrelated calls.

Verified red/green rather than assuming: with the call site reverted to canonicalItemTypeFromAcpToolKind, the new test fails with expected collab_agent_tool_call, received dynamic_tool_call; with the fix it passes.

Verified locally:

  • vp test run src/provider/acp/AcpCoreRuntimeEvents.test.ts → 4 passed
  • full apps/server suite → 245 files passed, 2816 passed / 10 skipped (baseline on this commit's parent: 245 files, 2815 passed)
  • vp run typecheck → exit 0
  • vp fmt --check → clean; vp lint reports nothing new for the changed files

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes — see the UI Changes section; the rendering delta is described precisely, but I could not capture live screenshots
  • I included a video for animation/interaction changes (n/a)

Note

Low Risk
Narrow classification change in ACP event mapping with targeted tests; no auth, data, or API surface changes.

Overview
ACP-backed providers (Cursor, Grok) were mapping Task subagent launches to dynamic_tool_call because classification only looked at kind: "other". The shared ACP runtime mapper now detects Task calls via rawInput._toolName (case-insensitive "task") or a title matching Task:, and emits collab_agent_tool_call so timeline rows align with Claude/Codex/OpenCode.

makeAcpToolCallEvent uses the new canonicalItemTypeFromAcpToolCall helper instead of kind-only mapping; other tool kinds are unchanged. Tests cover the three Task spellings plus controls so MCP and search tools still map to dynamic_tool_call and web_search.

Reviewed by Cursor Bugbot for commit c5af99e. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Classify ACP Task tool calls as collab_agent_tool_call in makeAcpToolCallEvent

Adds isAcpTaskToolCall to detect Task tool calls by matching rawInput._toolName to task (case-insensitive) or title starting with task:. The new canonicalItemTypeFromAcpToolCall returns collab_agent_tool_call for these calls and falls back to canonicalItemTypeFromAcpToolKind for everything else. makeAcpToolCallEvent now uses this new classifier instead of the kind-only lookup.

  • Risk: ACP other tool calls whose _toolName or title match the Task patterns now emit collab_agent_tool_call instead of dynamic_tool_call; non-matching mcp__ calls and search kind are unchanged.

Macroscope summarized c5af99e.

A thread on an ACP-backed provider that launched subagents via its Task tool
showed zero subagents in the UI. The launches were never dropped: over ACP they
arrive as ordinary background tool calls titled "Task: ..." with
`rawInput._toolName === "task"` and no agent identity on the wire, so
`canonicalItemTypeFromAcpToolKind` filed them under its `dynamic_tool_call`
default. Every consumer that makes delegated work visible keys off
`collab_agent_tool_call`, so the rows sat in the timeline as anonymous tool noise.

The other adapters already classify the same work as `collab_agent_tool_call`
(`ClaudeAdapter.classifyToolItemType`, `OpenCodeAdapter`, `CodexAdapter`), so the
shared ACP helper was the outlier. Recognize the Task spellings there so the ACP
providers get the same classification: `rawInput._toolName === "task"`
(case-insensitive) or a title matching `/^task:/i`. All other kinds are unchanged.

Identity limits remain: ACP carries no model, agent type, or subagent prompt for
these calls, so per-subagent attribution is still not possible. The row now at
least reports that it was agent work.
@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d27851c-e6bc-458a-99cd-a202d44b5daf

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 27, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5af99eea9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +85 to +86
if (isAcpTaskToolCall(toolCall)) {
return "collab_agent_tool_call";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Render reclassified Task calls distinctly on mobile

On the mobile client, this classification still does not expose Task launches as agent work: apps/mobile/src/lib/threadActivity.ts:653-655 maps both dynamic_tool_call and collab_agent_tool_call to the same hammer icon, and a repo-wide search finds no other mobile presentation branch for the collab type. Consequently, Cursor/Grok Task calls remain visually unchanged on mobile even though web now gives them bot styling and agent grouping; update the mobile derivation and its focused tests to render this type as agent work too.

AGENTS.md reference: AGENTS.md:L67-L70

Useful? React with 👍 / 👎.

@macroscopeapp

macroscopeapp Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This is a narrow ACP classification fix that preserves execution and schema behavior while changing existing timeline presentation for Task calls. An unresolved review comment identifies that mobile still renders the new agent classification like a generic tool, leaving a customer-facing behavior gap to resolve or explicitly accept.

You can add or adjust custom eligibility rules. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant