A module names its events locally and each transport works out where they land. That is what design 29 says and what neither client did: both passed the name straight through, which happened to be right on the old bus because modules were writing routing keys, and wrong on the new one (novox/hq 04-ISSUES/127). The old bus's client now turns a local name into `module.<emitter>.<event>` on the way out and back on the way in. Without that, converting the modules to local names would have broken the mesh that is actually running. **A handler and a manifest now say the same thing.** The key a module sees was the event name alone, so a manifest declaring `consumes: builder.built` produced a pattern that could never match what it was compared against — and a module consuming one event from two emitters could only tell them apart by reading a header. The subject already carries the emitter, so naming it in the key makes a mismatch between manifest and code a typo instead of a category error. Both matchers accept `**` for the rest of a name, which is how a manifest spells it; the old bus's `#` still works, because both buses ship until the rollout.
mesh-tools
The Novox Mesh tool runtime — the per-node process that makes a module's tools actually serve.
A module ships its tools (built on @novox/mesh-sdk); this
runtime is what loads them and puts them on the mesh. It:
- connects the mesh broker (novox/hq ADR 0001) — a concrete AMQP implementation of the sdk's
Brokercontract; - imports the assigned modules' compiled tool entrypoints, each of which registers its tools as it loads;
- serves them through the sdk's
serveToolsharness, answeringtools.invokeover the broker.
Everything hard — dispatch, collection, duplicate-name safety — is the sdk's. This is the thin wrapper that binds the broker and loads the modules. Keeping the AMQP client here, out of the sdk, is deliberate: a broker-client change never rebuilds a module (ADR 0039).
Running it
MESH_BROKER_URL amqp://… the mesh broker
MESH_TOOL_MODULES /a/tools/index.js,… the assigned modules' compiled tool entrypoints
node dist/main.js, or the container (Dockerfile). On a node the host resolves both variables
and starts it like any other supervised workload.
Verified
npm test stands up LavinMQ (the mesh's broker) and proves the whole path over real AMQP: the
runtime serves a registered tool, a separate connection invokes it by name and gets the result, and
an unknown tool is refused over the wire.