ADR 0214: 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 mesh plugin; servers, settings and instructions in the managed files; mesh, node and home scopes.
This commit is contained in:
@@ -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/0214-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
|
||||
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
---
|
||||
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
|
||||
---
|
||||
|
||||
# 214. 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, `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 `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 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 `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 `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
|
||||
@@ -313,6 +313,7 @@ python3 00-META/checks/index.py fail if stale
|
||||
- **0209** — [A login on a node moves that node to the account it logged in to; an API key is added from any node, sealed](0209-a-login-on-a-node-moves-that-node-to-its-account-and-an-api-key-is-added-from-any-node-sealed.md)
|
||||
- **0211** — [A machine's power is a node seat, its moments take contributions, and its states are events](0211-a-machines-power-is-a-node-seat-its-moments-take-contributions-and-its-states-are-events.md)
|
||||
- **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** — [The agent's configuration is registered through its module, at three scopes, and served as one plugin](0214-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/0214-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 0214](../../02-DECISIONS/0214-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 `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 `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 `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 0214 |
|
||||
| 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 0214, ADR 0182 |
|
||||
| live: a skill registered at the mesh scope is offered as `mesh:<name>` in a new session on each machine | ADR 0214 |
|
||||
| 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 |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user