Developers flagged a reproducible issue that should make anyone running background agents pause: Claude Code’s background Opus subagents intermittently stall on their first turn and, instead of producing useful work, emit system-prompt fragments — including text shaped like authorization data — as their only output. It’s labeled a security issue, it has a reproduction, and it’s open. That’s enough to treat it as a real, if intermittent, class of failure, and it generalizes to every agent that spawns autonomous child loops.
Here’s the mental model that matters: a subagent is not a trusted subprocess. It’s an autonomous loop with access to a context window, a toolset, and — too often — the same credentials as its parent. When that loop stalls and dumps its prompt instead of its result, anything that was in context is now in output. Authorization-shaped text leaking is the canary: if the prompt carried a token, a session string, or an internal endpoint, that’s what surfaces.
The fix is structural, not reactive. Three rules:
1. Scope credentials per subagent, not per session. A background agent that only needs to read a repo shouldn’t hold deploy keys. Hand it the narrowest token that completes its task and revoke it when the task ends. If the tooling can’t scope credentials, that’s a gap to close before you scale subagents.
2. Treat subagent output as untrusted. Anything a subagent returns — including error text, logs, and especially “stalled” dumps — should be parsed and sanitized before it touches shared state. Don’t pipe raw subagent output into a context that feeds other agents or into any log that leaves your machine.
3. Separate the system prompt from the working context. The leak happened because authorization-shaped content sat in the same window the subagent could echo. Keep credentials and internal routing data out of the prompt that a stalled loop might surface. Put them in a side channel the model can call, not text it can print.
Detecting a leak before it becomes an incident
The hard part is that a stall echoes silently — there’s no raised error, just output that looks like output. So detection has to be mechanical, not eyeballed. Three cheap signals worth wiring into any subagent runner:
- Hash-and-compare prompt fragments. Your system prompt is finite and known. Tokenize it, take a rolling hash of long spans, and scan subagent output for collisions. A subagent that repeats any locked span of its own prompt is stalling and needs to be killed, not trusted.
- Credential-pattern grep on every output. Before output touches shared state, run it through the same secret-scanning patterns you use in CI —
sk-keys,BEGIN RSA/OPENSSH/PRIVATE KEYblocks,AWS_-prefixed assignments, known UUID session id formats. A failed pattern match is a finding, not a warning. - Disposition log. Track, per subagent run, whether the output ended in a well-formed result or a truncation/stall, so you can spot the failure rate climbing before a specific run matters.
None of these need new tooling. They’re shellable in a few lines, and they convert the “silent” failure into an observable one.
The isolation model, concretely
The principles above map to four boundaries you can actually implement:
- Prompt boundary. Keep the system prompt minimal and credential-free. Anything machine-readable that the agent may need — a token file, a registry address — lives at a path the agent must call to retrieve, not as literal text in the prompt it can echo.
- Tool boundary. Give each subagent a read-only toolset by default. Deploy keys, write handles, and network capabilities are granted per-task and revoked on completion. If the runner can’t revoke, use throwaway tokens that expire by design.
- Output boundary. Treat output as an untrusted artifact. Sanitize, pattern-scan, and verify shape before it reaches git, a log aggregator, or another agent’s context.
- Runtime boundary. Run background agents where a stall cannot touch host state — a disposable sandbox, a container with no inbound credentials, or at minimum a dedicated user with a minimal keyring.
Solo developer vs. team
For solo developers this is a config discipline: separate keys, minimal scopes, sanitized logs. The whole model collapses to one script that creates a scoped credential, runs the subagent against a read-only clone, scans the output for secret patterns, and tears the credential down.
For teams it’s an architecture requirement — the runner becomes infrastructure, with audited credential lifecycles and a redaction layer that gates every subagent result.
Either way, the model is the same: untrusted loop, scoped credentials, isolated prompt. Do that and a leaked fragment is annoying. Skip it and a leaked fragment is an incident. Assume every background agent will, at some point, speak its prompt aloud — and design the boundary so that what it says can’t hurt you.
Ever wonder if Claude gives a better answer than GPT for a specific coding problem? aiFiesta lets you compare 9+ premium models side-by-side in one chat. No more juggling tabs.