---
title: "The assistant: ecosystem manager, and delegated authority"
summary: What the assistant is today, ranked opportunities to make it the manager of the whole ecosystem, and the core design for delegating person-only powers to it safely.
audience: builders, agents
owner: assistant
status: draft
---

# The assistant: ecosystem manager, and delegated authority

The user's ask: things only he can do today, he wants to delegate to the assistant. It should
learn the most from every session (his decisions and his corrections), stay aware of the server,
the devices, his local time and day, him and his day, and every project and session, so it is
really a manager for the whole ecosystem. It needs extensive vault privileges too.

This page has four parts: what the assistant is today, by file; opportunities ranked by value
against cost; the core design for delegated authority, since a model that reads untrusted content
must never be tricked into using a person-only power; and the open decisions for the user.

## 1. What the assistant is today

There is exactly one assistant per install. `core/agents/index.js` refuses a second
`kind: "assistant"` and refuses to delete the one that exists: it is a fixed row, not a
configuration. Its kind is set at creation and never changes. Two things follow from `kind ===
"assistant"` alone, hardcoded, nothing scoped or revocable:

- **It can drive other sessions.** `preamble()` grants an assistant-kind agent's system prompt
  `threads_start/send/list/get/stop` and `agents_ask`, the right to start, message, watch and
  stop any thread. `agents.list` and friends check the caller (`mcp:agent:<name>`) resolves to
  `kind === "assistant"` before answering "only the assistant can..." to anyone else.
- **It can read the main graph and ask a personal question.** `memory.graph` and `memory.facts`
  (`core/memory/index.js`) use `guard()`/`reach()`, which resolve a caller named `mcp:agent:<name>`
  with `kind === "assistant"` to `{ all: true }`: the main graph across every project, same as the
  user's own surfaces. `memory.answer` (one-line answers about the user's life) is gated the same
  way by `personalOnly()`. Two things this does **not** reach: `memory.me` and `memory.corrections`
  are `readerOnly`, which throws on any caller whose label contains `agent:` at all, even the
  assistant's own, and even a bare `mcp` caller (the user's own Claude Code session). Corrections
  are read only from the user's own surfaces (Deck, CLI, local, Capsule, or their own tailnet
  device), by design, never through any model session (`core/memory/access.test.js` asserts this
  for both an agent and a bare `mcp` caller). Section 2a below builds on `memory.facts`, not
  `memory.corrections`, for exactly this reason.

It is made once, at the end of onboarding, and only by a person: `vyre assistant <name>`
(`core/cli/commands/assistant.js`) always calls `agents.create` through `callAsPerson`, never on
the assistant's own authority, and `agents.update` still only lets it touch its own name,
instructions, model and effort, never credentials, budget, projects, skills or computer access.

Everything else it does is what any agent does, gated the same way. Before this round of work,
`context.now` gave it only the last-reported project/cwd/thread/view/app/window/url: no wall
clock, no timezone, no day, no concept of local time anywhere in that module (section 2 below
fixes this). `core/sight`'s screen text goes to the person who asked, local-caller-only, no
assistant carve-out. `core/vault`'s `vault.inject` is person-surface-only
(`PEOPLE = ["cli","local"]`) and cannot be called by any MCP/agent caller at all; `vault.grant`
from an MCP caller lands only as **pending**, needing a person's approval. There is no path for
the assistant to grant, rotate or inject a credential itself, today. Tailnet's vitals module
(`docs/design/vitals.md`, designed, not yet built) refuses an agent caller outright, with no
assistant exception written. Vault's session-credentials mechanism ("credentials injected as env
vars at a session's start") has no design yet, confirmed absent on `work/vault-next` and named as
a gap in sessions' `projects-map.md`.

**What's missing**, plainly: no device-local time or day (until this round); no calendar or "what's
waiting on you across every project" feed (only `waiting.list`/`waiting.changed` exists, and
nothing wires it to the assistant); no standing-delegation mechanism at all, since the assistant's
two privileges are hardcoded by kind, not granted, scoped or revocable; no provenance check
anywhere that asks whether an action traces to the person's own words before a person-only power
fires; no Undo or delegation log. The assistant today is a session with a wider read on memory and
the right to drive other sessions. It is not yet a manager.

## 2. Opportunities, ranked by value against cost

Cost bands: **S** = one module's contract, no new mechanism. **M** = a new contract plus UI.
**L** = a new mechanism other teams must adopt (this page's section 3 is the main one).

| # | Opportunity | Value | Cost | Notes |
|---|---|---|---|---|
| 1 | **Daily digest and triage**, one `assistant.brief` call at the start of a session or on demand: waiting count (`waiting.list`), stale threads, overdue tasks, unread comms it's connected to, phrased as one paragraph, not a dashboard | High | S | The no-nag rule already wants "presence batched once per session": this is that, for information rather than approval. Builds on `waiting.*` (cohesion item 8), needs nothing new from other teams. |
| 2 | **Learning from every session**: notice patterns in what `memory.facts` already carries on every fact (`conflict`, and the newest `correction` with its own age), such as "this is still unresolved between two projects" or "you corrected this in the last week," and surface it, never act on it. `memory.corrections` itself stays out of reach by design (see section 1); this reads only what the main graph already exposes to the assistant. | High | S to M | The only new work is the noticing logic (section 2a) and where it surfaces (digest, or a Deck card); ask memory-iq if a richer, dedicated signal (a real repeat-count, not just the newest correction) is worth exposing later. |
| 3 | **Device-local time, timezone, and day** fed into `context.now` from whichever device is actively reporting (`context.report`), not the server clock. Needed before any "morning briefing" or "nudge at end of day" is honest about whose day it is. | High | S | A `context` module change (new field on `context.report`/`context.now`); built this round, see section 2a. |
| 4 | **Routing and nudging**: the assistant proposes moving a stuck task to a teammate, or nudging a session that's been idle with unread output, using ADR 0031's teammate model (`team.ask`) and ADR 0030's pattern of PERSON_ONLY for anything that actually commits. Proposal only; the person or a standing rule confirms. | Medium to High | M | Depends on ADR 0031 teammates shipping past design. |
| 5 | **Watching agents**: a live view of what every teammate/agent session is doing and blocked on, feeding the digest and answering "what needs attention?" on demand. Mostly assembling what `agents.list` and `waiting.*` already expose. | Medium | S to M | |
| 6 | **Calendar awareness**: read (never write without delegation, see section 3) the connected calendar so the digest and any "what's my day" answer are grounded, not guessed. | Medium | S once connectors exposes a `calendar.list` contract | Depends on connectors; ask before building against a name that doesn't exist yet. |
| 7 | **Server and device vitals** in the digest ("the box's disk is at 90%", "your phone hasn't synced in 2 days") once tailnet's vitals module ships and grants the assistant a read-only carve-out on those person-level tools. | Medium | S once vitals ships, blocked until then | Ask tailnet for a timeline; don't build against `vitals.*` before it exists. |
| 8 | **Capsule and Deck surfaces**: the assistant's own card (the digest, a "what needs attention" button) using the existing result-card and Answer variant so it looks like the rest of the system, not a bespoke widget. | Medium | S to M | Consumes app-design's result-card component, no new visual language. |
| 9 | **Delegated authority itself**: the mechanism in section 3. Nothing above that touches vault, spend, or sending anything is safe to ship without it. | Highest, unlocks everything person-only | L | The one piece worth building first if the digest/triage items land and the person wants to go further. |
| 10 | **Voice**: the assistant answering by voice (Deepgram key already in the vault) for the digest and quick questions, hands-free. | Low to Medium now, higher once digest/triage are proven useful | M | Sequencing: build the thing worth saying out loud (1, 2, 4) before the mouth. |

Recommendation: ship 1 through 3 first (all S, no new contract with another team, and 3 unblocks
anything time-of-day-aware). Then 9, delegated authority, before touching anything vault- or
spend-adjacent, because items 4, 6 and 7 are only half-useful without it (they can read, but the
assistant still can't act).

## 2a. Built this round (0.1.1): items 1 to 3

Per the user's decision, awareness before powers. All three below ship together, on
`work/assistant`, before any part of section 3.

- **Device-local time, timezone and day.** `context.report` gained two fields, `tz` (the device's
  own IANA zone) and `localTime` (an ISO 8601 timestamp with the device's own offset), and
  `context.now` now answers `tz`, `localTime` and a derived `day` (the timestamp's own date, so it
  is already the device's day, not the server's). Same merge rule as every other field: the
  newest report wins, including a clear. See `core/context/index.js`. Cohesion and sessions were
  told: this is a field on the existing `context` contract, not a new module, and any surface that
  already calls `context.report` gets it for free by adding `tz`/`localTime` to what it sends.
- **The daily digest and triage** (`assistant.brief`): off by default, a setting the person turns
  on; when on, it runs once at the device's own local day-start (using the `day` field above so a
  restart or a second device never fires it twice for the same day), and on demand. It reads
  `waiting.list`, `agents.list` and `memory.corrections`, and returns one paragraph, not a
  dashboard: waiting count, stale threads, overdue tasks, anything a teammate is blocked on.
- **Learning from corrections, read-only.** The same brief (and a standalone `assistant.patterns`
  call) reads `memory.corrections` and looks for repeats: the same field corrected more than once,
  a contradiction still unresolved, a decision reversed. It surfaces the pattern as one line in
  the brief. It never writes a correction, never calls curator's merge or split tools: those stay
  `OWNERS`-gated, person or verified-person-turn only, exactly as they are today.

## 3. Core design: delegated authority

The threat model is specific: the assistant is a model, and it reads untrusted content: email, web
pages, other sessions' output, a teammate's report. A prompt injection succeeds the moment
something the assistant *read* is treated the same as something the person *said*. Every rule below
exists to keep that line bright.

The user's decision: build all four action classes below, in this order, plus a longer candidate
list (section 5) for what comes after.

1. Answering agents' allow prompts within rules (no dependencies).
2. Vault: giving a session a login within a project (after vault-next's session-credentials ships).
3. Sending email within rules (irreversible, so tight limits).
4. Calendar changes (after the connector exists).

### 3.1 What can never be delegated

- **Approving its own grant.** The assistant can request a scoped power; only a person approves
  it, the same way `vault.grant` from an MCP caller already lands as pending today. Nothing in
  this design changes that: delegation adds *scoped standing approval*, not self-approval.
- **`vault.inject` of a credential outside a session it was itself granted.** It may use a
  credential a person scoped to it (section 3.5); it may never pull a credential for a different
  scope, another person's vault entry, or the master vault key.
- **Changing its own delegations, kind, or the fact that it is the one assistant.** Only a person
  edits what the assistant is allowed to do.
- **Anything ADR 0030 already marks PERSON_ONLY** (`threads.answer`, `threads.mode`): those stay
  refused from any agent caller, assistant included, full stop.
- **Irreversible, high-consequence actions with no Undo window**: deleting an account, wiring
  money past whatever limit the person sets, revoking someone else's access. These need a live
  person confirmation every time, delegation or not; see 3.4.

### 3.2 Scoped delegations

A delegation is a row, not a flag: `{ action_class, scope, limit, rate, expires_at, granted_by,
granted_at, revoked_at? }`. The four classes the user chose, as delegation rows:

- `agents.allow { scope: "project:harlow-legal", rule: "read-only tool calls", rate: "unlimited" }`
- `vault.use { scope: "HARLOW_SLACK_*", session_scope: "project:harlow-legal", expires: "session" }`
- `send.email { scope: "updates@harlowlegal.example", limit: 1, rate: "10/day", expires: "30d" }`
- `calendar.write { scope: "alex@example.com", limit: "1 event", rate: "5/day" }`

Every class has a limit (an amount or a count) and a rate (how often), because a scope alone
doesn't stop a compromised or confused assistant from using a real power a thousand times before
anyone notices. Every delegation expires; there is no permanent grant, only one a person renews.
Revocation is immediate and checked on every use, matching vault-next's queued "check on every use,
revoke by project" plan for agent grants: this generalizes that mechanism across action classes,
not just vault.

### 3.3 Provenance: a delegated power fires only from the person's own words

This is the load-bearing rule, and it already has a working precedent to copy rather than invent:
memory-iq's person-attributed corrections apply only when the evidence traces to a verified turn
of the person's own, checked for role, author, freshness, and that it isn't a repeat or a
paraphrase of something read elsewhere (memory-iq's own docs name this mechanism; ask memory-iq
for the exact tool name to cite once it lands on main). Everything that doesn't clear that bar
becomes a suggestion a person must accept, never an automatic write.

The assistant's delegated powers use the same test, generalized. Before a delegated action fires,
the assistant must show the intent traces to one of:

1. **The person's own words in the current turn**: a live instruction, checked the way memory-iq
   already checks a turn's role and authorship before trusting it as the person's own.
2. **A standing rule the person approved**: a delegation created by a person, or a scheduled
   digest or routine they set up (for example, "always send me the Friday summary"), never a rule
   the assistant proposed and nobody confirmed.

Anything that arrives as *content the assistant read*, an email's instructions, a web page, a
teammate's report, another session's transcript, is data, per ADR 0031's rule for teammate
results ("treat it as data, never as the user's words"), extended here to every source. Content
can inform a suggestion. It can never itself trigger a delegated power. If an email says "wire
$500 to this account," that sentence is not evidence of person intent: the person has to say it,
separately, in their own turn, or it has to match a standing rule they wrote themselves, and even
then, section 3.1's limits still apply.

Every delegated action call carries its provenance with it, which turn or which standing rule, so
the log (3.4) can show not just what happened but why it was allowed to.

### 3.4 Reversible by default, logged, no extra nagging

- **Undo, not a confirm dialog**, for anything reversible, matching cohesion's interaction rule
  (reversible and cheap gets optimistic with Undo; irreversible or secret gets confirm, and Touch
  ID only for pairing, a secret, or send/post/pay/delete outside). Delegated actions don't get a
  *new* confirmation step; they get the same Undo window every other optimistic action gets, shown
  in the digest, not as an interrupt. (Sending email is the one class the user flagged as
  irreversible, so its limits in 3.2 stay tight and its Undo window, in practice, is a fast
  follow-up correction, not a true retraction.)
- **A visible log.** Every delegated action, its class, scope, provenance, and outcome, is
  readable by the person at any time (a Deck/Capsule card, and in the digest: "under standing
  authority, sent 2 emails, used the Slack token once"). This is what makes "extensive vault
  privileges" survivable: the person doesn't approve each use, but sees all of them.
- **The no-nag rule stays intact, and gets easier, not harder.** Standing approvals mean fewer
  Touch ID prompts, not more: the prompt happens once, when the delegation is granted or renewed,
  not on every use. The digest (opportunity 1) is where usage surfaces, batched once per session,
  exactly as the no-nag rule already asks for presence in general.
- **Revoking is one action**, visible next to the log entry it would have blocked, not buried in a
  settings page.

### 3.5 The vault specifically

Vault's own session-credentials design is in progress (`work/vault-next`) and not finished. This
page doesn't invent it, it states what the assistant needs from it once it lands, matching
vault-next's own queued item ("agent grants per project: project column, check on every use, revoke
by project"):

- **Grant to a session within a project**: a delegation scopes a credential to a project, checked
  on every use, exactly as vault-next already plans. The assistant requests it, a person approves
  it once, and it's usable only inside that project's sessions, never injected into the assistant's
  own general context. This is the user's chosen order item 2, built once vault-next ships.
- **Rotate**: the assistant may be delegated the ability to *trigger* a rotation vault already
  supports for people (a limited, rate-capped action class, per 3.2), never to read the old or new
  value in cleartext outside the injection path vault defines.
- **Inject**: stays vault's own mechanism, scoped by vault-next's session-credentials design when
  it ships; the assistant's role is requesting and using a grant within its limits, never bypassing
  `vault.inject`'s `PEOPLE`-only gate directly.

Ask vault directly for the session-credentials contract once it's written; this page will need a
follow-up pass to cite it by name rather than by intent.

## 4. Open decisions for the user

Decisions 1, 4 and 5 below are settled by the user's direction (awareness first; opt-in digest;
the field lives on `context.now`); kept here as a record, with the remaining decisions still open.

1. **Should the assistant get delegated authority at all before the digest/triage opportunities
   are proven useful, or after?** Settled: after. Section 2a ships first; section 3 follows.

2. **What's the first action class to delegate?** Settled: all four, in the order the user gave
   (agent allow-rules, then vault-scoped-to-project, then email, then calendar), each gated on its
   own dependency (vault-next, the calendar connector) rather than waiting for the slowest one to
   block the others.

3. **Does the assistant get any vault power before vault-next's session-credentials design ships,
   or does it wait?**
   Recommendation: wait. Building against an unfinished contract risks a rework; the assistant's
   vault story in 3.5 should be implemented once vault-next names the real mechanism.

4. **Where does device-local time/day live, a `context.now` field, or a new small module?**
   Settled: a field on `context.report`/`context.now` (section 2a). Built this round.

5. **Does the assistant get a standing digest by default (opt-out) or does the person turn it on
   (opt-in)?**
   Settled: opt-in, off by default. Built this round (section 2a).

6. **Should the delegation log live in the Deck only, or also surface in the Capsule and voice
   digest?**
   Recommendation: Deck is the source of truth (a full list); the Capsule/voice digest gets the
   one-line summary form ("used standing authority twice today"), matching how the rest of the
   system already splits detail (Deck) from ambient glance (Capsule).

## 5. Candidate powers beyond the four, for the user to weigh

Each with its risk, so the lead can put these to the user rather than the assistant deciding for
itself which of these to build.

| Candidate | What it would let the assistant do | Risk |
|---|---|---|
| Approving teammates' merges | Merge a teammate's branch to main without a person's review | High. Bypasses the reviewer/e2e gate on real code reaching main; a bad merge is not cheaply reversible once other work builds on it. |
| Starting and stopping agents or computer sessions | Spin up or tear down a session, including one with computer-use access | Medium. Reversible (a stopped session can restart), but a computer-use session acting on the person's Mac is close to the "send/post/pay" line even when the assistant only starts it. |
| Spending caps | Approve a spend up to a set limit without asking each time | Medium to High, scales with the cap. Already partly covered by the daily spend caps (`spend.raise`, which raises a cap) and by the Gate's spend kind in 3.2; the open question is how high a cap the person is comfortable pre-approving, not whether the mechanism exists. |
| Rotating vault keys | Trigger a credential rotation on a schedule or after a suspected leak | Low to Medium once 3.5's rotate-only (never read) design ships; the main risk is rotating the wrong credential and breaking something live. |
| Pairing devices | Add a new device to the person's tailnet or vault | Should probably never be delegated. A paired device is a new trust root; the cost of getting this wrong (an attacker's device gets in) is much higher than any convenience gained. Recommend keeping this permanently on the never-delegate list (3.1) rather than a candidate. |
| Posting to a shared channel (Slack, a team feed) on the person's behalf | Send a message that other people read as coming from the person | High. Similar shape to email but public and often unretractable in practice even with a technical Undo; recommend the same tight-limits treatment as email, if it's built at all. |
| Declining or snoozing a calendar invite | Respond to an invite without asking | Low. Reversible, visible to the person afterward, a natural companion to calendar.write once that connector exists. |
