From 066f14b5f8103149c65426e785285e96bb062d6e Mon Sep 17 00:00:00 2001 From: jochen Date: Sat, 29 Aug 2026 14:17:25 +0200 Subject: [PATCH] A node is a conversation, and that is not the employee model Moving this out of 0003 and out of its vocabulary. I had spent three attempts fitting the node's own session into the agent-as-employee record, each time bending hired, draining, reassigned and retired to cover something none of them describe. 0003 is back to its original text. It belongs in 0004, under what a node is, because that is what it is -- not a program installed on a node but part of the node. It holds one session permanently, anything in the mesh can message it, and it remembers across callers and across weeks. Its system prompt is the engram, which is recorded here for the first time despite running on every node. Also recorded: it has its own narrower tool list, so it can go and look rather than only report about itself; there is no authorisation between nodes, because every node is the operator's own; and how a node passes a question on is its own business rather than a protocol field. Switched off it still answers, and that is the point of having an off state rather than an absent one. A node with nothing there is a silence somebody has to diagnose. A node that says it is switched off is not. Same rule the host follows about a service that does not exist. 0001's summary is corrected too: it had one row for "agents", which is the conflation being complained about. Two rows now. A node's own session and a hired worker are built from the same parts and run on entirely different terms. Left standing and NOT resolved here: 0001 says a node does not authenticate to a model provider, agents do. A node that holds a session does. That is a real conflict between what is recorded and what runs, and it needs deciding rather than a fourth reconciliation from me. --- ...01-mesh-brokers-nodes-host-agents-think.md | 19 ++--- .../0003-agents-are-persistent-employees.md | 75 ------------------- 02-DECISIONS/0004-a-node-and-how-it-joins.md | 46 ++++++++++++ 3 files changed, 56 insertions(+), 84 deletions(-) diff --git a/02-DECISIONS/0001-mesh-brokers-nodes-host-agents-think.md b/02-DECISIONS/0001-mesh-brokers-nodes-host-agents-think.md index 60552ba..dfb74fc 100644 --- a/02-DECISIONS/0001-mesh-brokers-nodes-host-agents-think.md +++ b/02-DECISIONS/0001-mesh-brokers-nodes-host-agents-think.md @@ -81,17 +81,18 @@ Four layers. Naming them honestly is worth more than the word on the tin: | **machines are linked by a private network** | and every machine reaches every other over it | | **one node holds knowledge of all of them** | the control plane, and only it | | **modules are how anything is built and delivered** | this *is* the CI/CD, not something beside it ([ADR 0010](0010-delivery.md)) | -| **agents are hired onto nodes and do the work** | the layer the other three exist to carry | +| **every node is a conversation you can address** | it holds a session, it remembers, and any node can message any other ([ADR 0004](0004-a-node-and-how-it-joins.md)) | +| **workers are hired onto nodes to do tasks** | employees, with a lifecycle — a different thing from the row above ([ADR 0003](0003-agents-are-persistent-employees.md)) | -**The fourth row is where the value is, and the first three are what make it possible.** An agent -hired onto one node can reach any other — a shell, a service, a file — because the private network -makes every node reachable and `identity` decides which agents may reach which. **That is the -capability being built**: not machines that can be configured centrally, which is ordinary, but a -set of machines an agent can work across as though they were one. +**The last two rows are not the same thing and the vocabulary of one does not describe the other.** +A node's own session belongs to the node: nobody hires it, it holds no tasks, it is never +reassigned, and it is gone when the node leaves. A worker is an employee — named, hired, drained, +retired, movable. They are built from the same parts and run on entirely different terms, and +collapsing them is how the employee vocabulary ends up stretched over something it does not fit. -The credential belongs to the **agent**, never to the node it is sitting on -([ADR 0006](0006-the-substrate-and-the-control-plane.md)), which is the same rule as *nodes and -agents are decoupled* below, applied to access. +**Where the value is** is that both can reach across the whole set: a shell, a service, a file, or +simply a question to another node. Not machines that can be configured centrally, which is +ordinary, but a set of machines that can be worked across as though they were one. **This is not a mesh in the peer-to-peer sense and will not become one.** The word describes what machines can reach, not how they are governed: diff --git a/02-DECISIONS/0003-agents-are-persistent-employees.md b/02-DECISIONS/0003-agents-are-persistent-employees.md index 3f26127..5bbe516 100644 --- a/02-DECISIONS/0003-agents-are-persistent-employees.md +++ b/02-DECISIONS/0003-agents-are-persistent-employees.md @@ -51,81 +51,6 @@ when it expires. A temporary employee is still an employee. Some agents are **human**. What differs is modality — how the agent acts — not category. A node itself is an agent of a kind exempt from the hiring lifecycle. -### The node's own session - -*Written 2026-08-29. The sentence above is the whole of this and had been left as one line, which -is why it kept being read as a leftover rather than as the design.* - -**Every node holds one session of its own, permanently.** It listens on its own queue, anything in -the mesh may prompt it, and it remembers — what it was asked ten minutes ago and what it was asked -last week, across every caller, the way any conversation is remembered by both sides. Its system -prompt is the node's **engram**: the personality that makes one node's answers recognisably its -own. - -Nothing about it is request-response. A caller asks, the node answers, the exchange stays. - -**It is the same mechanism as a hired agent, and deliberately not the same lifecycle.** That -distinction is the answer to a question asked repeatedly and worth settling here: - -| the same | different | -|---|---| -| a persistent session, accumulating memory, a system prompt, a scoped tool list, addressable by message | how it comes into existence, and whether it can stop | - -**One implementation, two ways of existing: hired, or inherent to a node.** Building the mechanism -twice is real duplication and the concern was right; collapsing the lifecycles is the other mistake -and it is worse. - -**It is provisioned the ordinary way and made immutable — not held outside the system.** The -sentence above says *exempt from the hiring lifecycle*, and the precision matters: it is exempt -from **hiring**, not from having a lifecycle. Its lifecycle is the **node's** — provisioned when -the node enrols, retired when the node is retired. Same states, a different thing driving them. - -That distinction is what keeps it inside the model. A thing genuinely held outside would have to be -special-cased by everything that lists agents; a thing provisioned normally and constrained is one -row like any other, and the constraints are **checkable** rather than remembered: - -| | | -|---|---| -| **cannot be retired, reassigned, or deleted while its node exists** | it *is* that machine's voice — retiring it leaves a node nothing can talk to, moving it puts one machine's mind on another | -| **exactly one per node** | with two, nothing decides which replies when the node is addressed; with none, the node is mute | -| **may be disabled and re-enabled** | ordinary, and see below | -| **its engram may be changed** | its existence is immutable, its personality is not — that is how a node is configured | - -[ADR 0001](0001-mesh-brokers-nodes-host-agents-think.md)'s *the two agent rows per node merge* is -the same fact from the other side: **one per node** — not zero, and not two. - -**Disabled is a state that answers.** A node prompted while its agent is disabled replies saying -so, immediately, without a model being invoked. It does not time out and it is not silence — the -queue is still consumed, and the answer is the state. - -That is the whole reason disabling is better than not provisioning. A node with no agent is a -silence somebody has to diagnose; a node whose agent is disabled tells you what is wrong in the -reply. It is the same rule the host follows about a service that does not exist, applied here: -**absence must never be indistinguishable from a failure to answer.** - -### What is scoped, and what is not - -**Its tool list is its own and narrower than a session a person drives.** The same scoping any -agent has; a different list. - -**There is no authorisation between nodes.** Every node is the operator's own, and a prompt from -one is a prompt from the operator. Asking a node something is asking a colleague, and colleagues do -not present credentials. - -Stated once so it is not discovered later: **the mesh boundary is therefore the security -boundary.** Anything inside can reach whatever any node can reach, which is what makes the token -and the overlay the entire perimeter ([ADR 0004](0004-a-node-and-how-it-joins.md), -[ADR 0007](0007-connectivity.md)). - -**How a node passes a question on is the node's own choice, not a field in a message.** Asked -something it must ask a third node about, a node may say who is asking or may simply ask — the way -a person relaying a question decides how to phrase it. That follows from the engram, not from a -protocol. What it costs is a machine-readable chain of who ultimately asked; what each node was -asked, and by whom, remains in that node's own record. - -**A node thinks about one thing at a time**, being one session. Callers queue, and a long answer -delays the others. - ## Consequences - Memory, workspace and reputation have a subject to belong to. Policy becomes possible: an diff --git a/02-DECISIONS/0004-a-node-and-how-it-joins.md b/02-DECISIONS/0004-a-node-and-how-it-joins.md index 1725bbc..c8731e5 100644 --- a/02-DECISIONS/0004-a-node-and-how-it-joins.md +++ b/02-DECISIONS/0004-a-node-and-how-it-joins.md @@ -28,6 +28,52 @@ asked to do — and that belongs in the host's profile rather than in the defini because its absence is every node in the ordinary disconnected situation at once. An episodic host on a phone is that situation more often. Neither needed a new mechanism. +### A node is also a conversation + +*Written 2026-08-29. It runs on every node today and appeared in no record, which is how something +deliberate comes to look accidental.* + +**A node holds one session, permanently, and it is part of what the node is** — not a program +installed on it. Anything in the mesh can send it a message; it replies; and it remembers. What it +was asked ten minutes ago is still there next week, alongside what everything else asked in +between, the same way both sides of any conversation remember it. + +Its system prompt is the node's **engram** — what makes one node's replies recognisably its own +rather than generic. + +**It has its own tools**, and fewer than a session a person is driving directly. So a question can +be answered by going and looking: *what is in our forge*, not only *what is your battery*. + +**Messages travel the broker like everything else** ([ADR 0002](0002-nodes-communicate-over-a-broker.md)). +There is no second transport and nothing is dialled. + +**Any node can message any node, and this is the one part of the system that is genuinely a mesh** +— symmetric, with no centre. A node that is asked something it does not know can ask another, and +how it passes the question on is its own business: it may say who wants to know, or simply ask. A +person relaying a question makes the same choice, and it follows from the engram rather than from a +message format. + +**There is no authorisation between nodes.** Every node is the operator's own, so a message from +one is a message from them, and asking a node something is asking a colleague rather than +presenting credentials. Stated once so it is not discovered later: **the mesh boundary is therefore +the security boundary** — anything inside can reach what any node can reach, which is what puts the +whole perimeter on the token and the overlay +([ADR 0007](0007-connectivity.md)). + +**It can be switched off, and switched off it still answers.** A node whose session is disabled +replies saying so, at once, with no model involved — the queue is still read, and the state is the +reply. That is deliberate and it is the same rule the host follows about a service that does not +exist: **absence must never be indistinguishable from a failure to answer.** A node with nothing +there is a silence somebody has to go and diagnose; a node that says *I am switched off* is not. + +**One per node, always, and it cannot be moved to another machine.** Two and nothing decides which +replies; none and the node is mute; moved, and one machine is answering as another. + +**It is not an employee** ([ADR 0003](0003-agents-are-persistent-employees.md)). Nobody hires it, +it holds no tasks, it drains nothing and it is never reassigned — that vocabulary was written for +workers and does not describe this. It exists because the node does, and it is gone when the node +leaves. + ## How it joins **The host has one behaviour and two sources of declaration.** What differs between the first