Rejecting a foreground Agent tool call does not prevent the subagent from running and writing files
Summary
Rejecting an Agent tool call returns this to the parent agent:
The user doesn't want to proceed with this tool use. The tool use was rejected
(eg. if it was a file edit, the new_string was NOT written)
But the subagent had already spawned and already written 22 files to the working tree. The rejection killed it ~13 minutes later, before it reported back, so the parent never learned the files existed. They surfaced later as unexplained modifications to the repo.
Timeline
Reconstructed from the session's own subagent transcript (subagents/agent-<id>.jsonl):
| Time | Event |
|---|---|
| 10:40:14 | Subagent spawned (transcript's first message is the parent's prompt verbatim) |
| 10:50–10:51 | Subagent writes 22 files (mtimes on disk) |
| 10:53:07 | [Request interrupted by user for tool use] delivered to the subagent |
The user rejected the call shortly after it was issued; the interrupt reached the subagent only after it had done ~10 minutes of work and mutated the filesystem.
Impact
The parent is told no changes were made while the filesystem was mutated. Consequences:
- The parent may commit, or reason over, changes it did not make and cannot account for.
- The subagent is killed before reporting, so its work is orphaned — no summary, no validation results, no record of what it touched.
- In our case this produced a real provenance scare mid-code-review: unexplained modifications appeared in a worktree during a release gate, and we had to rule out other sessions and the user before tracing it to the rejected call.
The message asserting the new_string was NOT written is the specific problem — it is stated unconditionally and was false here, so an agent that trusts it will not go looking.
Expected behavior
Any of:
- Make the rejection message conditional on whether the subagent actually ran and touched anything.
- Surface partial work on interrupt: "subagent modified N files before being stopped", ideally with the paths.
- Kill the subagent before it can act, if preventing the work is the intent of rejection.
(1) or (2) seem clearly right — (3) may be impractical given the spawn is already in flight, but then the messaging must reflect it.
Environment
- Version 2.1.219
- Entrypoint: claude-desktop
- Foreground
Agentcall (run_in_background: false)