You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(agents): hand the conversation over when switching agents - #156
Until now AgentSession.setAgent() (and /agent in genaicode chat / ui) started the next agent with no context. Now it hands the conversation over.
What changes
Recap + transcript file. The next agent's first prompt starts with a short recap of the turns it missed (user prompts + final answers, ~4k chars, newest kept) and the path of a full Markdown transcript (tool calls with input/output, changed files, approvals, errors) written to .genaicode/handoff/<time>-<agent>.md in the cwd. That dir gets a *.gitignore. The file lives in the cwd, so sandboxed agents can read it.
Switch back resumes. The session remembers each agent's own session id and the last turn it knows. Switching back resumes that session (when capabilities.resume) and only tells it what the others did in between.
Failed first turn. If the agent's first turn fails without a session, the handoff is kept for the next turn.
Mid-turn switch. The running turn finishes with the agent that started it; its session id is stored for that agent, not the new one.
Opt out.createAgentSession({ handoff: false }), setAgent(agent, { handoff: false }), /agent codex --fresh. handoff: { dir } moves the files. reset() forgets every agent session, with no handoff.
SessionTurn.handoff = { turns, agents, file? } records what a turn was told.
genaicode/app-agent is unchanged: it creates a new session per agent/mode and already carries an inline transcript (carryOver).
Tests
npm run lint, tsc --noEmit, npm test (449 passed). New session tests: handoff contents and file, switch-back resume with only the missed turns, kept handoff after a failed turn, opt-out.
setAgent() now gives the next agent a recap of the turns it missed and
the path of a full Markdown transcript in .genaicode/handoff/. Switching
back to an agent resumes its own session and tells it only what it
missed. Opt out with { handoff: false } or /agent name --fresh.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019xAEPKxUieg5MJ6Y8AEsnC
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The release note is missing from the root changelog, causing the release guard to fail, and unresolved session-resume, fresh-reset, and transcript-truncation defects remain.
This PR adds conversation handoff to agent switching in the session library and chat front ends, allowing agents to receive prior context and resume their own sessions.
Changes:
Adds recap generation, Markdown transcripts, and per-agent session tracking.
Adds handoff opt-outs, including /agent name --fresh.
Adds session tests, command-parsing coverage, and documentation.
File
Description
src/ui/ui.test.tsx
Tests parsing of the --fresh option.
src/ui/format.ts
Adds --fresh parsing and updates command help.
src/ui/controller.ts
Passes handoff preferences through agent selection.
src/agents/session.ts
Tracks per-agent sessions and prepares handoffs.
src/agents/session.test.ts
Tests handoff contents, resume, retry, and opt-out behavior.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
A critical mid-turn race can execute the wrong agent and cache its session under another agent, while resume and handoff defects can lose or misattribute conversation history.
Prevent transcript filename collisions from overwriting handoffs
src/agents/handoff.ts:42
Two handoffs to the same agent in the same cwd within one millisecond produce the same filename, and writeFileSync() overwrites the first transcript. The first agent's prompt can therefore point to another conversation's contents. Use unique filenames with exclusive creation and retry on collisions so each handoff keeps its own transcript.
Include the final result text in the recap and transcript
src/agents/handoff.ts:92
When a CodingAgent supplies its final answer only in AgentResult.text, the recap reports (no answer) or an earlier message, and the transcript also omits that final answer. Prefer turn.result.text in the recap, falling back to the last text entry; also include it in handoffTranscript when no text entry already contains it (same issue at lines 52–80).
Seed the per-agent cache with the supplied resume session
src/agents/session.ts:174
The per-agent cache starts empty even when options.resume supplies an existing session. Creating a session for A with a resume ID, switching to B before A's first turn, and then switching back to A loses that ID: setAgent() clears explicitResume, and the cache has no entry for A. Initialize A's cached session from options.resume with upTo: 0 so switching back resumes it and hands over B's turns.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Handoff transcripts can expose credentials through world-readable permissions, omit failure reasons, and reintroduce reset-discarded context after an agent switch.
No open issues 🎉
3 previously missed issues
In code that hasn't changed since last review
Create transcript files with restrictive permissions
src/agents/handoff.ts:43
With a standard 022 umask, this creates a 0644 transcript in 0755 directories. In a workspace accessible to other local users, that exposes the automatically persisted prompts and tool inputs/outputs, which can contain credentials; .gitignore does not restrict filesystem reads. Create the transcript with mode 0o600 so handing off does not make this conversation data world-readable.
Include recorded failure details in the transcript
src/agents/handoff.ts:86
Failures such as a missing CLI, a timeout, or a stderr-only error are recorded by RunRecorder.finish() in result.error, without a corresponding error entry. This currently writes only the failed status, so the next agent cannot recover the failure reason even by reading the transcript. Include result.error, avoiding duplication when an error entry already contains it.
Keep pre-reset turns out of subsequent agent handoffs
src/agents/session.ts:557
After a completed turn, calling reset(), setAgent(other), then send() includes the pre-reset conversation in the next prompt and transcript because switching sets missedAfter back to 0. This lets context discarded by /new return on a later agent switch. Record a reset cutoff and exclude earlier turns from subsequent handoffs while retaining them in the visible transcript.
Handoff now hooks into switchAgent, so failover switches carry the
earlier conversation too; failed attempts stay out of the recap.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019xAEPKxUieg5MJ6Y8AEsnC
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Generated transcripts may remain eligible for commit and expose credentials, while excluding historical failed-over turns loses instructions needed for later handoffs.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Human assessment is needed because an unpublished finding indicates that overriding ignore-rule negations could leave credential-bearing handoff transcripts eligible for commit.
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
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.
Requested by Grzegorz · project thread
Until now
AgentSession.setAgent()(and/agentingenaicode chat/ui) started the next agent with no context. Now it hands the conversation over.What changes
.genaicode/handoff/<time>-<agent>.mdin the cwd. That dir gets a*.gitignore. The file lives in the cwd, so sandboxed agents can read it.capabilities.resume) and only tells it what the others did in between.createAgentSession({ handoff: false }),setAgent(agent, { handoff: false }),/agent codex --fresh.handoff: { dir }moves the files.reset()forgets every agent session, with no handoff.SessionTurn.handoff={ turns, agents, file? }records what a turn was told.genaicode/app-agentis unchanged: it creates a new session per agent/mode and already carries an inline transcript (carryOver).Tests
npm run lint,tsc --noEmit,npm test(449 passed). New session tests: handoff contents and file, switch-back resume with only the missed turns, kept handoff after a failed turn, opt-out.Generated by Claude Code