Skip to content

feat(agents): hand the conversation over when switching agents - #156

Merged
gtanczyk merged 7 commits into
masterfrom
claude/project-thread-3f2047
Nov 7, 2026
Merged

gtanczyk merged 7 commits into
masterfrom
claude/project-thread-3f2047

Conversation

@gtanczyk

@gtanczyk gtanczyk commented Nov 7, 2026

Copy link
Copy Markdown
Owner

Requested by Grzegorz · project thread

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.


Generated by Claude Code

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
@gtanczyk
gtanczyk requested a balanced review from Copilot November 7, 2026 14:56
@gtanczyk gtanczyk self-assigned this Nov 7, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review ✅ Completed 2026-11-07T15:03:09.457028Z 6d0edef PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019xAEPKxUieg5MJ6Y8AEsnC

Copilot AI left a comment

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.

🟡 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.

4 open issues
What changed in this PR

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.
src/​agents/​handoff.ts Generates recaps and writes Markdown transcripts.
docs/​cli.md Documents agent switching and --fresh.
docs/​CHANGELOG.md Adds a feature announcement.
docs/​agents.md Documents handoff options and session behavior.

Review effort: Balanced

Comment thread src/agents/handoff.ts Resolved
Comment thread src/agents/session.ts Resolved
Comment thread src/agents/session.ts Resolved
Comment thread src/ui/controller.ts Resolved
… full tool data in handoff

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019xAEPKxUieg5MJ6Y8AEsnC

Copilot AI left a comment

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.

🟡 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.

1 open issue
3 previously missed issues

In code that hasn't changed since last review

Medium severity 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.

Medium severity 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).

Medium severity 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.

4 resolved since last review

Review effort: Balanced

Comment thread src/agents/session.ts Resolved
…ff files, final result text

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019xAEPKxUieg5MJ6Y8AEsnC

Copilot AI left a comment

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.

🔵 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

High severity 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.

Medium severity 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.

Medium severity 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.

1 resolved since last review

Review effort: Balanced

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
…reset cutoff for handoffs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019xAEPKxUieg5MJ6Y8AEsnC

Copilot AI left a comment

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.

🟡 Changes recommended

Generated transcripts may remain eligible for commit and expose credentials, while excluding historical failed-over turns loses instructions needed for later handoffs.

2 open issues

Review effort: Balanced

Comment thread src/agents/handoff.ts Resolved
Comment thread src/agents/session.ts Resolved
…e; keep earlier failed-over turns in handoffs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019xAEPKxUieg5MJ6Y8AEsnC

Copilot AI left a comment

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.

🔵 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.

No open issues 🎉

2 resolved since last review

Review effort: Balanced

@gtanczyk
gtanczyk merged commit 86082c2 into master Nov 7, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants