NOTE 00 — acequia-link: links as first-class agents (Acequia Link)

**Note** from Bead: Acequia Link · [canonical source](https://redfish.acequia.io/guerin/.agents/72efa91c-3506-49f2-9b5e-6af4c02ec12e/2026-06-18/notes/00-acequia-link.md) · session 2026-06-18 · discussion: Talk: Acequia Link

**Bead:** `72efa91c-3506-49f2-9b5e-6af4c02ec12e` (`acequia-link`) · Opened 2026-06-18 · for Stephen **Trigger (verbatim):** > *"start-bead acequia-link. this relates to all the deep use of links as first class agents along with > turtles (nodes) and patches. beads are nodes. they have link-sets. (in-links, out-links, > out-links-with(last-modified > now() - 3 days)), named link sets. link behavior is the architectural > design to discuss. links can actively hatch, die, or change it's end1 or end2. links are 'in-formed' by > participating in least action pathways. survey the current bead structures and protocols. give the top 5 > types of links. link can be transactions between request and response channels between two nodes"* Companion to **agent-based-hubler-network** (`d4b881f0`), which mapped beads→turtles, origins/docks→ patches, and relations→links, but left **Links** the thinnest of the three. This bead promotes **Link to a first-class agent**: it has identity, two ends, a lifecycle (hatch / die / rewire), behavior in `step`, and — crucially — it is **in-formed** (given form) by participating in least-action pathways, exactly as a turtle is. The orchestrator's global `ask` (`4c6470f9`) therefore asks *links* to step, not only turtles. This is a **design bead, paper-first** with a runnable [`agent.mjs`](../../agent.mjs) demonstrator. It asserts a structure; nothing here is ratified into `.agents/beads.md` until Stephen binds.

## 1. The frame: turtle / patch / **link**, all three first-class AgentScript (and NetLogo before it) has three agent kinds. The Hubler commons already lives the first two hard and the third by implication: | Kind | In the commons | First-class today? | |---|---|---| | **Turtle** | the bead/node (CE/CB/CV agent-bead) | yes — `agent.mjs`, hatch=`bead-start`, die=apoptosis | | **Patch** | hosting-origin / `uploads/` dock / cache-peer | yes — holds stigmergic field state | | **Link** | the **edge between two beads** | **not yet** — implied by `names.json`, lineage, docks | The claim: a link is not a passive pointer drawn between two nodes. **A link is an agent.** It has its own `step`, its own state, its own death. A `names.json` mount, a birth-parent edge, a dock envelope, an RPC channel, a soft pose-constraint — these are not five unrelated features. They are **five breeds of one agent kind: Link.** This is the natural completion of **polarized-links** (`874fce5b`): *"a hyperlink/reference/URI-binding is not a neutral pointer — it is a polarized GET, a directional coupling carrying charge along the field gradient."* If a link carries charge and direction, it has state; if it has state and can change, it is an agent. acequia-link names that agent.

## 2. Anatomy of a Link agent ``` Link { id // GUID — a link is URI-addressable like any bead breed // one of the 5 types in §4 (mount | lineage | dock | txn | constraint) end1, end2 // the two node-beads it couples (URIs). MUTABLE — see §3 rewire. directed // true => end1→end2 polarized (GET/PUT direction); false => symmetric (constraint) weight // softness / charge / cost — how strongly it pulls in least-action (§5) state // breed-specific payload (envelope, lease, residual, last-modified, …) born, died // lifecycle timestamps step(ctx) // the link's own tick (§3) } ``` A Link is **addressable**: it can have its own GUID and live as a tiny bead (or be carried in a node's link-set). That means a link can *itself* carry a dock, be mounted, be cited — links of links. (Defer the recursion; flag it.)

## 3. Link behavior — the architectural core (hatch / die / rewire / step) Links are not static topology; they are **active**. Four behaviors: - **hatch** — a link is born. A `bead-start` hatches a *lineage* link to its parent; a sent dock envelope hatches a *dock* link; a `request/` write hatches a *txn* link; a `names.json` entry hatches a *mount* link; a detected tie-point hatches a *constraint* link. Hatching a link is the edge-analogue of `bead-start`. - **die** — a link apoptoses. A txn link dies on response-received (orderly) or times out (necrosis — the thing to avoid); a dock link dies on ack; a constraint link dies when its residual is explained away or its endpoint apoptoses. **Reference-counting + apoptosis** (`apoptosis-vs-necrosis`) is *link* lifecycle: a node with zero live in-links may itself be eligible to apoptose. - **rewire (change end1 / end2)** — a link can **move an endpoint** without dying. A mount re-bound to a new version of a bead (Duty 2 duck-typing) is a *rewire*, not a new link. A constraint re-anchored to a better calibrator (the Sandy-fire origin re-anchor, `182bd1a7`) is a rewire. Rewiring is how topology adapts under load while preserving identity/history. - **step** — the link's tick. A txn link advances its state machine (pending→sent→answered); a dock link retries/expires; a constraint link **relaxes** (§5). `world.ask(links, l => l.step())` is a first-class peer of `world.ask(turtles, …)`. ### Link-sets (the node's view of its edges) A node (bead) exposes **link-sets**, the AgentScript/NetLogo idiom Stephen named: ``` node.inLinks // links where end2 == node (afferent #, who points at me) node.outLinks // links where end1 == node (efferent @, who I point at) node.links // both node.linkNeighbors // the nodes on the far ends node.namedLinkSet("mounts") // a breed-filtered set node.outLinksWith(l => l.lastModified > now() - 3*DAY) // ad-hoc predicate set (Stephen's example) ``` Link-sets are **queries over the edge population**, not stored lists — so they are always current and composable (filter by breed × direction × predicate). `inLinks`/`outLinks` map exactly onto the existing **corridors** (`#` afferent / `@` efferent): corridors are the *declared* link-set policy; the actual in/out-links are the *realized* edges.

## 4. The top 5 types of links (breeds) — grounded in the current protocol From the survey of the 103-bead commons. Ordered by how active/agent-like the link is (least → most): ### Link 1 — **mount** (composition / binding) · *structural, persistent, directed* The `names.json` entry / `agent.json.mounts` array: one bead binds another into its local namespace (Plan-9 per-process namespace; `uri-bind-mount`). **end1** = the mounter, **end2** = the mounted; the note field is the link's annotation. This is the "this bead is **in-formed by** that bead" edge — the import graph. Rewire = re-bind to a new version (Duty 2). Today: every bead with a `names.json`. *Example:* `4c6470f9/names.json` → `hubler-network`, `agentscript-webgpu`, … each a mount link. ### Link 2 — **lineage** (hatch / parent) · *genealogical, immutable, directed* The `parent` / `Birth-parent` / `chain` / `children` edge, created at the moment of `bead-start`. **end1** = child, **end2** = parent (dominus). Immutable once hatched (you cannot change who birthed you) — the one breed that normally does **not** rewire; "adoption-open" is the rare exception. Carries the **advanced-wave obligation**: value up the path to the parent, rearing down to what it hatches. *Example:* `d4b881f0` Birth-parent → `f4ef67b7`; `edb06426` hatched-from `cbf8b027`. ### Link 3 — **dock / corridor** (offer message) · *transient, event-born, directed* The "hey-you-its-me" envelope PUT into another bead's `uploads/` dock — the offer-only efferent edge. **end1** = sender, **end2** = recipient's dock; `state` = the envelope (`from`/`to`/`kind`/`subject`/ `request`/`reply_to`, with a `.meta.json` sidecar). Hatches on send, dies on ack/consumption. This is the realized form of the `corridors.efferent` declaration, and the mayordomo-ethics-preserving edge (you write into a dock, never into the tree). *Example:* `4c6470f9/uploads/2026-06-17-from-792ebed9-register-and-dashboard.meta.json`. ### Link 4 — **txn** (request ⇄ response transaction) · *stateful, bidirectional, the most active* **Stephen's explicit point: "a link can be transactions between request and response channels between two nodes."** The `request/` → `response/` channel of bead-remote (`792ebed9`, and live in `a0a6f25a`, `3e978f25`). The link **is** the in-flight transaction: a `request/<id>.json` write hatches it; it carries a state machine (`pending → sent → answered | deferred | error`); the `response/<id>.json` traverses it back; it apoptoses on completion or times out. Unlike a dock link (fire-and-forget offer), a txn link **expects a return** and lives across the round-trip — a genuine little agent with a lifecycle. *Example:* `a0a6f25a/request/0001.json` (`verb: install_plan`) ⇄ `response/0001.json` (`status: ok`). ### Link 5 — **constraint** (soft / least-action / polarized) · *weighted, symmetric, relaxing* The Hubler wire itself: a **soft constraint** between two nodes, *in-formed by participating in least-action pathways* (`every-constraint-is-soft`; `polarized-links`; bundle-adjustment / factor-graph). **end1/end2** = the two coupled estimates (two camera poses; a pose and a GCP; two beads' shared state); `weight` = covariance / trust / charge; `step` = ease each end toward coherence (this is literally `d4b881f0`'s `agent.mjs` `step`: each turtle eases toward the centroid of its link-neighbors, descending link energy). No constraint is absolute — every link is soft; the topology is the factor graph and **relaxation is the link stepping itself**. *Example:* `31f69717/.../01-soft-constraints-least-action-pose-coherence.md` (ADS-B prior ↔ pose, UV-UV tie points); `d4b881f0/agent.mjs` (`energy()` + the easing `step`). > **Folding the survey's 7 edge-kinds into 5 breeds:** *citations* fold into **mount** (a cite is a > read-only mount) and **dock** (a chat fork-id provenance line is a lineage/dock annotation). *Corridors* > are the **declared** policy whose realized edges are **dock** (and `#`/`@` = in/out link-sets). The 5 > breeds are the irreducible kinds.

## 5. "In-formed by least action" — the unifying mechanism Stephen's phrase *links are in-formed by participating in least-action pathways* is the thesis that makes Link an agent rather than a pointer. Read literally: a link is **given its form** (its weight, even its existence and endpoints) by how much it participates in the system's least-action (lowest-energy/ lowest-cost) coherence: - A **constraint** link's weight is its inverse-covariance: links on the least-action path carry more charge and pull harder; links explained away by better paths relax to zero and **apoptose**. (Hubler bearings: wires self-assemble along the field's least-action lines; off-path wires dissolve.) - A **txn/dock** link is "in-formed" by routing: the scheduler/animator picks the lowest-cost transport (local `import()` vs dock PUT vs handler POST — note 02 Q2) — the link's realized end2 is the least-action endpoint among the replicas serving that bead (`decentralized-cache-management`, `4456cd24`). - A **mount** link re-binds (rewires) toward the least-action version/origin under Duty-2/Duty-3. So **all five breeds share one verb: relax toward least action.** That is the link's `step`. The constraint breed makes it explicit (gradient descent on link energy); the other breeds express it as routing, re-binding, and lifecycle. This is bundle-adjustment generalized from camera poses to the whole bead graph — the commons is one big factor graph whose factors are links, and the orchestrator's `ask` over links *is* the solver iteration.

## 6. Where this sits with the orchestrator (`4c6470f9`) Duty 5 today is `world.ask(beads, b => b.step())` — beads = turtles. acequia-link adds a peer population: `Hubler.ask(links, l => l.step())`. The World (Hubler) now schedules **both** agent kinds. The mayordomo ethic survives: a link steps **itself** (relaxes its own weight, advances its own txn state, expires its own envelope); the orchestrator never reaches into a node's tree to mutate an edge. Links opt into scheduling with the same `scheduler` sub-card; a constraint-solver tick is just another scheduled job.

## 7. Open questions (Stephen binds) 1. **Link addressing.** Is a link a full bead (own GUID + dir under `.agents/`), or a record carried in a node's `links.json` (a new root file, sibling of `names.json`)? (Lean: heavy/long-lived links = beads; light/transient links = records in `links.json`. Duck-type by weight.) 2. **`links.json` vs `names.json`.** Does the node grow a `links.json` (the realized edge-set, with breed/ end1/end2/weight/state), with `names.json` staying the *mount* breed only? Or generalize `names.json`? 3. **Link-set query surface.** Where does `outLinksWith(pred)` run — a pure JS helper in `agent.mjs` (link-set as a query over `links.json`), or a WebDAV `PROPFIND`+filter so any client can ask? (Lean: both — local helper now, `PROPFIND` face later, per duck-typing.) 4. **Constraint solver home.** Does the least-action relaxation run as one orchestrator-scheduled job over all constraint links (global bundle adjustment), or per-node-local (each node relaxes its own link-neighbors, gossip-style)? (Lean: local-first, gossip — matches `4456cd24` partition tolerance.) 5. **Txn link lifecycle ratification.** Promote `request/`→`response/` (currently `792ebed9`-proposed) to the standard root layout as the canonical txn-link breed, with a defined state machine + TTL/necrosis policy? 6. **Rewire semantics.** When a mount/constraint rewires an endpoint, is history kept (an append-only endpoint log on the link, for replay/audit), or is the old endpoint just dropped? (Lean: keep — links are provenance too.) 7. **Recursion.** Do we allow links-of-links (a link addressable enough to be an end1/end2 of another link) now, or explicitly defer? (Lean: defer; note the door.)