5.7 KiB
topic, status, date, deciders, reconstructed, extends
| topic | status | date | deciders | reconstructed | extends |
|---|---|---|---|---|---|
| what runs on it | accepted | 2026-10-03 | jochen | false | 02-DECISIONS/0152-the-operators-surface-is-a-module-the-console.md |
195. The mesh's tools are found by address, not announced whole
Context
The console answers MCP on a machine's loopback (ADR 0152, to-be 34) and announces, at a session's start, every tool the mesh can say it has: 228 on 2026-10-03, 110 KB, taken once. Three things are wrong with that, measured in research 021:
- Size. Only one client's habit of deferring long lists keeps them out of the model's context.
- Ambiguity. A module on two machines is listed once,
nodeoptional, whichever answers — for postgres and mssql, whose instances hold different data, a call that names no machine asks an arbitrary one. - Staleness. A tool that arrives after the session started is not listed until it reconnects.
The mesh already has the structure a caller needs: seats held once for the mesh, seats held once per machine (ADR 0159), and modules assigned to machines, each assignment issued its own subjects (ADR 0160). The operator's direction: tools are discoverable, in layers, and asking novox's postgres is not asking ace's.
Considered Options
- Keep the flat list and rely on the client. Rejected: the ambiguity and the staleness stay, and it is one client's behaviour.
- One tool per assignment, the machine in the name. Rejected: the list multiplies, and an address in
a tool's name meets the API's limit — letters, digits,
_and-, at most 64 characters. - A fixed handful of tools that walk the mesh's structure, the address an argument. Chosen.
- MCP resources or prompts. Rejected: unevenly supported, and an agent acts through tools.
Decision
1. Everything the mesh answers has one address, by the layer it lives in:
| layer | address | answered by |
|---|---|---|
| a seat held once for the mesh | <seat>.<verb> |
that seat's holder |
| a seat held once per machine | <node>/<seat>.<verb> |
that machine's holder |
| a module assigned to a machine | <node>/<module>.<tool> |
that assignment |
| a module whose instances are interchangeable (ADR 0160) | <module>.<tool> as well |
any of them |
A call to a module that is not interchangeable names its machine, or is refused naming the machines it runs on. "Whichever answers" is no longer an answer for state a machine holds.
2. The console announces a fixed set of tools, not the catalogue:
mesh_overview— the mesh's seats with their verbs, and its machines;mesh_machine— one machine: the node seats it holds and the modules assigned to it, each with its tools by name;mesh_search— words in, matching addresses out with one line each, across every layer;mesh_describe— one address in, its description and argument schema out;mesh_call— an address and its arguments in, the answer out, with the machine that gave it.
Each is answered from the mesh when it is asked, so a tool that arrived a minute ago is found without the client reconnecting. The names are the API's kind of name; addresses never have to be.
3. The flat catalogue stays reachable, not announced: the mesh client and a console setting can
still list it whole, for a person reading it or a client that wants it. An agent pointed at the console
sees the five.
The mechanism changed — 2026-10-03, by ADR 0197. Where the console learns what exists: not from the catalogue's roster and the controller's printed lists, but from every runtime announcing itself on the bus in the NATS services protocol, checked against the controller's records read as JSON. The addresses and the five tools stand.
Consequences
- An agent spends a call or two finding a tool it does not know, and none on one it does; the context no longer carries 110 KB it mostly never uses.
- The ambiguity is closed by the address, not by a description asking the agent to remember
node. - What got harder: an agent that once saw a tool's schema up front now asks for it.
mesh_describeandmesh_searchanswering with the schema of a close match keep that to one call. - The discovery verbs are the console's; the mesh's own records — seats, machines, assignments — are the controller's, and the console asks it rather than keeping a copy.
How it is checked
| Rule | Checked by |
|---|---|
| The console announces five tools | the console's test: tools/list answers exactly the five |
| An address resolves to one subject per layer | the console's tests: a mesh seat, a node seat, an assignment, an interchangeable module, each called by address over a real bus |
| A non-interchangeable module without a machine is refused, naming its machines | the same tests |
| A tool that arrives after the session started is found | a test registering a module after the console's first answer and finding it by mesh_search |
| Live | from a fresh session, which databases does novox's postgres hold is answered by novox's postgres, found through the five |