Something Smaller Than an Agent: ENGRAM Scopes Authority to a Shared Project

The safest agent I had was the one that couldn’t help anybody. Authority used to attach to the agent, because there was nothing smaller to attach it to – restrict a worker, and you restricted it everywhere. A project is smaller. In v1.17 a project can have members, so a token can be trusted inside one piece of work without being trusted across the whole instance.

There is a screen in ENGRAM that took me an embarrassingly long time to read properly, and what it says is not what I expected. It shows a unit of work called API layer. The owner is an agent. I am listed underneath, as a member.

That is the right way round. The agent does the work; I supervise it. But until this release, the token that agent holds could not share a single memory with me – not a finding, not a decision, not the shape of the endpoint it had just built. It owned the project. It could not talk to the person on it.

This post is about closing that, and about what closing it revealed: the boundary I had been drawing around authority was drawn around the wrong thing.

Screenshot of the Trailhead App project management interface showing various projects, settings, sub-projects, and member information.
The API layer sub-project: owner Trailhead API (agent), with me listed below as a member.
The agent owns the unit of work. Until v1.17, its token could not share a memory with the human on the same project.

The agent that couldn’t collaborate

Two releases ago I added restricted tokens. The reasoning was simple enough that I still stand behind it: an agent that reads input I did not write (a web page, an issue comment, a file from a repository I do not control) should not be able to mint credentials for itself or change account roles. The toggle in the interface says exactly that, and it says who it is for: any worker whose input you don’t control.

That was right. What was wrong was the granularity.

Because the reason to restrict an agent and the reason to let it collaborate are two different facts about the same agent, and one toggle had to answer both. This worker reads untrusted input is a fact about its exposure. This worker is building the API alongside me is a fact about its relationship to one piece of work. A restricted agent could sit on a project, curate what the project held, read the brief – and could not share what it learned with the only person who needed it. To let it do that, I had to un-restrict it globally, which handed a worker reading untrusted input the ability to publish to the entire instance.

So the safest configuration was also the least useful one, and every time I hit that I widened the token and made a note to fix it properly.

The switch wasn’t wrong. It was just the smallest thing I had.

A folder, until someone else could see it

A project in ENGRAM has been able to do a lot for a while. It scopes retrieval. It holds a library of artifacts. It declares its ground truth – the documents its workers answer from, which I wrote about in the last post.

All of it was mine. Not private in the sense of hidden – private in the sense of singular. One owner, one set of eyes, no way to say that this piece of work belongs to more than one of us.

In v1.17, a project has members. It can also be divided into sub-projects – a unit of work with its own team, its own library and its own brief, sitting under a parent that may or may not govern it. The two arrived together, and not by coincidence: once a project is something people and agents belong to, the useful question stops being what does this project hold and becomes which part of it is this worker on.

A project management interface for 'ENGRAM KB', displaying project settings, members, and a library of documents and articles related to memory architecture and agent management.
The ENGRAM KB project with two people added, and the grant stated in the interface itself.
A member reads the project and the project-visible artifacts it holds. That is the whole grant.

Membership, concretely.

A member can read the project and the project-visible artifacts it holds. That is the entire grant, and I want to be exact about what it excludes, because “added to a project” carries a lot of assumed meaning from other tools.

No edits. No settings. No ability to add or remove anything. And (the one that matters most) no access to anyone’s memories. Memories are shared one at a time, deliberately, through an explicit grant, and joining a project does not touch that. A private artifact stays private to its owner no matter who joins.

You can add people, your own sub-agents, and agents an administrator has opted in as valid share targets. A member can also be promoted to delegate, which adds the ability to manage the membership itself and attach sub-projects. Only the owner can grant that, deliberately: a permission that could grow its own population is a permission that eventually escapes.

One quiet consequence is worth naming. Until this release, list_projects returned only what you owned, which meant an agent could not discover a project it had been added to – the project id had to be handed to it by a human, usually pasted into a CLAUDE.md file so it survived the next session. It now returns owned and member projects, each row carrying how you reach it. An agent can ask what it belongs to and get an answer.

The brief no longer has to be public

In the last post I described ground truth: declaring the documents a project answers from, so a worker is anchored on a design rather than on whatever it can infer. And I noted a limitation I was not happy about — a ground-truth article had to be public, readable by everyone on the instance, because publishing was the only mechanism I had for making it readable by the team.

That is a strange thing to have to do. You scope a brief on purpose, then un-scope it entirely so the agents working from it can read it. And a brief is not neutral material once it is loose. It is written for one team, in that team’s terms, and it asserts what is true for this piece of work – this contract, this decision, this version. A public article is retrievable by every worker on the instance, and retrieval is associative rather than filtered – two REST API projects share most of their entities even when their contracts disagree. Prioritising your own brief ranks it up; it does not keep the other project’s contract out of the context, because the noun phrases pulling that contract in are the same ones pulling yours. The team it was written for is the only audience it helps.

The rule was never really about visibility. It is about readability: a ground-truth article must be readable by the project’s team, because a worker that cannot resolve the brief’s entities is anchored on something it cannot see. Public always satisfies that. Private never does, and is refused at declare time rather than accepted and silently useless.

What v1.17 adds is the case in between: project visibility, the one value where membership means anything at all. Public needs nothing – members read a public article because everyone does. Private is never readable by anyone but its owner, whoever joins. Only project asks who the team is.

And it takes two halves, neither of which works alone. The article must carry project visibility, and it must be filed in the project – the collection edge is what says whose members. A project-visible article that nobody filed is readable by nobody in particular; an article filed into a project while still private stays private to its owner, sitting in a library the team can see the shape of and not the contents of. Declaring your own article as ground truth files it as part of declaring, so that half comes free.

The same predicate governs ground truth and everything else in the library, which is the part I am most pleased with: there is one rule about who can read what, not one for briefs and another for artifacts.

While I am in this part of the interface: a project can also declare what it treats as wrong – a document listing claims to be checked against, in addition to ENGRAM’s built-in list of known confabulations, never instead of it. It has its own story and I will tell it properly another time.

Screenshot of the ENGRAM Knowledge Hub interface displaying the 'API layer' project section, with details on members, settings, and project artifacts.
The ground corpus of the API layer sub-project: two inherited system articles, one declared contract, and the readability rule stated in place.
Public always works; a project-visible article works for your own work, and declaring it makes it readable by this project’s members.

The ladder

The token change follows from all of that. An agent’s authority is no longer one bit; it is a rung.

Contributor is the floor: work in the knowledge base, keep your own memories, share nothing outward.

Project Collaborator is the rung that did not exist. A restricted token on this rung keeps everything that made it safe (it still cannot mint credentials for itself or change account roles) and gains exactly the two abilities that only make sense between collaborators: it can share a memory with someone it shares a project with, and it can publish its own article to a project it belongs to, where that team can read it. Publishing to the whole instance remains an act for a full-authority token.

Agent Manager is the top rung, provisioning and managing the agents it owns.

The nicest detail is in the interface rather than the model. The restricted toggle carries different explanatory text depending on the rung the agent sits on – the same switch, honestly describing what it now means for this particular worker.

Screenshot of an application interface displaying a user token management section with options to issue, rotate, and revoke tokens for a 'MacBook Pro PAT'.
A Contributor agent’s token panel: restricted means credentials and roles, and nothing else.
The floor. Safe, and unable to pass anything to anyone.

Screenshot of the Trailhead API settings interface showing user details, active token status, and options to manage JWT tokens.
The same panel for a Project Collaborator: the restriction text now names what the rung adds.
Still cannot mint credentials or change roles — and can now share memory with, and publish to, the projects it belongs to.

Admin panel displaying user management for ENGRAM agents, including a list of agents with their roles, statuses, and action options.
The role selector in Administration, showing the three rungs.
Authority stopped being a property you have and became a distance you reach.

Delegation follows the same shape. An Agent Manager provisions its own agents, but can never mint one more powerful than itself, and the tree is capped at two levels. A structure that can only narrow as it grows is one you can reason about after it has grown.

Two kinds of inheritance

A real project is rarely one job. An application has an API layer and a backend service; each has its own worker, its own contract, and its own idea of what finished looks like. Before this release the only way to express that was to make several unrelated projects and hold the relationship between them in my head. A sub-project makes the relationship explicit: a unit of work sitting under a parent, with its own team, its own library and its own declarations – small enough that “which project is this worker on” has one answer.

Building them alongside membership forced me to separate something I had been conflating. A unit of work can inherit two different things from its parent, and they are not the same question.

Inherit the parent’s corpus decides what the unit is accountable to – whether the parent’s brief governs its answers.

See the parent’s library decides what the unit can read – whether the parent’s artifacts are visible in it. Inherited artifacts are listed separately and stay the parent’s; nothing is copied.

A unit can take both, either, or neither. A sub-team that must honour the system contract but work only from its own material turns the library off and leaves the corpus on. This is the same distinction as ground truth versus collection, one level down, and once you can put people on a project it stops being academic: what a team is accountable to and what a team may read are different grants.

Screenshot of the Trailhead App settings page for the API layer, showing options for ground truth policy and inheritance of corpus.
The sub-project settings panel: ground-truth policy, default-corpus inheritance, parent-corpus inheritance, and parent-library visibility as separate switches.
Accountability and readability are different questions, and now have different answers.

Setting up a team from inside a session

None of this requires the interface. Seven new tools landed with this release, taking the MCP surface to 51, and the sequence an orchestrator runs from inside its own session is short:

  • create_project – provision the unit of work
  • add_to_project – file the artifacts it holds
  • add_project_member – put the workers and the human on it
  • set_project_authority – declare what it answers from
  • get_project_authority – read the declaration back and verify

Then each worker calls list_projects, finds the row it reaches as a member, and declares that project on recall. Also new, and quietly useful: get_memory reads one memory by id, whatever state it is in – the missing read counterpart to correcting one.

What this doesn’t do

Membership is read-only. It is a grant to read, not a shared workspace. The settings and the library stay with the owner, and a delegate extends only as far as managing members and attaching sub-projects. If a project needs several people curating what it holds, membership is not yet the mechanism for that.

You cannot file someone else’s private artifact. If a colleague’s research is private, adding it to a shared project is not yours to do – even as the project owner. They file it, or it stays out.

Delegate is owner-granted only. An orchestrator cannot bootstrap its own team’s membership beyond one level. That is deliberate today, and delegate administration for a project is on the list.

Retrieval has no recency axis yet. Ranking is associative and importance-weighted, so a question about a fast-moving project can return a finding that was true last week. Adding recency as a third axis is queued.

And then the one where my diagnosis was wrong.

An agent reaches a project’s brief by declaring the project on the call. Membership makes that easier (it can now list what it belongs to instead of waiting for someone to paste an id into a file) but it does not make it automatic, and for a while I was convinced the fix was obvious: give each agent a home project, and let an undeclared recall fall back to it.

It isn’t the fix. A standing fact cannot express a current one. active_repo says where the code is. Membership says what an agent belongs to. A default project says where it usually works. None of them can say this task, this project – and an agent that belongs to four projects has four equally true answers to a question about which one it is working in right now.

I also considered falling back to the caller’s sole membership when nothing is declared, and failing closed when there is more than one. That is correct, and it stops being useful the day an agent joins its second project, which is the normal case rather than the edge one.

What is missing is something that carries intent at the moment work is assigned – per task, not per identity. That is not a property of the agent. It is a property of the instruction. I know roughly what it looks like now, and it is the subject of the next post.

What it comes to

Memory stays personal – membership grants reads, and never touches what anyone remembers.

The project carries the brief – filed where the team can read it, and nowhere else.

And authority narrows as the tree grows, because the boundary finally has something smaller to attach to than the agent itself.


ENGRAM is in private beta. If you would like to try it, get in touch.


For the background this builds on:

  1. No Message Passed Between Them: ENGRAM Agents Coordinate Through Memory — agent projects, fan-out and fan-in, and the introduction of Scoped Authority Retrieval.
  2. When the Question Has a Right Answer: ENGRAM Allows Agents to Work from a Brief — ground truth, the prioritize and restrict policies, and the public-brief limitation this release closes.
  3. Tutorial 8 — What your agents inherit — declaring ground truth on a project and watching a worker resolve it.
  4. The v1.16 release notes, for restricted tokens and why they existed before there was a rung for them.

Leave a comment