3.7 KiB
status, opened, located-in, fixed-by, amended-design
| status | opened | located-in | fixed-by | amended-design |
|---|---|---|---|---|
| open | 2026-10-04 |
229 — A rollout cannot be followed through the mesh's tools, so an agent goes round them
What was observed
2026-10-04, rolling out to-be 41. An agent drove the rollout through the mesh's MCP tools: the
controller seat's status, plans, command, and the forge's merge. Five times it left those tools
and posted JSON-RPC by hand to the node console's HTTP endpoint with curl:
- To wait for a plan.
plansanswers once, with prose. Nothing waits for a plan to reach a tier, finish or fail. An agent's tools cannot be called from a shell loop, so the only way to be told when a plan moved was a backgroundcurlloop polling the console every twenty seconds and matching the plan's line withgrep. - To read
status.statusanswers a paragraph of prose (the bus's user list), then a JSON document, both inside one string. Picking outbehind,waitingandreportedtook a script that cut the string at the first brace and parsed the rest. - To read one module out of
module list, whose output was too long to read whole for one line. - To call a tool that arrived after the agent's session began. The modules rolled out in that same
session added
node-login-shell.executeandzsh.zsh_configto one machine. The agent's MCP connection to the mesh had listed its tools once, when the session started, and never listed them again: no list-changed notice reached it, and a search of its tools found neither verb. So the only way to prove the new verb through the mesh was the console'smesh_call, posted by hand. - To reach the console's own generic tools at all. The console serves
mesh_overview,mesh_machine,mesh_search,mesh_describeandmesh_call. The MCP connection the agent had flattens every module's tools into one list, and exposes none of those five. The one surface that can reach any tool by address is therefore missing from the connection agents use.
The calls were authorised, because the console is the operator's own surface. But each is a raw call the mesh's tools were meant to make unnecessary (ADR 0154 puts the controller's verbs behind the seat). Each is also a script that breaks silently when a sentence in the prose changes.
Why it matters beyond this instance
Every rollout an agent drives has the same shape: merge, wait for a plan, push, wait for reports,
check status. When the tools answer only once and only in prose, every agent writes its own poller
and its own parser. Those are invisible to review, different each time, and wrong the first time the
wording moves. An agent that cannot wait also tends to act early, which is the opposite of what a
rollout needs.
What a fix has to settle
- A way to wait on the mesh's own progress. For example,
plansandstatuscould take a plan or node and a bound, and answer when it moves or the bound passes. Or a verb could follow one plan to its end. - Structured answers from the controller's verbs, with the prose as a field beside the data, not around it.
- Whether
command's generic answer should take a filter, or whether the verbs it is used for most (module list,node show) deserve verbs of their own. - A tool list that follows the mesh. When a module's tools arrive or leave, the connection says so
(MCP's list-changed notification). Failing that, it always carries the console's addressable
mesh_callandmesh_describe, so a new verb is reachable without leaving the agent's tools.
How each is checked belongs to the record that settles it.