ADR 0216: the agent's configuration is registered through its module, at three scopes, and served as one plugin

Graduates research 029 and amends design 36 (section 8): skills, subagents,
commands, hooks and output styles in one nox-mesh plugin; servers, settings
and instructions in the managed files; mesh, node and home scopes.
This commit is contained in:
jochen
2026-10-05 11:45:58 +02:00
parent daf2f6d2b1
commit f291d113c8
4 changed files with 233 additions and 4 deletions
@@ -1,5 +1,5 @@
---
status: active
status: graduated
initiated: 2026-10-04
touches:
- 03-DESIGN/01-to-be/36-the-operators-agent-on-a-machine.md
@@ -8,7 +8,9 @@ touches:
- 02-DECISIONS/0201-a-module-keeps-its-current-state-in-key-value-buckets-it-declares-and-reaches-through-the-runtime.md
- 02-DECISIONS/0210-a-tools-configuration-is-its-seat-holders-and-every-other-module-extends-it-through-the-seat.md
- 02-DECISIONS/0213-the-operator-sets-the-agents-managed-settings-through-the-agent-module.md
became: []
became:
- 02-DECISIONS/0216-the-agents-configuration-is-registered-through-its-module-at-three-scopes-and-served-as-one-plugin.md
- 03-DESIGN/01-to-be/36-the-operators-agent-on-a-machine.md
---
# 029 — The agent configured through its module
@@ -0,0 +1,167 @@
---
topic: what runs on it
status: accepted
date: 2026-10-05
deciders: jochen
reconstructed: false
extends: 02-DECISIONS/0213-the-operator-sets-the-agents-managed-settings-through-the-agent-module.md
---
# 216. The agent's configuration is registered through its module, at three scopes, and served as one plugin
## Context
The operator wants everything about the coding agent that can be configured to be configured through
the agent module's tools ([research 029](../01-RESEARCH/029-the-agent-configured-through-its-module/00-overview.md)).
That covers subagents, skills, slash commands, hooks, output styles, settings, permissions,
instructions and tool servers. Each is registered once, from any machine, for one machine, several or
all of them.
The agent module already manages three files in the agent's machine-wide managed directory: the
settings, the tool servers and one instruction file ([to-be 36](../03-DESIGN/01-to-be/36-the-operators-agent-on-a-machine.md)).
Tool servers registered through its tools are kept in its state on the bus and reach every machine
they apply to. The vendor has **no machine-wide place for skills, subagents, commands or hooks**; they
live only in a home or a project. Measured on four machines
([029/01](../01-RESEARCH/029-the-agent-configured-through-its-module/01-what-is-configured-today.md)),
what was copied there by hand had drifted and gone stale:
- two skills of a retired system were on all four machines;
- one rule file existed in three versions;
- two contradicting instruction sets were loaded into the same session;
- a subagent existed on one machine only.
The vendor's **plugin** carries skills, subagents, commands, hooks and output styles. A machine-wide
setting can name a marketplace and enable a plugin from it
([029/02](../01-RESEARCH/029-the-agent-configured-through-its-module/02-what-the-vendor-allows.md)).
Tried on one workstation ([029/04](../01-RESEARCH/029-the-agent-configured-through-its-module/04-what-was-confirmed.md)):
- a plugin in a directory marketplace, enabled by the managed settings, loads in every session with no
prompt, read in place, and an edit reaches the next session with no version change;
- its items are offered under the plugin's name;
- its hooks run;
- its tool servers are blocked by the exclusive managed tool-server file.
A plugin cannot carry settings, permission rules or instructions.
The operator also set the scopes. A skill may be meant for:
- every machine;
- one machine;
- one machine's own account, as if written there by hand.
The instruction file the same: the mesh's piece, the node's piece, and further customisation per machine.
## Considered Options
1. **Copy everything into each home**, owned by the mesh path by path. Rejected as the *only* place:
the home is the person's ([ADR 0182](0182-inside-a-home-the-mesh-owns-what-it-places-and-holds-the-rest-as-found.md)),
a mesh item there is indistinguishable from the person's by name, and it fills the directory where
the drift was measured. Kept as one scope of three (below).
2. **A plugin per source:** one for the operator's registrations, one for what other modules
contribute. Rejected: two prefixes to remember for one agent. Where an item came from belongs in
the module's list, not in its name.
3. **Registrations in a repository on the forge**, the plugin built from it. Rejected for now:
registering would be a commit, and the forge would sit on the path to every machine. Configuration
would enter the code review cycle, which it does not need.
4. **One plugin, `nox-mesh`, plus the managed files the module already writes, at three scopes, all
registered through the module's tools and kept in its state on the bus.** Chosen.
## Decision
Option 4.
**1. What goes where.** Each kind of item goes to the one place the vendor honours for it:
| kind | place |
|---|---|
| skills, subagents, slash commands, hooks, output styles | the plugin `nox-mesh` |
| tool servers | the managed tool-server file, as today: the exclusive file blocks a plugin's servers |
| settings and permission rules | the managed settings file: a plugin's settings are dropped |
| instructions | the managed instruction file, in sections: a plugin's instruction file is not loaded |
The plugin is named `nox-mesh` (the operator's choice): the name its items carry in every session, and
not one a person's own plugin is likely to take. It lives in a marketplace directory inside the module's
managed directory, written whole by the module's code. The managed settings name that marketplace and enable the plugin. Those two keys
are the mesh's, laid last like the attribution key (ADR 0213), and no setting replaces them.
**2. Three scopes.** Every registration names one:
- **mesh:** every machine running the agent, including one that joins later.
- **node:** one machine, or a list of them. Rendered into the same plugin and managed files, on those
machines only.
- **home:** the operator account's own agent directory on one machine. The item is placed where the
person's own items live, without the plugin's prefix.
Settings and permission rules take the mesh and node scopes only. The home's settings file stays the
person's.
**3. Instructions follow the scopes.** The managed instruction file holds, in order:
1. the mesh's piece, the same everywhere;
2. the node's piece: its role, and the sections registered for it.
Further customisation per machine is a rule file placed at the home scope. The vendor concatenates
these and does not override, so the module's status tool names any section that contradicts another,
or that calls a tool the mesh no longer serves.
**4. Registered through tools, kept on the bus.** For each kind, the module serves `list`, `register`
and `unregister` tools; for settings, tools that read and set them at a scope. Each registration is a
key in the module's state ([ADR 0201](0201-a-module-keeps-its-current-state-in-key-value-buckets-it-declares-and-reaches-through-the-runtime.md)):
- an item and its files are one value, refused above **256 KiB**, well under the bus's message limit;
- every instance watches the state and renders what applies to its machine.
The settings registered this way are laid over the `managed_settings` layer of ADR 0213. In order:
ADR 0213's setting, then the mesh scope, then the node scope, then the mesh's own keys.
**5. The home scope owns only what it placed.** The module records each home path it placed, in its
state. It writes, changes and removes only those. It refuses to register a name the person already
uses there, rather than overwrite it.
**6. What the module did not place, it reports and can import.**
- A status tool lists the home's items and says which the mesh placed. It also names any that
duplicate a mesh item or call tools no longer served.
- An import tool registers an item found in one machine's home at a scope the operator chooses.
- Removing the original stays the person's act.
- Whether home items load at all stays the operator's choice, through a vendor setting in the managed
settings.
**7. Changing the agent's own settings is the operator's act.** The vendor's guard refuses an agent that
loosens its own settings. A settings or permission tool is called on the operator's word, and the
module does not try to get around that refusal.
## Consequences
- One registration puts a skill, a subagent or a rule on every machine, on some, or in one account. A
machine that joins takes the mesh and node items at its first start. Nothing is copied by hand.
- The plugin's items are named `nox-mesh:<name>`, and a person's own items keep their names. Nothing the
mesh adds can shadow them.
- A change reaches the next session on each machine, or a running one at its next plugin reload.
- **What got harder:**
- an item larger than 256 KiB cannot be registered until the state can hold files in pieces;
- the module's state now holds file content, not only small records;
- the stale files already in the homes stay until the person removes them. The module names them;
it does not remove them.
- **Not decided here:** another module contributing a skill or a subagent to the agent through a seat
([ADR 0210](0210-a-tools-configuration-is-its-seat-holders-and-every-other-module-extends-it-through-the-seat.md)).
The agent module holds no seat yet. When one is decided, contributions land in the same plugin.
## How it is checked
| Rule | Checked by |
|---|---|
| each kind lands in its one place | the module's render test: a registered skill, subagent, command, hook and output style appear in the plugin; a tool server in the managed tool-server file; a setting in the managed settings file; an instruction section in the managed instruction file |
| scopes | the same test, for one machine of two: a mesh item on both, a node item on one, a home item only in that machine's home |
| the marketplace keys are the mesh's | the render test: a setting naming either key is overridden |
| the home scope owns only what it placed | the module's test: a name the person already uses is refused; unregistering removes only the placed path |
| the size limit | the module's test: an item above 256 KiB is refused at registration |
| live | a skill registered at the mesh scope is offered as `nox-mesh:<name>` in a new session on each machine |
## References
- [Research 029](../01-RESEARCH/029-the-agent-configured-through-its-module/00-overview.md) — the evidence, the vendor's rules, and what was confirmed
- [ADR 0213](0213-the-operator-sets-the-agents-managed-settings-through-the-agent-module.md) — the managed settings setting this lays over
- [ADR 0182](0182-inside-a-home-the-mesh-owns-what-it-places-and-holds-the-rest-as-found.md) — what the mesh may do inside a home
- [ADR 0201](0201-a-module-keeps-its-current-state-in-key-value-buckets-it-declares-and-reaches-through-the-runtime.md) — module state on the bus
- [to-be 36](../03-DESIGN/01-to-be/36-the-operators-agent-on-a-machine.md) — the design this amends
+1
View File
@@ -315,6 +315,7 @@ python3 00-META/checks/index.py fail if stale
- **0213** — [The operator sets the agent's managed settings through the agent module, under the mesh's own keys](0213-the-operator-sets-the-agents-managed-settings-through-the-agent-module.md)
- **0214** — [Backups guard against mistakes, stay on the machine, and are declared by the module that owns the data](0214-backups-guard-against-mistakes-and-stay-on-the-machine.md)
- **0215** — [The machine's message bus is a node seat, and it is never restarted live](0215-the-machines-message-bus-is-a-node-seat-and-is-never-restarted-live.md)
- **0216** — [The agent's configuration is registered through its module, at three scopes, and served as one plugin](0216-the-agents-configuration-is-registered-through-its-module-at-three-scopes-and-served-as-one-plugin.md)
### How it is built
@@ -2,8 +2,9 @@
layer: to-be
status: in-progress
code: [mesh-catalog modules/claude-code]
updated: 2026-10-04
updated: 2026-10-05
decisions:
- 02-DECISIONS/0216-the-agents-configuration-is-registered-through-its-module-at-three-scopes-and-served-as-one-plugin.md
- 02-DECISIONS/0213-the-operator-sets-the-agents-managed-settings-through-the-agent-module.md
- 02-DECISIONS/0209-a-login-on-a-node-moves-that-node-to-its-account-and-an-api-key-is-added-from-any-node-sealed.md
- 02-DECISIONS/0206-a-node-reports-the-anthropic-grant-it-holds-and-the-licence-manager-adopts-a-licence-by-refreshing-it.md
@@ -41,7 +42,8 @@ The agent reads a machine-wide, administrator-owned configuration directory unde
by the vendor: a managed settings file that outranks every user and project setting; a key in it that
adds HTTP tool servers *beside* a person's own without blocking them; and a managed instruction file every
session reads before the user's and the project's. The agent has **no** machine-wide directory for
rules, skills, slash commands or hooks; those exist only under a home or a project.
rules, skills, slash commands or hooks; those exist only under a home or a project — or in a **plugin**
the managed settings enable, which is how the mesh puts them on every machine (§8).
So the mesh's part of the agent's configuration lives there, **owned whole by the module**, and the home
is left alone. What the predecessor shipped as two rule files and two skills folds into the managed
@@ -205,6 +207,60 @@ answer is a package repository for this ecosystem as a seat
and trusted by every node's package manager; not built, and not this module's to build. The vendor's own
installer is rejected: it puts a self-updating binary under the person's home, invisible to the mesh.
## 8. The agent's configuration, registered at three scopes
Everything about the agent that can be configured is registered through this module's tools, once, from
any machine, and kept in the module's state on the bus
([ADR 0216](../../02-DECISIONS/0216-the-agents-configuration-is-registered-through-its-module-at-three-scopes-and-served-as-one-plugin.md)). Every instance watches that state and writes what applies to its
machine. A machine that joins later takes it at its first start.
**What goes where.** The vendor honours each kind of item in one place only, so the module writes four:
- skills, subagents, slash commands, hooks and output styles go into **one plugin named `nox-mesh`**. It
sits in a marketplace directory inside the managed directory, written whole by the module and read in
place by the agent. Its items are offered as `nox-mesh:<name>`, so nothing the mesh adds shadows a
person's own item;
- tool servers go into the managed tool-server file, as in §4. The exclusive file would block a
plugin's servers;
- settings and permission rules go into the managed settings file, as in §2;
- instructions go into the managed instruction file, as sections (§3).
The managed settings name the marketplace and enable the plugin. Those two keys are the mesh's, laid
last with the attribution key, and no setting replaces them.
**Three scopes.** Every registration names one:
- **mesh:** every machine running the agent;
- **node:** one machine or a list of them, rendered into the same plugin and files there only;
- **home:** the operator account's own agent directory on one machine, where the item sits as if
written there by hand.
Settings take the first two scopes only. In the managed settings file they are laid in this order:
the operator's `managed_settings` setting (§2), then the mesh scope, then the node scope, then the
mesh's own keys.
**Instructions follow the scopes.** The managed instruction file holds the mesh's piece, then the node's
piece: its role, and the sections registered for it. Further customisation per machine is a rule file
placed at the home scope. The agent concatenates these and does not override, so the status tool names
a section that contradicts another, or that calls a tool the mesh no longer serves.
**The home scope owns only what it placed.** The module records each home path it placed and touches
only those (ADR 0182). It refuses to register a name the person already uses there.
**The tools.**
- For each kind: list, register and unregister. Each register takes a scope, and a list says where
each item came from.
- For settings and permission rules: read, and set at a scope.
- A **status tool** lists the home's own items beside the mesh's and names the stale ones.
- An **import tool** registers an item found in one machine's home at a scope the operator chooses.
An item and its files are one value in the state, refused above 256 KiB.
**Changing the agent's own settings is the operator's act.** The vendor refuses an agent that loosens its
own settings, and the module does not route around that refusal. A settings tool is called on the
operator's word.
## How it is checked
| Check | Defends |
@@ -215,6 +271,9 @@ installer is rejected: it puts a self-updating binary under the person's home, i
| a switch asked of the seat through the console changes the licence and the token on the node; no tool answer and no log line holds a token | ADR 0183 |
| the API-key binding writes nothing under the home and the agent authenticates through the helper | ADR 0183 |
| the module's test: keys set in `managed_settings` (an auto-mode allow list, a permissions list) appear in the rendered managed settings file, a setting naming the attribution, the connectors key or a key-helper is overridden, and a key-helper appears only for an API-key binding | ADR 0213 |
| the module's render test: a registered skill, subagent, command, hook and output style land in the `nox-mesh` plugin; a tool server, a setting and an instruction section in their managed files; for one machine of two, a mesh item on both, a node item on one, a home item only in that home; a setting naming the marketplace keys is overridden | ADR 0216 |
| the module's test: a home name the person already uses is refused, unregistering removes only the placed path, and an item above 256 KiB is refused | ADR 0216, ADR 0182 |
| live: a skill registered at the mesh scope is offered as `nox-mesh:<name>` in a new session on each machine | ADR 0216 |
| the console's provision resolves by co-location; a machine without the console refuses the module by name | ADR 0027, ADR 0152 |
| a new session on the assigned workstation lists the console's five tools under `mesh` ([ADR 0195](../../02-DECISIONS/0195-the-meshs-tools-are-found-by-address-not-announced-whole.md)) and answers "which node am I" from the instruction file | the exit of the build |