feat: conversation review — a nightly report on a supervised person's conversations
Nightly Build / build (push) Successful in 7m40s
Nightly Build / build (push) Successful in 7m40s
The first AgentScope::PerSubject system agent, and the reason that scope exists. Once a night, for each person with a supervision edge, it reads every message that person and the assistant exchanged since the previous review — across all their conversations — and writes one report for the people who supervise them. Schema (all registry except reports): - supervision(subject_user_id, supervisor_user_id): the generic §0.1 edge, answering both 'whom does a background agent look at' and 'who may read what it produced', with real FKs so deleting a user cascades both ways - system_agent_coverage(agent_id, subject_user_id, covered_through): the per-subject watermark that makes 'everything since last time' a window — neither system_agent_runs (history for humans) nor system_agent_state (advances before the work), and advanced only on a completed pass so a crash re-covers instead of skipping - reports (owner schema, the second two-homes table after memory_docs): instance rows land in system.db, deliberately cleartext to the box owner, who is the intended reader (§2); the subject cannot see them structurally The pass reads the subject's database inside a supervisor's runtime, so the ephemeral session and run row land in the watcher's file; iteration is over subjects, so two parents watching one child get one review; and the subject need not be logged in when their space is unencrypted — via the new UserManager::open_unencrypted, which refuses an encrypted user outright (no key to be had) and never registers the pool as unlocked. The agent declares the new AgentMeta flag allow_tools: false, so its turn gets an empty tool registry — nothing for a prompt injection in the transcript to call — and produces its report as its final assistant message, read back from chat_history and parsed (NOTHING_TO_REPORT sentinel, no row on quiet days). chat_history::conversation_window is the transcript query; its four filters (non-ephemeral, depth 0, non-synthetic, non-empty) each guard a specific way the review would otherwise be wrong, and tool calls are absent by construction. Cadence is Run at (hour) rather than Interval — 4am local by default — with due-ness answered inside has_work against the coverage watermark, so a machine off for three days covers the whole stretch in one pass. Reports announce ReportCreated on the system bus (no subscriber yet). run_ephemeral_turn gains a per-pass system_substitutions map, which the review uses to hand the model the subject's profile under __SUBJECT_PROFILE__ — the system-context substitutions describe the session owner, the wrong person here. docs/system-agents.md gains the conversation review section; CLAUDE.md documents the scope, the tables and the tool-less design.
This commit is contained in:
+1
-1
@@ -12,7 +12,7 @@ This index will grow over time. Right now it covers memory, projects, system age
|
||||
| --- | --- |
|
||||
| [memory.md](memory.md) | Private and shared memory: what goes where, the indexes and history log, why some shared facts can't be changed on request |
|
||||
| [projects.md](projects.md) | Projects: shared folders with their own assistant chat, a live file explorer, and member sharing |
|
||||
| [system-agents.md](system-agents.md) | Background agents that run on a schedule (event triage, the two memory lints): what they watch, why they only ever report, why a run can be skipped, and their settings |
|
||||
| [system-agents.md](system-agents.md) | Background agents that run on a schedule (event triage, the two memory lints, the nightly conversation review of a supervised account): what they watch, why they only ever report, why a run can be skipped, and their settings |
|
||||
| [settings.md](settings.md) | The admin's Config page: interface language, the compaction model picker, debug mode |
|
||||
| [access.md](access.md) | Who can use which plugin or connector: the open default, removing access per person, and the role switch that keeps children out of it |
|
||||
|
||||
|
||||
+30
-6
@@ -2,19 +2,20 @@
|
||||
|
||||
A **system agent** is an assistant that runs in the background on someone's behalf, without being asked. Nobody starts it and nobody is waiting for its answer: it wakes up on a schedule, looks at something, and gets in touch only if there is a reason to.
|
||||
|
||||
There are three:
|
||||
There are four:
|
||||
|
||||
| Agent | What it watches | How often |
|
||||
| --- | --- | --- |
|
||||
| **Event triage** | events arriving from that person's connectors | every few minutes |
|
||||
| **Private memory lint** | that person's own memory notes | weekly |
|
||||
| **Shared memory lint** | the group's shared memory | weekly |
|
||||
| **Conversation review** | the conversations of someone who is supervised | nightly |
|
||||
|
||||
They share three habits worth stating once, because they explain most of what people ask:
|
||||
|
||||
- **They only read and report.** None of them changes anything. If something needs doing, they say so and the person decides.
|
||||
- **They only read and report.** None of them changes anything. If something needs doing, they say so and a person decides.
|
||||
- **An empty run is a correct run.** They are not supposed to find something every time, and they stay quiet when they don't.
|
||||
- **They run per person, on that person's own things**, with one exception noted below.
|
||||
- **They run per person, on that person's own things** — except the last two, which are about the group and about someone else respectively.
|
||||
|
||||
## Event triage
|
||||
|
||||
@@ -45,6 +46,23 @@ There are two of them because the two stores are not the same job.
|
||||
|
||||
The shared store belongs to nobody in particular, so that pass runs **as the admin** and its report goes to them. That is about who can act on it, not about privacy: everything in shared memory is already readable by every member.
|
||||
|
||||
## Conversation review
|
||||
|
||||
Some accounts are **supervised**: somebody else has agreed to keep an eye on how that person is getting on with the assistant. A child's account is the usual case, but nothing in the system says "child" — it is a link between two people, and an admin decides who is on either end of it.
|
||||
|
||||
Once a night, for each supervised person, this agent reads everything that person and the assistant said to each other since the previous review, and writes **one report** for the people who supervise them.
|
||||
|
||||
A few things about it are worth knowing, because they are the questions people actually ask:
|
||||
|
||||
- **One report per person, not per conversation.** Somebody may open five chats in a day. The review takes the whole stretch at once, so a subject that came up twice in two different places is something it can notice — reviewing each conversation separately would lose exactly that.
|
||||
- **It reads what was *said*, not what was *done*.** Messages only. If the assistant ran a search, opened a file or used a connector, none of that is visible to the review — not the action, not the result. It is told to say so rather than guess.
|
||||
- **It has no tools at all.** No filesystem, no memory, no connectors, no notifications. It reads the transcript it is handed and writes prose. It cannot act on anything it finds, and it cannot look anything up.
|
||||
- **Nobody is reviewed unless a link says so.** No supervision link, no review — being a child, or a member, or anything else is not what triggers it.
|
||||
- **The person being reviewed does not see the report.** It is stored for their supervisors. What they *should* know — and this is a matter for the household, not the software — is that their account is supervised at all.
|
||||
- **A quiet report is the normal one.** The agent is told to report what a careful adult would want to know and could act on: distress, someone pressuring or approaching them, a risk to their safety, money, a pattern repeating across days. It is told *not* to report swearing, sulking, secrecy, embarrassment, awkward questions asked out of curiosity, or homework they wanted done for them. Most nights it should conclude there is nothing to report, and that is the system working — a review that passed on everything would be read once and ignored afterwards.
|
||||
|
||||
The report is kept where the supervisors can read it rather than in the reviewed person's own space, and it names its window, so two reports never cover the same evening twice.
|
||||
|
||||
## Why a run can be missing
|
||||
|
||||
Users are handled one at a time, and a user is **skipped** if they have not logged in since the server last restarted.
|
||||
@@ -55,6 +73,12 @@ So if someone asks "why didn't it tell me about that email from this morning?",
|
||||
|
||||
Schedules are counted **per person from their own last run**, and they survive a restart — so a weekly pass stays weekly even on a machine that gets rebooted every few days.
|
||||
|
||||
The conversation review has its own version of both rules, because it is about one person but runs for another:
|
||||
|
||||
- The **supervised person does not need to be logged in** — provided their space is not encrypted, which is the normal setup for an account somebody else looks after. Without that, nothing could ever run at four in the morning. A supervised person who *has* an encrypted space is reviewed only while they are logged in, and there is no way around that: no password, no key, no reading it.
|
||||
- **At least one of their supervisors must be logged in**, because the review has to run somewhere. If none is, the review waits, and the next one covers the whole stretch that was missed instead of losing it.
|
||||
- If the machine was off at the scheduled hour, the review runs at the next start and covers everything since the last one — three days off means one report covering three days, not three missing reports.
|
||||
|
||||
## The System agents page
|
||||
|
||||
Sidebar → **System agents**. There is one tab per agent, plus **All**. A tab holds that agent's description, its settings (admin only), and its run history — because "why did this do nothing last night?" is usually half a settings question and half a log question.
|
||||
@@ -76,7 +100,7 @@ A run appears **only when there was something to look at**. Long gaps mean quiet
|
||||
Each agent's tab carries the same three settings, visible only to an admin:
|
||||
|
||||
- **Enabled** — turns that agent on or off for the whole instance, for everyone.
|
||||
- **Interval** — how long between passes for each person. Event triage is in minutes, the lints in days.
|
||||
- **Security group** — which tools the agent may use during a run. It is re-checked against each user's own role: if their role does not allow that group, their run uses their role's default group instead. Nobody's background agent gets more access than their role would give them.
|
||||
- **Interval** — how long between passes for each person. Event triage is in minutes, the lints in days. The conversation review has **Run at (hour)** instead: it runs once a day, after that hour, local time — 4am by default, so the report is waiting in the morning.
|
||||
- **Security group** — which tools the agent may use during a run. It is re-checked against each user's own role: if their role does not allow that group, their run uses their role's default group instead. Nobody's background agent gets more access than their role would give them. (The conversation review ignores this in practice: it is given no tools whatsoever, so there is nothing for a group to permit.)
|
||||
|
||||
There is no per-user on/off switch: if an agent is enabled, it runs for everyone who has logged in.
|
||||
For the first three there is no per-user on/off switch: if the agent is enabled, it runs for everyone who has logged in. The conversation review is the opposite — it runs for **nobody** until an admin creates a supervision link, and that link is what turns it on for one person.
|
||||
|
||||
Reference in New Issue
Block a user