Every minion accounted for

Checked 22 Sep 2026 · By Luke Czak

ArticleHow to Use AIFree to read

Orphaned agent processes burn quota and CPU for days and lose work. Session teardown means enumerating live workers from the system, never trusting what memory says should be running.

Every worker an orchestrating session launches, a background CLI, a terminal pane running a coding agent, a headless process kicked off to handle one slice of a task, is a thing that has to end somewhere, and somewhere has to be a state I can actually verify, not a state I remember deciding on. The trap is treating the orchestrator’s own memory of what it launched as the source of truth about what is still running. That memory is a plan, not an observation, and the two drift apart more often than seems reasonable.

A worker can outlive the session that spawned it in several ordinary ways. A pane gets closed without confirming the process inside it actually exited. A background job finishes its assigned task but the loop that was supposed to notice completion and tear it down never fires. A crash in the orchestrator leaves every child process it started running exactly as before, because nothing about a parent dying automatically kills processes it did not explicitly bind its own lifetime to. None of these require anything going dramatically wrong, they are the default outcome of not checking, not the result of a rare edge case.

The cost of an orphan is not abstract. A live agent process left running keeps consuming whatever quota its account is metered on, for as long as it keeps working or polling, whether or not anyone is watching it or benefiting from the output. It holds CPU and memory on the machine it is running on. If it has a working tree checked out, that tree stays locked to a branch nobody is tracking, which is the same silent-loss problem as an abandoned tree, except now there is a live process actively adding commits to it that nobody is reviewing.

The only reliable defence is enumeration from the system, not recall from memory, at the end of every session that spawned workers. That means actually listing what the process table, the pane manager, or the session registry reports as live, not what the orchestrating session believes it launched and believes it already stopped. The two lists should match. When they do not, the discrepancy is the finding, and it needs an explanation before the session is allowed to consider itself done.

Every worker has to resolve to one of exactly two states before teardown: stopped, with its work merged and its result accounted for, or explicitly surfaced as still running, with enough detail attached, what it is, where it lives, why it is still going, that whoever picks this up next does not have to rediscover any of that from scratch. A worker in neither state is not a loose end to tidy up later. It is quota and compute being spent on nobody’s behalf, invisibly, for as long as nobody looks.

Inherited workers make this harder, not easier to skip. A worker launched by a previous session, in a previous context window, is still a worker this session is responsible for accounting for if it finds itself picking up that thread, ownership does not expire just because the session that started it is gone. ‘I did not launch that one’ is not an answer to ‘is it still running’, and treating it as one is exactly how orphans accumulate across sessions instead of being caught by any single one of them.

The check itself is cheap, a process list, a pane list, a session registry query, a few seconds of reading the output against what should be there. The failure it prevents is not cheap: work quietly lost because nobody was the one who verified the worker doing it was ever actually stopped.

Comments (0)

Sign in to comment.