Skip to content

feat(web): hide subagent threads from user-facing thread lists (5/5) - #4664

Draft
shivamhwp wants to merge 1 commit into
subagent-obs/04-agents-panelfrom
subagent-obs/05-thread-visibility
Draft

feat(web): hide subagent threads from user-facing thread lists (5/5)#4664
shivamhwp wants to merge 1 commit into
subagent-obs/04-agents-panelfrom
subagent-obs/05-thread-visibility

Conversation

@shivamhwp

@shivamhwp shivamhwp commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Last of five stacked PRs replacing #4551. Stacked on #4663 — review that first.

A subagent's child thread is an implementation detail of the agent that owns it, not a conversation the user started. Listing them alongside real threads makes the sidebar grow with every delegation.

Filtered at the source — the shell snapshot the server serves — so every client sees the same set rather than each re-deriving it. The web client filters again for locally-held state, and the thread route redirects to the parent if a subagent thread is reached directly.

Mobile is part of the sweep

Found in review, and the reason this isn't a web-only change. Mobile still offered "Open subagent thread" with no redirect to fall back on, so it would have navigated to a thread the client no longer receives. Its relationships banner also needed the same subagent-edge filter web has — those edges derive from the projection rather than from thread shells, so they survive the shell filtering and would have rendered as "Unavailable", and by sorting first could have taken over the banner headline.

The trade-off, stated plainly

A subagent's transcript becomes unreachable. The Agents panel from #4663 shows what an agent did and what it returned, but not its full conversation. That is the intended shape here, and the "Open subagent thread" affordances are removed on both clients rather than left as dead ends — but it is a real capability loss and worth a deliberate decision rather than being smuggled in with a sidebar tidy-up.

Testing

Typecheck clean on server, web, client-runtime. Server 1,685 passing, web 1,500 passing, client-runtime 485 passing. (apps/mobile has 70 pre-existing typecheck errors on the base branch, unchanged by this PR.)

Known, not fixed here

  • The route's redirect-to-parent is unreachable against a server that also filters, because the shell is already absent and the earlier "missing thread" effect wins — a deep link to a subagent thread lands on / rather than the parent. It matters under version skew, so it is kept.
  • entities.ts swaps memoized ref atoms for per-call filter+map. The cost is negligible but the identity stability is not; filtering inside the client-runtime atoms instead would be the better shape.
  • Each shell event on a subagent thread now emits a spurious thread.removed delta, absorbed harmlessly by the reducer.

Note

Hide internal subagent threads from all user-facing thread lists and navigation

  • Adds a new threadVisibility.ts module with isInternalSubagentThread and isUserFacingThread helpers that classify both lineage-subagent and node-owned subagent threads as internal.
  • Filters subagent threads from HTTP and WebSocket shell snapshot responses via a new userFacingShellSnapshot utility in ThreadManagementService.ts.
  • Removes subagent relationship links and open-thread buttons from the sidebar, relationships panel, message timeline, and work log across web and mobile.
  • Redirects direct navigation to an internal subagent thread to its parent thread (or /) in _chat.$environmentId.$threadId.tsx.
  • Risk: findThreadRef now returns nothing for internal subagent thread IDs, which could silently break any code that attempts to look up a subagent thread by ID.
📊 Macroscope summarized 6bc3a8d. 12 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted (Automatic summaries will resume when PR exits draft mode or review begins).

🗂️ Filtered Issues

No issues evaluated.

@coderabbitai

coderabbitai Bot commented Jul 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: b599a79d-8b47-4171-9329-03a6c0abfcfd

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch subagent-obs/05-thread-visibility

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 27, 2026
@shivamhwp
shivamhwp force-pushed the subagent-obs/04-agents-panel branch from 940e8fb to c3a50f8 Compare July 27, 2026 20:20
@shivamhwp
shivamhwp force-pushed the subagent-obs/05-thread-visibility branch from d2ef6c7 to adb1e9b Compare July 27, 2026 20:20
@shivamhwp
shivamhwp force-pushed the subagent-obs/04-agents-panel branch from c3a50f8 to 8c6a796 Compare July 27, 2026 20:52
@shivamhwp
shivamhwp force-pushed the subagent-obs/05-thread-visibility branch from adb1e9b to 39912b0 Compare July 27, 2026 20:52

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

if (relationshipRows.length === 0) {
return null;
}

When a user-facing thread's only relationships are subagent edges, the .filter((relationship) => relationship.edge.kind !== "subagent") call empties relationshipRows, causing the early return null at line 127 to hide the entire panel — including the "Disconnect agent session" menu. So even when canDetach is true, the user cannot stop the provider session from this panel. The canDetach check and its menu are computed before the early return but are never rendered because the return short-circuits first. Consider gating the early return on the absence of both relationship rows and a detachable session, or rendering the session controls independently of the relationship list.

-  if (relationshipRows.length === 0) {
-    return null;
-  }
+  if (relationshipRows.length === 0 && !canDetach) {
+    return null;
+  }
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/components/chat/ThreadRelationshipsControl.tsx around lines 127-129:

When a user-facing thread's only relationships are subagent edges, the `.filter((relationship) => relationship.edge.kind !== "subagent")` call empties `relationshipRows`, causing the early `return null` at line 127 to hide the entire panel — including the "Disconnect agent session" menu. So even when `canDetach` is true, the user cannot stop the provider session from this panel. The `canDetach` check and its menu are computed before the early return but are never rendered because the return short-circuits first. Consider gating the early return on the absence of both relationship rows and a detachable session, or rendering the session controls independently of the relationship list.

@shivamhwp
shivamhwp force-pushed the subagent-obs/04-agents-panel branch from 8c6a796 to 103b937 Compare July 27, 2026 23:03
@shivamhwp
shivamhwp force-pushed the subagent-obs/05-thread-visibility branch from 39912b0 to 6bc3a8d Compare July 27, 2026 23:03
@shivamhwp
shivamhwp force-pushed the subagent-obs/04-agents-panel branch from 103b937 to 31adb36 Compare July 28, 2026 15:31
@shivamhwp
shivamhwp force-pushed the subagent-obs/05-thread-visibility branch from 6bc3a8d to 05fe44c Compare July 28, 2026 15:31
@shivamhwp
shivamhwp force-pushed the subagent-obs/04-agents-panel branch from 31adb36 to b270c47 Compare July 28, 2026 19:27
@shivamhwp
shivamhwp force-pushed the subagent-obs/05-thread-visibility branch from 05fe44c to 7458298 Compare July 28, 2026 19:27
A subagent's child thread is an implementation detail of the agent that
owns it, not a conversation the user started. Listing them alongside real
threads makes the sidebar grow with every delegation.

Filtered at the source — the shell snapshot the server serves — so every
client sees the same set rather than each re-deriving it. The web client
filters again for locally-held state, and the thread route redirects to
the parent if a subagent thread is reached directly.

Mobile is part of the sweep, not left behind. It still offered "Open
subagent thread" and had no redirect to fall back on, so it would have
navigated to a thread the client no longer receives. Its relationships
banner also needed the same subagent-edge filter web has: those edges are
derived from the projection rather than from thread shells, so they
survive the shell filtering and would have rendered as "Unavailable" —
and, sorting first, could have taken over the banner headline.

Trade-off worth stating plainly: a subagent's transcript becomes
unreachable. The Agents panel added in the previous PR shows what an
agent did and what it returned, but not its full conversation. That is
the intended shape here, and the "Open subagent thread" affordances are
removed on both clients rather than left as dead ends.
@shivamhwp
shivamhwp force-pushed the subagent-obs/04-agents-panel branch from b270c47 to daf1a88 Compare July 28, 2026 19:46
@shivamhwp
shivamhwp force-pushed the subagent-obs/05-thread-visibility branch from 7458298 to 4daeac4 Compare July 28, 2026 19:46
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:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant