Inherit user-attached files in sub-agent sessions#2532
Merged
dgageot merged 4 commits intodocker:mainfrom Apr 27, 2026
Merged
Conversation
Sub-agents created via transfer_task receive only the task string; they have no access to the parent's conversation history or to the files the user attached. When the parent passes a bare filename like "something.go", the sub-agent has to scan the workspace and may pick the wrong file when several share the same name. Update both system prompts to make this contract explicit: * Parent agents are told to always include absolute paths in the task description and reminded that sub-agents do not see attached files. * Sub-agents are told to treat absolute paths in <task> as authoritative and to ask for an absolute path (rather than guess) when a file is referenced by name only. The matching e2e cassettes are updated so the prompt change still replays. Assisted-By: docker-agent
When the user attaches files via @-mentions or /attach, only the root agent sees them - the file content is inlined into the parent's user message. When that agent delegates work via transfer_task, the sub-agent starts in a fresh session and has no record of which files the user originally attached, so a bare filename in the task description forces the sub-agent to scan the workspace and risks picking the wrong file when several share the same name. Track attached files explicitly on the session and inherit them in sub-sessions: * session.Session gains an AttachedFiles []string field plus AddAttachedFile, AttachedFilesSnapshot, and a WithAttachedFiles option. Paths are deduplicated and order-preserved. * The TUI App.Run path and the CLI PrepareUserMessage / CreateUserMessageWithAttachment helpers register every successfully attached file's absolute path on the session. * runtime.newSubSession copies the parent's AttachedFiles into the child and surfaces them in the task system prompt under <attached_files>, so the sub-agent has the absolute paths up-front. * branch.go and the in-memory store preserve AttachedFiles when copying session metadata. AttachedFiles is in-memory only (not persisted in SQLite) since the use case is delegating within an active session; reloaded sessions can re-attach as needed and would otherwise require a schema migration. Assisted-By: docker-agent
Pure cleanup, no behaviour change: * buildTaskSystemMessage now uses a single strings.Builder throughout instead of mixing string concatenation with a one-off builder for the attached_files block. * CreateUserMessageWithAttachment introduces a noAttachment closure so the seven best-effort fallback paths share one return statement instead of repeating session.UserMessage(userContent), "" everywhere. * branch.go drops a redundant cloneStringSlice on the result of AttachedFilesSnapshot, which already returns an independent copy. * The over-eager three-line comments at the AddAttachedFile call sites and on top of newSubSession are replaced with a single line each that states the contract. Assisted-By: docker-agent
Two correctness fixes uncovered while reviewing the AttachedFiles plumbing: 1. App.Run was recording att.FilePath on the session before processFileAttachment had a chance to verify the file existed or was a regular file. A user typing @some/missing/path or @some/directory in the editor would silently propagate that broken reference to every sub-agent created in the rest of the session. processFileAttachment now returns a bool meaning "the path resolves to a real, regular file we attempted to surface" and App.Run only records on true. Content-handling failures (too large to inline, unsupported MIME, transient read errors) still record the path because a sub-agent may have larger limits or different tools than the parent. 2. AddAttachedFile is documented as taking an absolute path but accepted any string. A buggy caller could leak a relative path into the sub-agent's system prompt, where it would be ambiguous. Add a filepath.IsAbs guard that silently drops non-absolute paths (with a debug log) and update the doc comment. Also clarify the Session.AttachedFiles field comment to mention all three entry points (editor @-mention, /attach directive, --attach CLI flag) and extend TestAddAttachedFile / TestWithAttachedFiles to cover the new validation. Assisted-By: docker-agent
gtardif
approved these changes
Apr 27, 2026
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.
Problem
When a user attaches a file via
@-mentionin their initial prompt, only the root agent sees the file content (it's inlined into the user message). When that agent then delegates work viatransfer_task, the sub-agent starts in a fresh session with no record of which files the user originally attached. If the parent's task description says "editsomething.go" instead of "edit/abs/path/something.go", the sub-agent must scan the workspace, often picks the wrong file when several share the same name, and burns tokens doing it.This was reported as a frequent pain point when working with multi-agent teams. See: user feedback in the issue.
Approach
Two complementary changes — one prompt-only, one structural:
A. Prompt guidance (LLM-side reminder)
task; sub-agents do not see the conversation history or attached files.<task>as authoritative; if a referenced file is given by name only, do not guess — search the workspace or ask the calling agent.This catches the case where the parent agent itself discovers a new file mid-flight (i.e. files that were never attached by the user).
C. Inherit attached files in sub-sessions (deterministic)
Session.AttachedFiles []stringfield withAddAttachedFile,AttachedFilesSnapshot, and aWithAttachedFilesoption (deduplicated, order-preserved).App.Runpath and the CLIPrepareUserMessage/CreateUserMessageWithAttachmenthelpers register every successfully attached file's absolute path on the session.runtime.newSubSessionsnapshots the parent'sAttachedFiles, propagates them to the child viaWithAttachedFiles, and surfaces them in the task system prompt under<attached_files>. Sub-sub-sessions inherit too because the child becomes the next parent.branch.goand the in-memory store preserveAttachedFileswhen copying session metadata.This is the structural fix that doesn't trust the LLM to remember.
Why both?
@AttachedFilesCommits
a896bc03dEncourage absolute file paths when delegating to sub-agents — prompt-only change inpkg/session/session.go(parent prompt) andpkg/runtime/agent_delegation.go(sub-agent prompt). E2E cassettes (TestA2AServer_MultiAgent,TestRuntime_MultiAgent_SessionReload) updated to match.359b8f6a8Propagate user-attached files to sub-agent sessions — adds theAttachedFilesplumbing (session field + helpers, TUI/CLI registration, sub-session inheritance, system-prompt surfacing). New tests inpkg/session/session_options_test.goandpkg/runtime/agent_delegation_test.go.86641e4feTidy up the AttachedFiles plumbing — pure refactor, no behaviour change. Singlestrings.BuilderinbuildTaskSystemMessage,noAttachmentclosure to collapse seven duplicated returns inCreateUserMessageWithAttachment, drops a double clone inbranch.go, trims over-eager comments.22e40848eReject dangling and non-absolute paths inAttachedFiles— review fixes:App.Runrecordedatt.FilePathbeforeprocessFileAttachmentvalidated it, so paths to missing files or directories silently propagated to sub-agents.processFileAttachmentnow returns a bool ("the path resolved to a real, regular file") andApp.Runonly records ontrue. Content-handling failures (too large to inline, unsupported MIME, transient read errors) still record because a sub-agent may have larger limits or different tools than the parent.AddAttachedFile's parameter is namedabsPathand the docstring claims absolute, but the function accepted any string. Added afilepath.IsAbsguard with aslog.Debugfor visibility.Session.AttachedFilesfield comment now mentions all three entry points (@-mention,/attach,--attach).Tests
mise test✅ all greenmise lint✅ green (golangci-lint run: 0 issues, customlint .: 778 files, no offenses,go mod tidy --diff: clean)TestAddAttachedFile(dedup, empty, non-absolute, snapshot independence),TestWithAttachedFiles,TestSubSessionInheritsAttachedFiles,TestSubSessionWithoutAttachedFilesOmitsBlock, plus expanded cases inTestBuildTaskSystemMessage.What's intentionally not changed
GET /sessionsandGET /sessions/:iduse curated DTOs (api.SessionsResponse,api.SessionResponse) that don't includeAttachedFiles.POST /sessionsechoes a freshly-created session where the field is empty. Same exposure surface as the pre-existingCustomModelsUsed.AttachedFilesis not literal@-resolution by sub-agents. That would reproduce an editor concern in the runtime and doesn't help when the parent drops the@entirely (the actual reported failure mode).