- Feature Name: `agents-inherit` (what an agent may do follows from what
owns it: a person's agent inherits that person within its scope, a
site's, team's or repository's own agent holds what it is granted)
- Start Date: 2026-10-31
- Status: Draft. Every decision settled by the owner on 2026-10-31 (see
[Decisions](#decisions)); worked out first as a page of questions with
a recommendation each, all taken as recommended except token upkeep,
which the owner tightened. Build step 1 is built.
- Depends on: RFC 0021 (agent accounts: the operator, the intersection,
tokens, revoke-all, the deed rules, forge agents); RFC 0008 (roles over
the letters); RFC 0018 (teams, their owners, a team's row on a
repository); RFC 0011 §9 (the chat bridge, whose reader rule this
keeps)
- Amends: RFC 0021 decision 3 and [Granting](0021-agent-accounts.md#granting)
(a grant narrows instead of opening); [Tokens](0021-agent-accounts.md#tokens)
and [Lifecycle](0021-agent-accounts.md#lifecycle) (no required expiry;
idle lapse; one revoke-and-reissue per agent); [Team-owned
agents](0021-agent-accounts.md#team-owned-agents) (replaced by team
agents of two kinds); [Migration](0021-agent-accounts.md#migration)
- Terms: as RFC 0021, **operator** is the person, team, repository or
forge an agent answers to, and **site admin** is the person who runs
the forge.
## Summary
An agent is a personal agent or a dedicated agent, at site, team or
repository scope. A **personal** agent belongs to a person and holds
everything that person holds within its scope, live, unless the person
narrows it; it can never hold more. A **dedicated** agent belongs to the
site, a team or a repository itself and is a general account: it holds
what that scope's admins grant it. Tokens need no upkeep: one button
revokes and reissues an agent's tokens, one revokes all of a person's,
and an unused token lapses by itself.
## Motivation
RFC 0021 made an agent its own account that never holds more than its
operator, but gave it nothing by default: the operator grants it each
repository in turn. In practice an operator wants their agent to do what
they do, and they are the one responsible for it. Working repository by
repository is upkeep that buys little, since the intersection already
keeps the agent under its operator.
The second gap is ownership. 0021 knows a person's agent and a forge
agent and defers a team's. A release bot that belongs to a repository,
or a triage bot a team runs, has no home today except some person's
account, which ties a shared tool to whoever happened to create it and
breaks when they leave.
## Decisions
[decisions]: #decisions
Settled by the owner on 2026-10-31.
1. **The owner is responsible, so a personal agent inherits.** On every
repository within its scope, a personal agent's letters are its
operator's effective letters, computed at each check, unless the
operator narrowed it there. It never holds more than its operator; an
operator losing a letter takes it from the agent in the same instant.
2. **Two kinds, three scopes.**
| Scope | Personal agent | Dedicated agent |
|---|---|---|
| Site | its owner's letters on every repository, and site powers if the owner has them and opted in (decision 4) | what site admins grant it (`zeitgeist` today) |
| Team | its owner's letters on the team's repositories | what the team's owners grant it, on the team's repositories |
| Repository | its owner's letters on that repository | what the repository's admins grant it, there only |
3. **A grant narrows.** Today's per-repository grant (`agent.grant`)
keeps its storage and its clip to the operator, and changes meaning:
where the operator wrote a string, the agent holds that string
(intersected with the operator, as now); where none is written it
inherits. Each personal agent has one switch, **inherit** or **only
where set**, the second turning the grants into an allow-list.
4. **Site powers by inheritance are opt-in.** A personal site agent of a
site admin is a site admin only when its owner chose that at
creation, behind a confirmation, and the fleet's People page marks it
"site admin by inheritance". A leaked token of such an agent can
manage the whole forge, so it never happens by default.
5. **Existing agents do not widen.** Every person's agent today becomes
a personal site agent set to **only where set**, keeping its grants.
Its operator switches it to inherit when they choose.
6. **Dedicated agents answer to someone.** A repository agent is created
by a holder of `a` on the repository; a team agent by one of the
team's owners; a site agent by a site admin (RFC 0021's path for forge
agents). The creator is answerable and can hand that to another admin
or owner of the same scope. The agent goes with its repository or
team; anyone who could create one may disable it.
7. **A dedicated team agent is held under its team.** On each of the
team's repositories it may be granted at most the role the team holds
there.
8. **Tokens need no upkeep.** One **Revoke tokens** button per agent
revokes every token it has and issues a fresh one in the same step.
One **Revoke all my agents** button on a person's own account (0021's
revoke-all). No expiry date to choose and nothing to renew: a token
lives while it is used and lapses after 90 idle days. When a person
leaves, their personal agents' tokens end with them (decision 10); a
dedicated agent's tokens stay with it. A site admin may revoke any
agent's tokens.
9. **The record says who it was for.** Wherever an action is shown, a
personal agent reads "`curator` for `dmestas`" and a dedicated one
"`release-bot` for `quarry`". A check-in keeps the agent as its user,
with the operator shown beside it, never substituted.
10. **An owner leaving ends their agents.** Disabling or deleting a
person disables their personal agents and their tokens at once
(0021's cascade, unchanged). A dedicated agent whose answerable
person leaves passes to its scope's other admins or owners; with
none, a site admin is asked.
11. **Agents do not make agents.** Only a person creates a personal
agent, and only a person holding the scope's admin letters creates a
dedicated one, so every line of responsibility is one step long.
12. **Limits.** 0021's cap on agents per person applies to personal
agents; dedicated agents get a cap per repository and per team, set
by site admins.
13. **`zeitgeist` is unchanged:** a dedicated site agent, answerable to
`dmestas`, holding what it holds today.
## The model
[model]: #the-model
### Scope and kind are columns of the agent
An agent account gains two facts beside 0021's `operator`:
| column | values | meaning |
|---|---|---|
| `kind` | `personal`, `dedicated` | who it belongs to |
| `scope` | `site`, `team:<name>`, `repo:<id>` | where it reaches |
For a personal agent the operator is a person and the scope bounds what
it inherits. For a dedicated agent the operator is the scope itself
(`forge`, the team, the repository), and `answerable` names the person
who answers for it, as forge agents do today.
### Effective letters
For a personal agent P with operator O on repository R:
- outside its scope: nothing;
- **only where set** and no string on R: nothing;
- a string S on R: `S ∩ effective(O, R)`, as 0021 computes now;
- **inherit** and no string on R: `effective(O, R)`.
For a dedicated agent D on R inside its scope: its own string on R, and
for a team agent at most the team's row on R (decision 7). Outside its
scope: nothing.
Both are computed at each check, never copied, so there is no stored
state to fall out of date when an owner, a team or a role changes.
### Site powers
The site-admin flag is not a letter, so inheritance does not carry it on
its own. A personal site agent carries it only with the opt-in from
decision 4, and only while its owner holds it. A personal team or
repository agent never does.
### What does not change
The deed rules (0021 [What an agent may hold](0021-agent-accounts.md#what-an-agent-may-hold)),
run tokens for CI, the token value's shape, per-token narrowing by
repositories and ceiling, sync and API scopes, and the audit trail are
0021's as written. A token can still narrow its agent further; it can
never widen it.
## Tokens
[tokens]: #tokens
- **Revoke tokens** on an agent: one transaction revokes every token of
that agent and mints one replacement with the same name, scope,
repositories and ceiling as the most recently used; the value is shown
once. A person with nothing to paste it into can ignore it, and it
lapses on its own.
- **Revoke all my agents** on a person's own account: 0021's
`agent.token.revoke_all`, reissuing nothing.
- **Idle lapse** replaces required expiry. `last_used` already exists; a
token unused for 90 days fails every door with the refusal a revoked
token gets, and the daily sweep removes it. No expiry is asked for at
minting. 0021's one-year maximum goes with it.
- A personal agent's token is as strong as its owner within its scope.
That is the price of inheritance, and one-click revocation is what
keeps it acceptable.
## Bridged chat
[chat]: #bridged-chat
The chat bridge's rule stands: a bridged channel is readable only by
those holding chat (`C`) on the repository, and the bridge stops if chat
is opened to more than named people. A personal agent holding `C` by
inheritance reads it exactly when its owner may. Linking a person's
upstream Fossil or GitHub login to their account, so that reading can
follow who holds chat upstream, is a later RFC.
## Migration
[migration]: #migration
- Every agent with a person operator gets `kind = personal`,
`scope = site`, and **only where set**. Its grants are unchanged, so
its reach is unchanged.
- Every forge agent gets `kind = dedicated`, `scope = site`, operator
`forge`, `answerable` as today.
- Existing tokens keep working. A token with an expiry keeps it; a token
with none lapses after 90 idle days from the day this ships.
- The "Your agents" section gains the inherit switch, the scope at
creation, and the Revoke tokens button.
## What the forge shows
- **Your agents** (personal): each agent's scope, its switch, its grants
as narrowings, Revoke tokens, and one Revoke all my agents.
- A repository's and a team's settings gain **Agents**: their dedicated
agents, who answers for each, a create form for those who may, and
Revoke tokens.
- The People pages show an agent with its operator and kind ("for
`dmestas`", "for `quarry`"), and "site admin by inheritance" where it
applies.
## What is not proposed
- Linking upstream identities (Fossil, GitHub) to forge accounts: a later
RFC.
- An agent as a team member in its own right.
- Agents creating agents.
- Inheriting the deed, which no agent holds.
## Build order
1. The effective-letters rule with the inherit switch, behind the
existing intersection; migration as above. Built: an `inherit`
column whose default of 0 is the migration, `agent.inherit`, and
narrowing on the agent's page. `kind` and `scope` wait for step 3,
the first step that reads them: until then every person's agent is
personal at site scope, and the operator column already says which
kind an agent is.
2. Idle lapse and Revoke tokens; remove the required expiry from minting.
3. Personal team and repository scopes in "Your agents".
4. Dedicated repository agents: creation, answerable, the repository's
Agents section.
5. Dedicated team agents, held under the team's row.
6. Site powers by inheritance, behind its opt-in.
## Testing
- A personal agent set to inherit holds exactly its owner's letters on a
repository with no string, and loses one in the same check its owner
loses it.
- **Only where set** holds nothing where no string is written; a migrated
agent's reach before and after migration is identical on every
repository.
- A personal repository agent holds nothing outside its repository; a
personal team agent nothing outside the team's repositories.
- A dedicated team agent granted admin on a repository where the team is
a developer holds developer.
- A personal site agent of a site admin is not a site admin without the
opt-in, is one with it, and stops being one when its owner does.
- Revoke tokens leaves one fresh token and fails every earlier one;
Revoke all my agents fails every token of every agent of that person.
- A token idle for 90 days is refused; one used on day 89 lives on.
- Disabling an owner disables their personal agents and tokens; a
dedicated agent whose answerable person is disabled passes to another
admin of its scope.
- An agent's attempt to create an agent is refused.