On Monday evening one of my agent sessions sent a briefing to another session that had stopped listening two hours earlier. The send reported success. Nobody read it. Two days later the same step ran again and found no reachable session at all.
Zero for two. What makes that worth writing about is not the failure. It is that I had already established why it would fail, in the design record for this same system, six days before I built it.
One person, several working contexts
I work across a handful of contexts: an employer, a few advisory engagements, my own projects. Each has its own repositories, its own chat and mail, its own calendar entries, its own people. A morning sync and an evening close have to cover all of them.
The constraint I set at the start was about the output, not the work. I am one person. I don’t become a different person when I switch contexts, and if the system gave me several to-do lists, several daily briefs, several consoles, I would stop opening any of them. One brief. One list. One console. If this ever produces five, the design failed.
The shape that follows has a name in my own industry. Bureau reporters file to a desk, and the desk decides the front page. Workers run per context and hold only that context. The desk reads what they filed, reconciles it, and produces the one brief I actually open. Fan out execution, converge presentation.
The finding I verified and then ignored
When I designed this I checked the mechanisms rather than assuming them. Agent sessions here can message each other, so the obvious move is to have the desk message each context’s session and tell it to run.
The tool’s own documentation says otherwise. A session message is delivered as a user turn into a session that must already exist and be attended. It is a relay between humans at keyboards, not a dispatch primitive. I wrote the consequence into the record: a design that needs every context’s session open and attended every morning has relocated the multi-session overhead, not removed it.
I also wrote the rule that follows. Never build worker-to-desk messaging. Workers write files, the desk reads files. Artifacts survive; messages need a listener.
Then I built the briefing step on session messaging.
What actually delivered
Both mornings the work arrived. Not through the message, which nobody read, but through the artifact, written when I opened that context myself and worked in it. The substrate that was never supposed to be the clever part did the entire job, twice, while the clever part failed silently and reported success.
An artifact is a file at a known path with a schema: which surfaces were synced, what got skipped and why, decisions that need me, what’s waiting on someone else. A worker that ran leaves a fresh one. A worker that didn’t leaves nothing, and that absence is the signal. It can only be a signal because the set is closed: the desk reads absence against a registry of contexts it already knows, so a missing artifact is a named gap rather than a search that came back empty. That distinction is the whole difference between a bounded absence and a null result you should not trust. The desk’s brief opens with a coverage line naming every registered context and its state, so a thin brief is honest rather than late. Compare that with the message version, where a context that never ran is indistinguishable from one whose message nobody opened.
The second force pointing at the same substrate
Files earn their place for a reason that has nothing to do with dispatch.
An employer in a regulated industry can require you to purge their data when you leave, and plenty of them do. If the daily plan copies each context’s content into one person-side file, that file accretes their material every day, and deleting their folders stops erasing them.
So the plan splits along the same line the artifacts already do. Each context’s worker artifact is that context’s plan fragment, stored in that context’s own private repository. The person-side file is a shell: my timeline, the coverage line, pointers to each fragment. A renderer merges them for display. Converged presentation, separated storage, and the boundary stated honestly rather than oversold: content lives only in the context’s folders, while names as references and git history remain.
Two requirements arriving independently at the same answer is usually a sign the answer is right. That should have been enough to stop me building on messages. It wasn’t.
A design record is not a constraint
The question I care about is why I ignored a finding I had verified myself and written down in plain language.
Because a design record reads like advice. It’s prose in a folder. Nothing in the build path consults it. The implementation happened days later in a different session with its own context, holding the goal and the tools but not the earlier conclusion, and it re-derived a plan from scratch that looked entirely reasonable. Reasonable is exactly what a ruled-out mechanism looks like when you rule it out once and don’t write it anywhere the builder has to read.
This generalizes past my own setup. In agent-assisted work the analysis and the implementation are separate acts, usually separate sessions, and the second does not inherit the first’s conclusions unless something makes it. A verified mechanism finding is a constraint. Leaving it in a design document and expecting it to bind the build is the same category of error as writing a coding standard on a wiki page and expecting it to bind the code.
The correction cost one release and no new code. The default worker is now an attended session I open myself, in that context, on that context’s schedule. Desk-dispatched subagents demote to opt-in, for the days I deliberately want everything closed from one seat. The desk never nudges, triggers, blocks on, or waits for a worker. Contexts close on independent schedules, which the timestamped artifacts already supported and the doctrine now states out loud. And one line names the mechanism as it actually is: the principal is the dispatcher.
I put the evidence in the contract next to that line, because the alternative keeps looking attractive. The next person to read it, me included, gets the two failed runs in the same paragraph as the rule.
Where this leaves the machine
The version I shipped first was trying to take me out of the loop. The version that works puts me back in it and makes the machine precise about what it cannot do without me: it reports which contexts are owed, and I decide where to go next. Nothing starts work in a session but the person sitting at it.
Any agent client, or a person with a text editor, can produce a conforming artifact, and any of them can act as the desk. The contract itself is public and client-neutral; nothing in it names a vendor, a scheduler, or a dispatch mechanism, which is the property I’d want most if I were adopting someone else’s version of this.