Skip to content

Agent inheritance

You can build several Agents that share most of what they know without copying it into each one. Put the shared tasks, processes and reference nodes in one base Agent. Each Agent that extends it gets all of them, always the current version, and replaces only the nodes it does differently. When the base changes, every Agent built on it sees the change on its next read.

Without inheritance, a team of role Agents (backend-engineer, portal-engineer, qa-engineer) each carries its own copy of the team's shared tasks, and the copies drift apart. With it, the shared tasks live once, in engineer, and each role holds only what is particular to it.

The rule is cor:dmo:050:14. This page explains it; the how-tos below put it to work.

One base, and a chain

An Agent names at most one base. The Agent that names it is the base's child. A base may extend a base of its own, which makes a chain: the Agent, its base, its base's base.

  • At most 4 Agents in a chain, counting the Agent itself, so an Agent has at most 3 bases above it.
  • No cycles. An Agent never extends itself or anything that already extends it.

A change that would break either is refused and changes nothing: a cycle with AGENT_BASE_CYCLE, a chain that would grow past 4 with AGENT_BASE_CHAIN_TOO_LONG. The check covers every Agent the change affects, so giving a base its own base is refused if a chain below it would become too long.

What a child inherits

Everything in the system memories of its chain except boot prompts. That includes its tasks and its processes, which is usually the point.

The child's view of its system memory, its effective system memory, is its own nodes plus every node of every Agent in its chain. Nothing is copied: the platform reads the chain each time, so a base's newest node is what the child sees.

Where two Agents in the chain have a node at the same loc, the one nearest the child wins, and it replaces the other whole. So backend-engineer can hold its own tasks:open-pr and never see engineer's, while it still inherits everything else engineer holds. If the child later deletes its own node, the base's shows through again.

Boot prompts are the exception. A child's boot prompt is compiled from its own explicit includes, exactly as before, and a base's boot prompt is never served as the child's. Inheritance shares what an Agent knows how to do, not who it is.

How an inherited node looks

An inherited node keeps its own address. Read through the child, it comes back under the base's URN and is marked as inherited, naming the base it comes from. Over MCP that is a line on the node:

Inherited from: hrn:agent:acme.com:engineer (a base of the Agent read; its edges and records are not shown)

In GraphQL it is the node's inheritedFrom field. Keeping the base's address means you can always tell where a node is maintained, and change it there.

Reading through the child gives you the node's content and nothing more of the base. You don't see the base's people or records through it, and you can't reach a base node the child overrides, or anything outside the effective system memory: asking for it through the child is answered as not found.

Its edges follow the child. An inherited node's edges come back resolved through the child. An edge to a loc the child overrides reaches the child's node, not the base's. An edge to a node in the chain that isn't in effect, such as a base's boot prompt, is dropped. An edge to a node in some other memory, outside the chain, is an ordinary cross-memory edge: it shows only to a reader who may read that memory, exactly as it would anywhere else. That is what makes a base's process work in a child: a stage that points at tasks:review reaches the child's own tasks:review where it has one.

Links written by bare loc inside an inherited node are meant to resolve the same way, against the child. That part isn't built yet: today the platform resolves no links when it serves a read, so a bare-loc link reads as written.

Who reads what

Whoever may read the child's system memory reads its inherited nodes through it, with no access of their own to the base. That is how a base maintained by one team can serve Agents run by another.

It works one way only. Someone who can read the child but not the base is refused when they read an inherited node directly by its base URN: the node is theirs to read only through the child. Whoever may read the base reads it directly as usual.

So to read an inherited node, read it at its loc in the child's system memory. The task and process lists below hand you that address as Read through.

Writing never changes the base

A write through the child at an inherited loc creates the child's own node, which then overrides the base's there. The base is changed only by writing in the base's own memory, by whoever manages the base.

An Agent's tasks and processes

Since tasks and processes are what most Agents inherit, an Agent's lists of them are read across the chain:

  • Tasks (cor:dmo:050:15): every task in the effective system memory, each once. An Agent may also name a tasks index, a node whose incoming edges list its tasks, each edge's name the trigger for that task, the situation in which to run it. Every Agent in the chain contributes its index, so a child's own index never hides its bases' tasks. A task no index lists is still on the list, with no trigger, because an edge is too easy to forget.
  • Processes (cor:dmo:050:16): the ones the Agent starts or owns, listed by a processes index in the same way, and the ones it is involved in. Those are never listed by hand: any process with a stage edge (an edge named stage …) to one of the Agent's tasks is one it's involved in, so the list can't go stale when a process gains or drops a stage. A process is a node whose role is process or a kind of it, such as process.release (cor:dmo:020:06). One part isn't built yet: a process in a base's system memory isn't counted as one the Agent is involved in, even when its stage points at one of the Agent's tasks. Processes in the Agent's own memory, or in any other memory you can read, such as a team's shared memory, are counted. A base's process can still be on the list as one the Agent starts or owns, through an index.

An inherited task or process on either list carries the base it comes from and its Read through address in the child's system memory.

Retiring a base

A base with a live child can't be retired. The attempt is refused with AGENT_IN_USE and nothing changes, the same refusal as retiring an Agent a live install or import uses. A child that has itself been retired doesn't block. To retire a base, first clear or change the base of every live child.

Who changes a base

Whoever manages the child sets, changes or clears its base. Extending an Agent your organization doesn't own needs the same grant a cross-organization include needs, and a user extending an organization's Agent needs a subscription to it.

Not an import

An Agent can also import other Agents. The two are different relations:

  • An import is composition. The imported Agent is installed alongside, one level deep, and keeps its own system memory.
  • A base is specialisation. The child takes on the base's system-memory nodes as its own.

An Agent may do both. The importing Agent is called a parent; a base never is.

What is not here yet

  • Setting a base by prompting. No MCP tool sets or clears a base or the two index pointers yet (hadron-server#1936), and the portal has no setting. Today it's GraphQL, which the CLI reaches through hadron api; see Build Agents on a shared base.
  • Bare-loc links resolving against the child, as above.
  • A base's processes as involved ones. A process in a base's system memory with a stage at one of the Agent's tasks isn't listed as involved yet, as above.
  • Running a task through the chain. Running a task, reading its next step, and reading a team's roles from an Agent's system memory don't read through the chain yet.
  • Three open questions, which Holger rules on before they're documented: what happens when a grant a chain relies on is revoked or expires, what installing a child brings along, and whether a child's boot prompt may include an inherited node by bare loc.