What does your spec file look like when you kick off a new agent? Curious if you start from scratch each time or carry over context from previous sessions on the same project.
The Planners/Workers split is interesting too. Do you find the Worker agents stay within scope reliably, or do you still end up with surprises when they go off-plan?
The routing layer uses tmux: `agent-doc claim`, `route`, `focus`, `layout` commands manage which pane owns which document, scoped to tmux windows. A JetBrains plugin lets you submit from the IDE with a hotkey — it finds the right pane and sends the skill command.
For context sync across agents, the key insight was: don't sync. Each agent owns one document with its own conversation history. The orchestration doc (plan.md) references feature docs but doesn't duplicate their content. When an agent finishes a feature, its key decisions get extracted into SPEC.md. The documents ARE the shared context — any agent can read any document.
It's been working well for running 4-6 parallel sessions across corky (email client), agent-doc itself, and a JetBrains plugin — all from one tmux window with window-scoped routing.
The SPEC.md as the extraction target after a feature is done is a nice touch. In our case the tricky part is that browser automation state is partly external - you have sessions, cookies, proxy assignments that live outside the codebase. So the "ground truth" we needed wasn't just about code decisions but about runtime state too. Ended up logging that separately.
Checking out agent-doc, the snapshot-based diff to avoid re-triggering on comments is clever. Does it handle cases where two agents edit the same doc around the same time, or is the ownership model strict enough that this doesn't come up?
On concurrent editing — it's handled at two levels:
*Ownership:* Each document is claimed by one tmux pane (one agent session). The routing layer prevents two agents from working the same doc simultaneously.
*3-way merge:* If I edit the document while the agent is mid-response, agent-doc detects the change on write-back and runs `git merge-file --diff3` — baseline (pre-commit), agent response, and my concurrent edits all merge. Non-overlapping changes merge cleanly; overlapping changes get conflict markers. Nothing is silently dropped.
The pre-submit git commit is the key — it creates an immutable baseline before the agent touches anything, so there's always a clean reference point for the merge.
The IMAP parallel to browser sessions makes sense. External state that changes independently of your code is the hard case - your doc can describe "the session is authenticated" but by the time the agent reads it that might no longer be true. The document is a snapshot, not a live connection.
One thing we haven't solved cleanly: what happens when the external state change is what triggers the agent task in the first place? Like, a session getting flagged and needing recovery. The event comes from outside the doc system, so there's a gap between "thing happened" and "agent knows about it".
On the "event → agent" gap: we've been thinking about this as a layered problem.
The bridge is a file write. agent-doc is user-initiated (edit a doc, hit submit), but the diff pipeline doesn't care who writes the file. A watcher process — or any external system — can write to the file system, and the agent sees the change on next poll.
We already do this in a different layer: corky (https://github.com/btakita/corky), our email tool, runs a watch daemon that polls IMAP for new messages and syncs them to markdown files on disk. External event (email arrives) gets translated into a file-system change, which is the agent's native input format. Same pattern would work for session recovery: monitoring process detects flagged session → writes to a task file → agent picks it up.
Dashboard-as-document is something we're actively planning. The idea: a markdown template where a watcher fills in operational fields — session status, health checks, proxy assignments. When the watcher updates "active" → "flagged", the diff pipeline sees exactly what changed. The template gives structure; the diff gives the trigger.
The snapshot diff already works for this — partial support exists today via agent-doc's routing layer (external scripts can trigger submission when a file changes). What we're building next is auto-submit on file change and sectional write-back so the agent can update specific dashboard fields rather than only appending.
For sub-second latency, a lightweight daemon that receives webhooks and writes to the notification file or directly triggers an agent submit. But for most operational tasks, a polling interval (ours runs every 30 seconds) closes the gap well enough.
The gap you're describing — "thing happened" to "agent knows about it" — is really about who writes the event into the file system. Once it's a file change, the diff pipeline handles the rest.
the dashboard-as-document idea is pretty much exactly what we ended up needing. in our case the operational state (which sessions are live, which proxies are assigned, what their detection status is) was getting stale almost immediately in any static doc. a watcher that keeps specific fields fresh while leaving the rest of the doc stable solves that without turning the whole thing into a firehose.
we actually built around this problem specifically - CloakBrowser (https://github.com/CloakHQ/CloakBrowser) is focused on browser session isolation, and the state-sync piece was one of the harder parts to get right. each session has runtime state that no static spec can capture. the file-write pattern for feeding live state into agent context would have saved us some pain early on.
curious about the sectional write-back you mentioned building - does the agent target sections by header, or is it more like named anchors in the markdown?
I only run a couple of agents at a time, but with Beads you can create issues, then agents can assign them to themselves, etc. Agents or the human driver can also add context in epics, and I think you can have perpetual issues which contain context too. Or could make them as a type of issue yourself, it’s a very flexible system.
The NERDs approach reminds me of how we ended up thinking about it from the browser automation side too: the thing you actually need to share isn't history, it's a live description of each component's current state and its dependencies. We got there through trial and error but it's interesting to see the same insight in a formal model.
Reading the paper now - curious how you handle NERDs for components that change state frequently at runtime (vs design-time decisions). Browser sessions are a good example - the "entity" changes with every request.
for browser sessions the state problem is even more acute because you have multiple timescales: there's the slow-changing config state (proxy assignment, profile settings) and the fast-changing runtime state (cookies, auth tokens, detection score). a flat NERD document can capture the slow state pretty cleanly but the fast state goes stale the moment it's written. a timeline approach where the NERD just tracks "core state" transitions and points to external logs for the fast stuff might be the right split - you're not trying to snapshot everything, just the inflection points.
the complications in the paper might also look different once you scope it to a specific domain. for code entities the history is mostly append-only and agents mostly read it. for operational entities like browser sessions, the agent is writing frequently and needs to detect conflicts. those are pretty different access patterns.
We hit the same wall running parallel Claude Code sessions. Ended up switching to ctlsurf, which gives agents structured blocks via MCP -- task tables, key-value state, append-only logs. An agent can check "is anyone already on the auth module" by querying a table, not parsing prose. State survives across sessions too, so a new agent doesnt start from scratch.
The drift problem across parallel agents is exactly what convinced me flat files werent enough.
ctlsurf looks interesting, haven't seen it before. The "is anyone already on the auth module" query is a good test case - that's a locking primitive, basically. Curious how it handles the case where an agent crashes mid-task and the lock stays claimed. Does it have a timeout or does someone have to manually clear it?
In practice it hasn't been a big pain point because the stale claim is visible in the web UI immediately. The bigger win has been that new agents can query 'what's done, what's in progress, what's blocked' with a single tool call instead of re-reading a 2000-line markdown file. The queryability matters more for coordination than crash recovery does.
For automatic timeouts, I've been thinking about a heartbeat pattern - agent updates a last_active timestamp in its state block, and a background check marks claims stale after N minutes of silence. Haven't needed it yet at my scale though.
the tricky part we ran into: what counts as "active"? an agent can be mid-computation (legit busy) or just hung. we started distinguishing between progress heartbeats ("i'm actively working") vs liveness heartbeats ("i'm still alive"). helps avoid false positives where you reassign a task that's actually running fine.
the queryability point is underrated btw. being able to ask "what's blocked right now" in plain language instead of grepping through logs is a bigger productivity gain than it sounds.
The spec file helps, but we found we also needed a short shared "ground truth" file the agents could read before taking any action - basically a live snapshot of what's actually done vs what the spec says. Without it, two agents would sometimes solve the same problem in incompatible ways.
Has anyone found a clean way to sync context across parallel sessions without just dumping everything into one massive file?