agentHost: speed up subagent session enrichment (parallel load + memoized reconstruction)#322674
Open
DonJayamanne wants to merge 3 commits into
Open
Conversation
…tion for improved performance
Contributor
There was a problem hiding this comment.
Pull request overview
This PR optimizes subagent session enrichment when reopening agent-host chat sessions by parallelizing child-session hydration on the client and eliminating repeated event-log reconstruction on the backend via memoization. It also adds an optional backend API to eagerly surface subagent child sessions during parent restore so subsequent client lookups hit in-memory state.
Changes:
- Parallelize client-side subagent child-session loads during history enrichment and ensure both session + default-chat channels are hydrated before reading
turns. - Memoize
getEvents()+mapSessionEvents()inCopilotAgentSession, share it across parent/subagent lookups, and invalidate it on session log mutations. - Add optional
IAgent.getSubagentSessions()and eagerly register restored subagent child sessions during parentrestoreSession, with tests covering memoization and eager registration.
Show a summary per file
| File | Description |
|---|---|
| src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentHostSessionHandler.ts | Collect subagent insertions across history, dedupe + parallelize child loads, and wait for both session and default-chat hydration before reading child turns. |
| src/vs/platform/agentHost/node/copilot/copilotAgentSession.ts | Add memoized reconstruction shared across message/subagent lookups, plus getSubagentSessions() for eager child discovery. |
| src/vs/platform/agentHost/node/copilot/copilotAgent.ts | Implement optional getSubagentSessions() for Copilot sessions (skipping peer chats, subagent URIs, and provisional sessions). |
| src/vs/platform/agentHost/node/agentService.ts | During restore, eagerly register subagent child sessions from agent-provided discovery to avoid per-child re-restore work. |
| src/vs/platform/agentHost/common/agentService.ts | Introduce IRestoredSubagentSession and optional IAgent.getSubagentSessions(). |
| src/vs/platform/agentHost/test/node/agentService.test.ts | Add test ensuring parent restore eagerly registers subagent child state. |
| src/vs/platform/agentHost/test/node/copilotAgentSession.test.ts | Add test for memoization across message/subagent lookups and invalidation on log change. |
Copilot's findings
- Files reviewed: 7/7 changed files
- Comments generated: 1
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Opening an agent session that used subagents (a parent agent that spawned helper "child" agents) was slow. To render the transcript, VS Code rebuilds the full conversation and groups each child's inner steps under its parent tool call. That rebuild was slow because:
What changed
agentHostSessionHandlernow collects all subagent insertions across the whole history, dedupes child-state loads via aMap, and loads them in parallel (Promise.all) instead of sequentially.CopilotAgentSessionmemoizes thegetEvents()+mapSessionEvents()result (_getMappedEvents), shared bygetMessages,getSubagentMessages, and the newgetSubagentSessions. The memo is invalidated whenever the persisted event log could change (user message, turn start/end, tool complete, subagent completed/failed, compaction, truncation, snapshot rewind) so it never serves stale turns for an active session.IAgent.getSubagentSessions()+IRestoredSubagentSession. DuringrestoreSession, the dispatcher registers every discovered child session eagerly (reusing B's single reconstruction — no extra event-log reads), so the client's later per-child lookups are instant in-memory hits._loadSubagentStatenow waits for both the child's session summary and its default-chat channel to hydrate before reading. After the multi-chat protocol split,turnslive on the chat channel; awaiting only the session subscription read too early and silently produced zero inner steps.Results
For a real 90-turn / 4-subagent session:
Notes for reviewers
getSubagentSessionsis optional onIAgent; agents without subagents simply omit it.agentService.test.ts) and memoization + invalidation (copilotAgentSession.test.ts).For #320303