The hard part of running a fleet was never spawning the agents or routing the tasks — your harness already does that. The hard part is what they know, and whether one agent’s finding can reach another without leaking to everyone. That is not a scheduling problem. It is a memory problem.
The two claims, and the debt
A few weeks ago I wrote that an agent harness owns the loop (it spawns workers, routes tasks, sandboxes execution, enforces budgets) but that it does not own what its agents know, because a harness process dies at the end of a run and takes its context with it. The essay drew a boundary I still think is the right one: your harness governs what an agent may do and spend; ENGRAM governs what an agent may know and pass on. Two different planes, and conflating them is how knowledge leaks between tenants.
That piece made two claims and demonstrated neither. It was an argument, not a walkthrough. This is the walkthrough.
- A harness gets a brain between sessions. Its operating knowledge persists, stays current, and corrects itself without losing history.
- The coordination is the memory. If every agent writes its findings to one associative store and reads back under governed scope, you get coordination without a board, a mailbox, or a broadcast channel.
Everything below runs on a live ENGRAM instance: one orchestrator, three workers, two services. By the end, one agent will have diagnosed a bug, another will have fixed it, the two will never have exchanged a message, and a human will have taken ownership of the result through a review gate that nothing crossed unasked.
The fleet:
user_003 (you — human root: quota, audit, revocation)
└── claude-orchestrator agent, Agent Manager, shareable
├── Scout researcher → checkout-service
├── Forge coder → checkout-service
└── Warden reviewer → billing-service
Each identity (you, the orchestrator, each worker) is a separate MCP server entry carrying its own personal access token. Identity is pinned server-side from the token, so an agent can never act as another. That property is doing quiet work throughout: every “who owns this” and “who may read this” question below resolves against a token the caller cannot forge.
The one step everyone skips
“Seeding, concretely.”
Before any of the interesting coordination, there is a step that looks like boilerplate and is in fact the single most common way to lose an afternoon. It is worth understanding why it is mandatory, because the reason is the same reason the whole system needs a feature it does not yet have — but that is the end of the story, not the start.
ENGRAM’s recall is entity-seeded. A query is resolved to entities in the graph, and memories surface by association through those entities. The consequence is unforgiving: a memory about a concept that does not yet exist in the graph will be stored, and will never come back. It is not lost — it is simply unreachable, because nothing links to it.
Now, a freshly provisioned agent is not working from an empty graph, which is the part that surprises people. It can already resolve every entity extracted from public articles and documents — that is ENGRAM’s cold-start mechanism, and it means a new agent is not born mute. What it cannot reach is your private content. Delegation hands an agent an identity and credentials; it does not hand it your private memories, and sharing is fail-closed. So a brief you write for the team is invisible to the team until it is readable by them.
The fix is ordinary work with tools you already have. Write a short brief to the knowledge base e.g., the services in play, the worker-to-repo assignment, the operating knobs, and references to any secrets (references only; ENGRAM never sees credentials). Then make it readable: a brief is private by default, and private content does not reach your sub-agents, so you publish it, and the whole fleet resolves the same vocabulary. Ingestion runs as a background job, so you poll with a recall until the entities resolve before dispatching anyone.

PRIVATE > PUBLIC badge and provenance line. The vocabulary the fleet will share, before any agent runs.

This cluster is what every agent recalls against.
Hold on to the fact that the brief had to be made public for the fleet to share it. It is the correct move today, and it is the seam that the last section of this post returns to.
Claim one: a brain between sessions
“Persistence, concretely.”
Before any agents exist, the harness’s own operating facts go somewhere that outlives the process. These are authored under the human root identity — which matters, because a human root sees only its own memories, so authoring them under your identity is what makes them visible and eligible for your own contradiction detection.
remember(content="The per-agent token budget for checkout-service agents "
"is 100k tokens per run.", scope="long_term")
remember(content="The deployment target for checkout-service agents is staging.",
scope="long_term")
Authored memories are active and recallable immediately — no consolidation wait. So far this is just durable storage. What makes it a brain rather than a notebook is what happens when the facts change, and that mechanism is the subject of the previous post, so I will keep it to the two beats that matter for a fleet.
The budget was raised. You do not edit the fact — you supersede it, deliberately, by id:

via revise · manual · conf 1.00. A correction you asked for.
The deployment target moved to production. This time you say nothing — you write the new reality as an ordinary note, and ENGRAM finds the conflict with staging on its own, judges it a direct contradiction, and retires the old belief without a human step:

via auto · T1 · conf 0.98. A correction nobody asked for. Same mechanism, different decider.
Because every version carries validity bounds, the harness can answer not only what do I believe but what did I believe last Tuesday — a point-in-time reconstruction that composes across independent supersession chains. The previous post makes that case in full; here it is enough to say that the harness’s operating knowledge now persists across runs and corrects itself without losing its past. That is claim one, demonstrated.
Growing the team
“Identity, concretely.”
Now the workers. Each becomes a real ENGRAM identity, not a label in your harness’s config:
create_sub_agent(name="Scout", agent_role="researcher") # → user_008
create_sub_agent(name="Forge", agent_role="coder") # → user_009
create_sub_agent(name="Warden", agent_role="reviewer") # → user_010
issue_sub_agent_pat(user_id="user_008", pat_name="scout-mcp-server")
# → raw_key returned ONCE
Each PAT registers as its own MCP server entry. Every sub-agent records its creator and its human root, delegation depth is capped at two, and you keep quota, audit, and a kill switch over the whole subtree — disabling an agent revokes all of its tokens at once.

Each worker a real identity, not a label.
Two things trip up nearly everyone the first time, and both are worth stating flatly.
The first is the grantee opt-in, and its direction. Automated agents are not valid share targets by default (someone must opt them in) and the flag lives on the receiver, so the question is always who is being shared to, never who is doing the sharing. This fleet’s traffic runs fan-in, workers granting their findings up, so the one identity that must be marked shareable is the orchestrator; the workers are receiving nothing, so they need no flag. Get the direction backwards and every share_memory call returns a 403. An orchestrator opts in an agent it owns with set_sub_agent_shareable, so the reverse direction (handing a finding down to a specific worker) is equally reachable from an agent’s own toolset; it simply isn’t the pattern this fleet uses. Grantee identity is a user_id or email, never a display name, so a worker resolves “the orchestrator” to something concrete with list_grantees() before it shares.
The second is project provisioning. New since v1.12.5, the orchestrator sets up the team’s projects from its plan. A project is purely a scoping anchor — ENGRAM tracks it, but does not create the repo, hold credentials, or run anything.
list_projects() # ALWAYS first — reuse, don't duplicate
create_project(name="checkout-service",
repo_url="github.com/pvelua/checkout-service")
create_project(name="billing-service",
repo_url="github.com/pvelua/billing-service")

repo_url. The key that makes “the project you created” and “the project the worker works in” the same thing.
The repo_url is the shared key, and that is the whole trick: a worker assigned a repo declares active_repo, and it resolves to the exact project the orchestrator provisioned — no opaque id passed around, no coordination needed to agree on which project is which. Keep the mapping one-to-one; repo resolution needs a single match, and two projects sharing a repo_url make it ambiguous.
Wiring one agent in
“Setup, concretely.”
This post shows a fleet already standing. Getting a single agent onto ENGRAM correctly is its own small discipline, and it fails in a particular way worth naming: quietly. An agent write returns an id and reports success whether or not the memory is ever reachable again, so the mistakes do not announce themselves — they surface a session later, as a memory that simply isn’t there.
Three checks catch all of them. Identity is per token — ENGRAM pins who you are from the credential on the connection, with no parameter to override it, so the server you call is whose memory you write to; an agent wired with your token writes into your store, not its own. An agent’s long-term memory defaults to context, not user — a bare remember is session-local unless you say otherwise, which is rarely what you want from an agent you are teaching, so pass owner_scope="user" for anything meant to outlive the session. And an id is not a round trip — recall what you just wrote and confirm it comes back as via: own before you trust the connection at all. Each of these is one call, and each one turns a silent loss into a loud, early failure.
The full walkthrough (provisioning the identity, proving the loop, and choosing the ring) is its own tutorial, linked at the foot of this post.
Claim two: the coordination is the memory
“Coordination, concretely.”
Dispatch itself is your harness’s job — checkouts, branches, credentials, sandboxes. ENGRAM’s job begins the moment a worker learns something.
Fan-out. Scout, working checkout, finds the bug and records it (project-bound) then grants it up to the orchestrator:
# as Scout, on checkout-service
remember(
content="In checkout-service the token-refresh retry loop has no jitter, "
"so parallel runs collide and the auth suite flakes intermittently.",
owner_scope="project",
active_repo="github.com/pvelua/checkout-service",
scope="long_term",
)
share_memory(selector_kind="memory", selector_id=<mem id>,
grantee="user_007", bound_scope="project")
Forge does the same on checkout after shipping a fix; Warden does it on billing. Two details carry real weight here. owner_scope="project" requires an anchor — omit it and you get a 400 that tells you exactly what is missing, where an earlier build would have silently accepted the write and stranded it as a memory that existed but could never be recalled. And bound_scope="project" confines where the grantee may use what it borrows: a finding shared for checkout cannot surface while the orchestrator is working billing, even if it asks directly. Hold that second one — it is about to be the whole point.

Attribution survives the share — a borrowed memory still says who wrote it.
Fan-in. The orchestrator recalls per project, and gets back only what belongs to that project:
recall(active_repo="github.com/pvelua/checkout-service",
query="auth suite flake token refresh retry jitter backoff")

via: shared.The orchestrator sees what was granted up to it — and whose it was.
Switch the anchor to billing and Warden’s refund finding appears; checkout’s two do not. Then ask, deliberately, for checkout’s findings while anchored to billing — and get nothing back.

One orchestrator, two projects, provably isolated — the last row is the security property, not a promise.
The grant’s bound_scope holds against a direct, deliberate request for the memory it confines. That empty result is the security property — not asserted in a design doc, but demonstrated on a live instance: the isolation is a property of the recall predicate itself, not a convention the agents agree to respect.
Step back and see what happened across these two movements. Scout diagnosed a defect. Forge fixed it. The two never exchanged a message — no queue, no shared scratchpad, no direct call. They shared a project and a graph, and every finding moved through governed memory under a scope that decided who could read it. The coordination was the memory. That is claim two, demonstrated.
Handing the work back
“Review, concretely.”
The findings are real, but they are owned by agents. To make them yours, the orchestrator hands them off — it does not push them into your memory:
suggest_memories(
items=[...], # the synthesis, in the orchestrator's words
context_ref="harness-demo/act3-fanin",
hand_off_to="user_003", # you
task_ref="checkout & billing agent findings",
)
Three things are true the instant that call returns. The recap is owned by you, not the agent that wrote it — its id is namespaced to the receiver. It lands in your Suggestions inbox, badged and attributed to the authoring agent. And nothing is recallable yet: query the recap’s own literal wording and you get nothing back, because suggested means suggested.

Nothing is recallable until you accept it.
Accept it, and ownership genuinely transfers: the memories flip to active under your user_id, land user-scoped (recallable everywhere, which is the right home for a cross-project summary a person is meant to act on), and — the neat part — the worker that did the work gets it back. An automatic share with origin: grant_back returns recall to the author, so it does not strand on a memory it wrote.

origin: grant_back. You own it; the worker that wrote it can still read it.
But only within the context the work happened in. The grant-back carries bound_scope: "context", so the access it returns is exactly as wide as the work and no wider. You can verify that directly — recall the same memory with the context declared and without it:

grant_back, and the same recall without the context declared comes back empty.bound_scope holds — a borrowed memory stays exactly as reachable as the work it came from.The third row is the one that matters: a borrowed memory stays borrowed, and grant-back returns access to keep working, nothing more. This is the review gate the whole design turns on — ENGRAM never grows your recallable memory behind your back, and never widens anyone else’s either.
What this doesn’t do yet
Every honest walkthrough owes a section on where its own edge is, and this one has a real one — it has been visible since the second movement.
The seed brief had to be made public for the fleet to share it. That move has a cost: the moment the brief is public, its entities join the same undifferentiated pool as every other public artifact. A worker recalling against its project’s vocabulary can pull in whatever else in the public knowledge base happens to share those entities — another team’s brief, an ambient research note, a stale onboarding doc. During this very run, anchored recalls kept surfacing unrelated public design articles because they shared entities as generic as token budget and memory-service. The project scoping you saw governs sharing precisely (the write side) but for a while it had no read-side counterpart: nothing let you tell a project’s workers these particular artifacts are ground truth, prefer them over everything else public.
That counterpart now exists. A project authority set lets an orchestrator declare which knowledge-base artifacts are ground truth for a project, and recall performed under that project’s scope prefers them — while still falling through to the public knowledge base when a query goes outside the brief, so a worker is never left mute on a question the brief did not anticipate. It is the read-side complement to the write-side isolation this post demonstrated: the fleet stops reasoning from whatever ambient public content happens to share an entity, and reasons from what it was told to trust. It ships today, and it earns its own post rather than a paragraph here — this one had a fleet to get running first
And the standing boundary, unchanged from the essay that started this: ENGRAM does not spawn, route, sandbox, or budget your agents — that is your harness. It holds no credentials and runs no code. It is the layer underneath, not a meta-harness.
Where this leaves things
The harness owns the loop. ENGRAM owns the knowledge. And the coordination between two agents that never spoke was never a message in flight — it was the memory they shared, under a scope that decided who was allowed to read it.
ENGRAM remains in private beta. If you are running an agent fleet and this is a shape you recognise, get in touch.
For the background this builds on:
- A Brain Between Sessions — and Between Agents: ENGRAM Learns to Recall on Demand (10 July 2026)
- Standing Up Your Own Agents: ENGRAM Adds an Agent Manager Role (12 July 2026)
- A Team of Its Own: ENGRAM Agents Learn to Grow and Orchestrate a Team (14 July 2026)
- The Layer a Harness Can’t Own (19 July 2026)
- What I Believed Last Tuesday: ENGRAM Learns to Change Its Mind (24 July 2026)
- Guide to ENGRAM Knowledge Hub – the ENGRAM documentation
- Give your agent harness a memory – the hands-on walkthrough for everything above
- Give your agent a memory of its own — provisioning one agent’s identity, proving the remember → recall loop, and choosing where a memory lives