Skip to content

fix(cursor): show Task subagents in the Agents panel - #13906

Closed
p000 wants to merge 1 commit into
pingdotgg:mainfrom
p000:fix/cursor-task-subagents
Closed

p000 wants to merge 1 commit into
pingdotgg:mainfrom
p000:fix/cursor-task-subagents

Conversation

@p000

@p000 p000 commented Sep 27, 2026 •

Copy link
Copy Markdown

Summary

  • Cursor ACP reports a subagent as an ordinary tool call (rawInput._toolName === "task", title Task: …). Those calls were stored as dynamic_tool_call items, so the Agents panel stayed empty.
  • The Cursor adapter now projects that tool onto task.started / task.progress / task.completed with taskType: "local_agent". Existing ingestion stamps agentKind: "agent", which fills the Agents roster and keeps the thread working until the task finishes.
  • A string subagentType becomes the row role. The object form Cursor sends when the type is unspecified ({unspecified: {}}) is ignored.

Closes #14006

Closes discussions

Not in this change

Child tool calls inside the subagent are not tagged with a parent id on the ACP wire, so they still appear on the parent transcript. Nested sidebar threads stay Codex-only.

Test plan

  • vp test run src/provider/acp/CursorSubagents.test.ts
  • In a Cursor thread, launch a Task subagent and confirm one Agents-panel row moves pending → running → completed, and the thread stays working until that row completes.

Made with Cursor

Summary by CodeRabbit

  • New Features
    • Cursor subagent tasks now report when they start, make progress, and finish, including when they fail. Task updates include the subagent’s role when available, and tasks that finish immediately still show both their start and final status. Ordinary tool activity is not presented as subagent task progress.

Cursor reports each subagent as a tool named task. Project that lifecycle onto task.* so the roster and background liveness can see it.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 27, 2026
title,
...(role ? { role } : {}),
};
input.tasks.set(input.toolCall.toolCallId, { title, ...(role ? { role } : {}), phase });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Medium acp/CursorSubagents.ts:89

Terminal tasks remain in input.tasks for the lifetime of the session, so every completed or failed Cursor Task permanently retains its title and role and ctx.subagents grows without bound as subagents accumulate. Evict terminal entries after suppressing duplicate updates, while preserving any separate deduplication state needed for late tool-call updates.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/acp/CursorSubagents.ts around line 89:

Terminal tasks remain in `input.tasks` for the lifetime of the session, so every completed or failed Cursor Task permanently retains its title and role and `ctx.subagents` grows without bound as subagents accumulate. Evict terminal entries after suppressing duplicate updates, while preserving any separate deduplication state needed for late tool-call updates.

@macroscopeapp

macroscopeapp Bot commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a focused Cursor adapter bug fix that maps existing Task tool lifecycles into the established Agents-panel event stream, with localized production changes and unit coverage. An unresolved Medium finding notes that terminal task records remain retained for the session lifetime, creating a bounded memory-retention risk that should be addressed separately.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: pingdotgg/t3code/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 8fde73bc-2c2e-4e9d-b921-19cdcb60c844

📥 Commits

Reviewing files that changed from the base of the PR and between c9a0e8a and 7687f51.

📒 Files selected for processing (3)
  • apps/server/src/provider/Layers/CursorAdapter.ts
  • apps/server/src/provider/acp/CursorSubagents.test.ts
  • apps/server/src/provider/acp/CursorSubagents.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Cursor task tool calls now produce lifecycle events for start, progress, and completion. The Cursor adapter tracks subagent state per session and publishes projected events with provider, thread, turn, and timestamp data.

Changes

Cursor subagent task events

Layer / File(s) Summary
Task detection and lifecycle projection
apps/server/src/provider/acp/CursorSubagents.ts, apps/server/src/provider/acp/CursorSubagents.test.ts
Detects task tools and projects start, progress, and completion events from tool-call state. Tests cover ordinary tools, role and status data, and an initially failed task.
Cursor adapter integration
apps/server/src/provider/Layers/CursorAdapter.ts
Tracks subagent records per session. After each ACP tool-call event, publishes projected task events with runtime identifiers and timestamps.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant ACP
  participant CursorAdapterLive
  participant cursorSubagentTaskEvents
  participant RuntimeEventStream
  ACP->>CursorAdapterLive: tool-call update
  CursorAdapterLive->>cursorSubagentTaskEvents: project task events
  cursorSubagentTaskEvents-->>CursorAdapterLive: task lifecycle events
  CursorAdapterLive->>RuntimeEventStream: publish stamped events
Loading

Merge Risk: ⚪ Minimal · up to 7687f

No actionable issue is established for the Cursor subagent lifecycle change; it is ready for normal merge checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 7687f

The new task tracking is limited to a Cursor session and does not appear to grant an agent new execution authority. One lifecycle identity edge case could cause a later task to be missed; provider ID guarantees and interruption behavior remain unverified.

Retained concerns

  • Low · reliability · inferred: A terminal task record suppresses every subsequent event with the same tool-call ID for the life of the session. If Cursor reuses an ID in a later turn, the upstream tracker can accept the new call while the new task projection omits its lifecycle, weakening task-state failure containment. Cursor's ID uniqueness guarantee is not established.
Security review details

Security Blast Radius

  • inferred — The observed new classification path is bounded by the owning Cursor session's event stream and thread ID. Evidence does not establish a new cross-session lookup, credential path, or tool-execution authority.

Trust Boundaries and Controls

  • observed — Only raw input whose tool name normalizes to task enters the projection. The ordinary tool-call event is still published first, and ingestion subsequently stamps the projected task's agent classification for clients.

Resilience and Maintainability Implications

  • inferred — The projector advances its in-memory phase before task-event publication. The inspected notification path logs processing errors without an observed restart; whether publication can fail in production or interruption leaves externally inconsistent task state remains unresolved.

Hardening Proposals

  • proposed — Establish Cursor's tool-call ID lifetime and cancellation contract, then align projector identity and terminal cleanup with those guarantees. Check whether interrupted publication requires task-state reconciliation.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the primary change: displaying Cursor Task subagents in the Agents panel.
Description check ✅ Passed The description explains the problem, implementation, scope limits, issue references, and automated test result. It does not use the template headings exactly and leaves the manual Agents-panel valida…
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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

kvnloo commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

One useful follow-up connection: this Task -> task.* projection is also the main missing behavior I found when comparing the old OMP provider (#9038) with current generic ACP in Orchestrator V2.

Generic ACP V2 already covers OMP's model/config discovery, modes/plan, permissions, commands, usage, MCP, resume/load, attachments, and rollback-by-new-session. What it does not generically express is “this ordinary ACP tool call represents a subagent.” #9038 had an OMP-specific parser for its task tool and emitted the same task.started / task.completed stream.

No need to widen this Cursor fix. But after this lands, it may be worth extracting the event-projection shape into a small ACP helper/hook so Cursor, OMP, and future ACP agents can supply only their tool-identity/parser logic instead of rebuilding Agents-panel lifecycle projection per provider.

Copy link
Copy Markdown
Member

Note

This comment is posted by Julius' dot

#14006 shows a Task call reporting completed with isBackground: true while its child is still running. This mapper treats that status as child completion. Which later event establishes that the child actually finished? Please provide the representative Cursor trace and a focused regression for that distinction under the verification rule. Leaving this open pending that explanation.

@juliusmarminge

Copy link
Copy Markdown
Member

Thanks for working on this. We merged the orchestrator V2 rewrite in #2829, and we are closing this PR as part of that transition.

This change touches CursorAdapter.ts, which the V2 merge removed. Cursor now runs through the SDK-based CursorAdapterV2 instead of the V1 ACP adapter.

Sorry for the extra work this creates. If the change is still needed on V2, please rebuild it on current main, verify it there, and open a new PR linking back here. We're closing the current implementation without assuming the underlying request is resolved.

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

Labels

size:L 100-499 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.

[Bug]: Cursor Agent subagents disappear into the ether after being spawned

3 participants