ADR 0197: every tool announces itself on the bus, in the NATS services protocol #331
@@ -68,6 +68,11 @@ the client reconnecting. The names are the API's kind of name; addresses never h
|
|||||||
still list it whole, for a person reading it or a client that wants it. An agent pointed at the console
|
still list it whole, for a person reading it or a client that wants it. An agent pointed at the console
|
||||||
sees the five.
|
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
|
## Consequences
|
||||||
|
|
||||||
- An agent spends a call or two finding a tool it does not know, and none on one it does; the context
|
- An agent spends a call or two finding a tool it does not know, and none on one it does; the context
|
||||||
|
|||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
---
|
||||||
|
topic: what runs on it
|
||||||
|
status: accepted
|
||||||
|
date: 2026-10-03
|
||||||
|
deciders: jochen
|
||||||
|
reconstructed: false
|
||||||
|
extends: 02-DECISIONS/0195-the-meshs-tools-are-found-by-address-not-announced-whole.md
|
||||||
|
---
|
||||||
|
|
||||||
|
# 197. Every tool announces itself on the bus, in the NATS services protocol
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
[ADR 0195](0195-the-meshs-tools-are-found-by-address-not-announced-whole.md) gave every tool an
|
||||||
|
address and the console five tools to find them. Where the console learns what exists, it inherited
|
||||||
|
from [to-be 34](../03-DESIGN/01-to-be/34-the-console.md) §3: ask the catalogue for its roster, ask
|
||||||
|
each module on the roster for its `tools`, and read the machines and assignments from the
|
||||||
|
controller's printed `node list` and `module list`. Built that way on 2026-10-03, it worked and showed
|
||||||
|
what is wrong with it:
|
||||||
|
|
||||||
|
- **It asks what should exist and infers what does.** The roster holds every module the catalogue
|
||||||
|
ever registered; 47 of them were reported "not answering" on 2026-10-03, most with no tools at all
|
||||||
|
and several retired.
|
||||||
|
- **It parses prose.** Two of the controller's answers are text for a person, and a reworded column
|
||||||
|
breaks discovery.
|
||||||
|
|
||||||
|
The bus already knows what answers. NATS has a services protocol for exactly this: a service answers
|
||||||
|
`$SRV.PING` and `$SRV.INFO` — every instance, on one request — with its name, its instance, and every
|
||||||
|
endpoint's subject and metadata, in a published format the NATS tools read. The operator's direction:
|
||||||
|
*every tool announces itself; the mesh has the full picture, so nothing should be inferred or parsed.*
|
||||||
|
|
||||||
|
## Considered Options
|
||||||
|
|
||||||
|
1. **Keep asking the roster, and give the controller JSON answers.** Fixes the parsing, keeps the
|
||||||
|
inference.
|
||||||
|
2. **Re-serve every tool through a NATS services library.** The announcement for free, but every
|
||||||
|
runtime's serving path rewritten around a library, in two languages, for no change in behaviour.
|
||||||
|
3. **Every runtime answers the services protocol's discovery subjects with what it serves; serving
|
||||||
|
is unchanged.** Chosen.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
**1. What answers announces itself.** Every runtime that serves tools — each machine's tool runtime,
|
||||||
|
the per-module runtimes still in containers, and the controller for the seat it holds — answers
|
||||||
|
`$SRV.PING` and `$SRV.INFO` in the NATS services format: one service per module or seat it serves,
|
||||||
|
named for it, its instance the machine; one endpoint per tool, its subject and queue exactly as
|
||||||
|
served, its metadata the tool's description, argument schema, the machine, the seat and scope where
|
||||||
|
it is a seat's verb, and whether the module's instances are interchangeable.
|
||||||
|
|
||||||
|
**2. The console finds what exists by asking the bus,** one `$SRV.INFO` request, every answer
|
||||||
|
gathered for a short window. What it announces through ADR 0195's five tools is what answered.
|
||||||
|
|
||||||
|
**3. What should exist is the mesh's records, read as data.** The controller answers its machines and
|
||||||
|
modules as JSON, and says which modules declare tools; the console names as *not answering* only an
|
||||||
|
assignment that declares tools and did not announce them. A module with no tools is never listed.
|
||||||
|
|
||||||
|
**4. The grants say so.** Every principal that serves tools may subscribe the services discovery
|
||||||
|
subjects for what it serves; the console's and every runtime's account may publish the discovery
|
||||||
|
request. Replies travel to the asker's own inbox as every reply does.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- The standard `nats micro list` and `nats micro info` show the mesh's tools, live, to anybody holding
|
||||||
|
a credential — the bus's own view, not the mesh's description of it.
|
||||||
|
- Discovery costs one request and a gathering window, not one request per roster entry.
|
||||||
|
- What got harder: three runtimes must answer the same format the same way — the Go tool runtime, the
|
||||||
|
TypeScript runtime the containers still run, and the controller. The format is NATS's, so a test
|
||||||
|
reads all three with the NATS services client and nothing of the mesh's.
|
||||||
|
|
||||||
|
## How it is checked
|
||||||
|
|
||||||
|
| Rule | Checked by |
|
||||||
|
|---|---|
|
||||||
|
| A runtime announces exactly what it serves | each runtime's test: `$SRV.INFO` answered with one service per served module or seat, its endpoints' subjects the subjects served |
|
||||||
|
| The format is NATS's | the same tests read the answer with the NATS services client's own types |
|
||||||
|
| A module with no tools is never listed; an assignment with tools that did not answer is | the console's test, against controller records with both |
|
||||||
|
| Nothing is parsed from prose | the console reads only JSON answers (code review; the text parsers are deleted) |
|
||||||
|
| Live | `nats micro list` against the mesh's bus lists every machine's tool runtime and the controller |
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [ADR 0195](0195-the-meshs-tools-are-found-by-address-not-announced-whole.md),
|
||||||
|
[ADR 0160](0160-the-mesh-issues-an-assignments-subjects-and-a-runtime-serves-what-it-is-issued.md),
|
||||||
|
[ADR 0175](0175-one-tool-runtime-per-node-serves-every-modules-tools-on-the-host-side.md)
|
||||||
|
- [to-be 34](../03-DESIGN/01-to-be/34-the-console.md)
|
||||||
@@ -296,6 +296,7 @@ python3 00-META/checks/index.py fail if stale
|
|||||||
- **0192** — [A tools bundle declares what it is given, and the runtime hands it to that bundle alone](0192-a-tools-bundle-declares-what-it-is-given-and-the-runtime-hands-it-to-that-bundle-alone.md)
|
- **0192** — [A tools bundle declares what it is given, and the runtime hands it to that bundle alone](0192-a-tools-bundle-declares-what-it-is-given-and-the-runtime-hands-it-to-that-bundle-alone.md)
|
||||||
- **0193** — [Every bundle the runtime serves is launched, and the runtime knows no language](0193-every-bundle-the-runtime-serves-is-launched-and-the-runtime-knows-no-language.md)
|
- **0193** — [Every bundle the runtime serves is launched, and the runtime knows no language](0193-every-bundle-the-runtime-serves-is-launched-and-the-runtime-knows-no-language.md)
|
||||||
- **0195** — [The mesh's tools are found by address, not announced whole](0195-the-meshs-tools-are-found-by-address-not-announced-whole.md)
|
- **0195** — [The mesh's tools are found by address, not announced whole](0195-the-meshs-tools-are-found-by-address-not-announced-whole.md)
|
||||||
|
- **0197** — [Every tool announces itself on the bus, in the NATS services protocol](0197-every-tool-announces-itself-on-the-bus-in-the-nats-services-protocol.md)
|
||||||
|
|
||||||
### How it is built
|
### How it is built
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ status: designed
|
|||||||
code: [mesh-catalog, mesh-tools, mesh-controller]
|
code: [mesh-catalog, mesh-tools, mesh-controller]
|
||||||
updated: 2026-10-03
|
updated: 2026-10-03
|
||||||
decisions:
|
decisions:
|
||||||
|
- 02-DECISIONS/0197-every-tool-announces-itself-on-the-bus-in-the-nats-services-protocol.md
|
||||||
- 02-DECISIONS/0195-the-meshs-tools-are-found-by-address-not-announced-whole.md
|
- 02-DECISIONS/0195-the-meshs-tools-are-found-by-address-not-announced-whole.md
|
||||||
- 02-DECISIONS/0160-the-mesh-issues-an-assignments-subjects-and-a-runtime-serves-what-it-is-issued.md
|
- 02-DECISIONS/0160-the-mesh-issues-an-assignments-subjects-and-a-runtime-serves-what-it-is-issued.md
|
||||||
- 02-DECISIONS/0159-a-tool-call-names-the-machine-and-a-holder-serves-its-seats-verbs.md
|
- 02-DECISIONS/0159-a-tool-call-names-the-machine-and-a-holder-serves-its-seats-verbs.md
|
||||||
@@ -106,6 +107,11 @@ interchangeable is called with its machine or refused with the machines it runs
|
|||||||
verb asks the mesh when it is called, so nothing is kept for a session's length; the flat catalogue
|
verb asks the mesh when it is called, so nothing is kept for a session's length; the flat catalogue
|
||||||
stays reachable through the `mesh` client and a setting, unannounced.
|
stays reachable through the `mesh` client and a setting, unannounced.
|
||||||
|
|
||||||
|
**What exists is what announced itself** ([ADR 0197](../../02-DECISIONS/0197-every-tool-announces-itself-on-the-bus-in-the-nats-services-protocol.md)):
|
||||||
|
every runtime answers the NATS services protocol's `$SRV.INFO` with what it serves, and the console
|
||||||
|
gathers one request's answers; the controller's records, read as JSON, say which assignments with
|
||||||
|
tools should have answered.
|
||||||
|
|
||||||
*Found 2026-10-03, measuring for that record:* §3's statement that a stateful module on two machines is
|
*Found 2026-10-03, measuring for that record:* §3's statement that a stateful module on two machines is
|
||||||
listed once per machine does not hold on the live console — postgres and mssql are listed once, `node`
|
listed once per machine does not hold on the live console — postgres and mssql are listed once, `node`
|
||||||
optional, answered by whichever instance replies. The address replaces that statement rather than
|
optional, answered by whichever instance replies. The address replaces that statement rather than
|
||||||
|
|||||||
Reference in New Issue
Block a user