Overseers — the work, the settings and the internals (part 3)
Part 3 of the Overseers page: the kinds of work an Overseer can hand out and the jobs it may start on its own, what it notices without being told, how agents hand notes to each other, the spend circuit breaker and the settings that govern it all — plus the internals for anyone working on it.
What it is
This is part 3 of the Overseers page — what an Overseer actually does with its time, and how the system is put together.
Where to find it
The Overseers hub and its settings; the last section is agent- and developer-facing.
How it behaves
The kinds of work an Overseer can hand out
There's a fixed list of roles, each with its own trusted starting job description:
| Doing the work | Checking the work | Working out what to do |
|---|---|---|
| Builder — builds new features | Reviewer — reviews one change for bugs and quality | Planner — turns a vague goal into a sequenced plan |
| Fixer — root-causes and fixes bugs | Tester — writes tests that would catch a regression | Researcher — investigates and answers, changes nothing |
| Tool Builder — builds scripts and harnesses other agents use | Auditor — sweeps a whole area against a standard and reports | First-Principles Evaluator — re-derives what it should be, ignoring how it is done today |
| Documenter — writes the docs a change leaves behind | Red Teamer — attacks a claim or design to find where it breaks | Pattern Finder — finds every place a recurring shape appears |
| Optimizer — makes working code faster or cheaper | Triager — gives every item in a pile a disposition | Janitor — clears out dead code and tech debt |
An Overseer can propose one of those workers through the ordinary agent-session route by
including agentType. An Overseer's own proposal is applied on the spot — it never waits for
a click: the Overseer is only running because you stood it up and gave it a standing job, so
that deployment IS the approval, and a card it could never clear itself would only stall your
own decision. An ordinary caller's proposal still lands in your inbox for you to approve. Either
way Omniscio rejects roles outside that Overseer's allow-list before the spawn happens, the
spawn stays attributed to the Overseer, and it is still bound by the per-token rate limit and
the spawn's own dollar/turn caps. An Overseer you have switched off in Settings, or whose
session you paused, gets no exemption — its proposal queues like anyone else's.
The list is a closed set and is append-only — a stored allow-list holds these ids verbatim, so renaming or removing one would silently un-tick it everywhere it was chosen. Adding a role is free: an Overseer with no allow-list set is unrestricted, so it can use a new role immediately.
Example proposal body for POST /agent/sessions:
{ "projectId": "<project>", "initialPrompt": "Fix the failing checkout test", "agentType": "fixer" }
agentType is optional for ordinary callers. When the caller is an Overseer, it selects and
enforces the role and prepends the trusted stock instructions; the Overseer's prompt supplies
the specific assignment, not a replacement role definition.
What a spawned worker is actually told
The prompt a worker starts with is assembled by Omniscio in three parts, always in this order:
- The shared preamble — the same for every role. It explains where the worker is, that an agent (not a person) wrote its job, that a human approved the spend, the standard it is held to (fix causes not symptoms · label every claim confirmed or hypothesis · believe the report · do the smallest thing that works · never guess in silence), what it may not do (start other agents, push or merge, restart the app, touch another session's work), and how to sign off — its final message is the deliverable, read later by someone with none of its context.
- The role — the trusted per-type instructions above.
- The job — the only part the Overseer wrote, and deliberately last, so the trusted text is already in place before anything agent-authored is read.
Two things follow from that ordering and are worth knowing:
- A worker never produces a Plain Speak card or spoken narration. Its messages are read back by an Overseer, not watched by a person, so the spawn sets the session's overlay-suppression flag and the preamble says so — the flag removes the injected fragments, and the instruction covers any sub-agent the worker runs itself, which the flag cannot reach.
- A job that tries to restate the rules is read as the instruction it is, not as the standard the worker is held to.
From the command line
GET /overseer/agent-types reads the full list of roles and their starting instructions.
POST /overseer/agent-types sets which roles one Overseer may use:
{ "slotId": "custom:<id>", "allow": ["fixer", "tester"] }
Leave the setting alone and every role is allowed; send an empty list and none are. Like assigning sessions above, this applies immediately from inside Omniscio and is queued for your approval from anywhere else.
Work an Overseer starts on its own
An Overseer can hold standing rules: jobs it starts by itself, without a person asking each time. Each rule names three things — an agent type (from the roles list above), the job that worker is given, and what makes the rule fire:
- Every N minutes — a cadence, from 1 minute to 24 hours.
- When something happens — either a session finishing, or a worker failing.
A rule does nothing until you approve THAT rule. This is the whole safety story, so it is worth being blunt: writing a rule down is not approval, switching on the Overseer is not approval, and switching on the feature is not approval. A rule with no approval on it is stored, listed on the Settings tab, and completely inert — it never spawns, on a timer or on an event. Approving the rule is a separate act, and it is the one that authorises the spend.
Every rule also carries a required maximum runs per hour — there is no version of a rule without a ceiling, because a cadence with no cap is exactly the failure this feature exists to avoid. Two things follow from the ceiling and from how the schedule is kept:
- Repeated events fold into one run. A worker that fails five times between two sweeps leaves one trigger standing, not five, so a flapping worker becomes one run rather than a spend loop.
- A window the app slept through does not pile up. The next run is anchored to now, not to the cadence that came and went while Omniscio was closed, so an app down for a day wakes to one run per rule — never one for every interval it missed.
A run also crosses the same rails work started by hand does: it is held back when the spend breaker is tripped, and it is booked against that Overseer's interrupt budget. The rule's agent type must still be in the Overseer's allowed types at the moment it runs, so narrowing that list stops a rule written before the change rather than letting it keep spawning the type you removed.
Where you edit them. The Overseer's own Settings tab has the list, under Jobs it runs on
its own: each rule's type, job, trigger, hourly ceiling, and the Approved to run switch that
is the approval to spend. Headlessly, POST /overseer/auto-actions creates or changes one rule and
GET /overseer/auto-actions reads them back. That read reports each rule's approved state
explicitly, because that flag — not the rule's presence — is the answer to "why did nothing
happen?".
{
"slotId": "custom:<id>",
"action": {
"agentType": "fixer",
"job": "Re-run yesterday's failing checkout test and fix the cause.",
"maxPerHour": 2,
"trigger": { "kind": "every", "minutes": 60 } // or { "kind": "on", "event": "workerFailed" }
},
"approve": true // the approval to spend; omit to store it inert
}
What it notices on its own
Every few minutes each Overseer reviews your recent activity looking for patterns — repeated failures, wasted effort, things that look stuck. Anything it concludes now arrives in your inbox. (Until 2026-08-29 those findings only went to an internal log, so nobody ever saw them.)
The same finding recurring doesn't post a new card each time — it groups onto the existing one. And these go through the normal screening like any other alert, so if an Overseer's own observations get noisy, it can batch and quieten them itself.
Each Overseer can also be capped on how many of these it may push to your inbox in an hour —
No limit, Max 5/hr, Max 2/hr, or Only when blocked. A finding held back by the cap is never
lost: it is still recorded (you can see it as a "deferred" entry below), it just waits rather
than interrupting you immediately. Whatever the cap, something the Overseer genuinely can't get
past on its own always reaches you regardless. Set it on the Overseer's Settings tab (May
interrupt you) or in the wizard's Rhythm step; the stored key is interruptBudgetPerHour.
Notes one agent hands another
There is a second, quieter channel between sessions: a note. Any agent session can hand another
a short note, and it costs nothing — no turn is started, no model call is made, and the recipient
is never woken. POST /session/:id/aside sends one, and GET /session/:id/asides shows what is
still waiting to be read.
The honest trade is the whole design, so here it is plainly. Because a note never interrupts, it is read at the recipient's next turn — folded into the next prompt that session receives for some other reason, and never the reason that prompt exists. A session that never runs again never reads it. That is the price of a note costing nothing, and it is why a note is a courtesy and never a way to hand out work: anything needing an answer, a decision, or an action is a real turn.
It is also one-way. The sender gets nothing back — no reply, no acknowledgement, no inbox of its own. Every note is labelled with who sent it and framed to the recipient as untrusted information from another agent, never as your words: a note that tries to give an order is read as a claim it has merely read, not a command it should obey.
Every alert is copied to the Overseer that owns the session
Turn that channel around and it is also how an Overseer hears about your inbox. Every alert you get is mirrored to the Overseer assigned to the session that alert is about, as one of these notes. Two things make that safe to leave running:
- Only the ASSIGNED Overseer gets it. A session nobody assigned has no note to send, and there is no fallback to the project's or the global Overseer — putting an alert about a session in front of an agent that does not watch it would be worse than not passing it on at all.
- The note says what it is. It is labelled an automated copy of an inbox alert, and it states in words that it is not a person writing and not a request or an instruction — so it can never read as something you asked for.
The mirror adds nothing to the alert and can never delay it: it is a courtesy copy left beside the card, and every failure in it costs the copy, never the card. It is also capped per session, so one noisy session cannot flood its Overseer's notes.
Seeing what they did, and where things went
Each Overseer's Board tab in the hub is the record of what has actually happened, newest first: everything it did — each row says in plain words where the alert ended up (passed it through to you, you never saw this one, folded it into a similar alert) with its stated reason, and each wake-up's round report — alongside the questions agents asked it and what it answered, the boards of its swarms, the shared agent board, and the direct messages among its sessions. Filter by channel to read one stream at a time.
Since Stage 2 (2026-09-08) those are all ONE store. Every peer message, every question an agent asked its Overseer and every answer it gave is ALSO written as a post on a channel — overseer:<slot>, swarm:<id>, dm:<a>|<b>, group:<uuid> for a small group chat among picked agents, crew:<id> for one crew's private board, repo:<projectId> for every agent working one repository, and the bare name overseers for the one room every crew's lead shares. The Board tab looks exactly the same; it just reads one table instead of merging four.
Two things that follow from that, and are worth knowing before you change anything here. Recording never delays or blocks a message — the board is the record, the delivery guarantee belongs to agent-to-agent messaging, and a board write that fails costs a row and never a message. An empty Board is not the same as a broken one — because one mirror now feeds every message kind, the read reports when that mirror has failed rather than rendering an empty feed that looks like a quiet day.
The action name alone ("release", "silence") says what happened to the alert but not whether it ever reached you, which is the thing you actually want to know — so the outcome is spelled out.
An action recorded before Overseers became plural belongs to no Overseer's Board rather than being attributed to a guess.
Spend — what each one has cost today shows in the hub; the shared daily ceiling in the fleet settings shows the day's total against the cap.
Under the hood
Every action — hold, release, merge, silence, escalate, kill, spawn, guidance given, settings
change, circuit-breaker trip, scheduled restart, an inbox interrupt (or one held back by the
hourly cap) — is appended to overseer_action_ledger
with a timestamp, the target (alert dedupKey / session id / setting key), a stated reason, and
the slot id of the Overseer that acted. Ledger writes are fail-open — a DB error never
crashes the Overseer.
One thing worth knowing: judging is done by the global Overseer, even for a card a per-project Overseer caused to be held. The trail says so honestly rather than crediting the project's Overseer with a decision it did not make.
The spend circuit breaker
The Overseer tracks its own trailing-hour spend against your rolling baseline. If spend exceeds your configured multiplier (default 4×), the breaker trips: the Overseer pauses itself, stops holding new alerts, and raises a never-held inbox alert so you can investigate. While tripped, the inbox behaves exactly as it would with the Overseer disabled.
The breaker fails closed on unmeasurable spend — a DB outage is treated as tripped rather than zero, because that is exactly when a stuck loop might be accumulating real charges.
Settings
All of it lives in the Overseers hub, in two places:
- Each Overseer's Settings tab — what it is called, what it is told to do, the sessions it watches, its own cadence and interrupt cap, the agent types it may run, its run switch, and Wakes up: the check-ins actually scheduled for it, whether each required one is covered, and the control that adds another.
- Fleet settings (the gear at the top of the list) — the settings that apply to every Overseer at once: whether they screen your inbox, how long they may hold an alert, how often they wake, how often they start fresh, the runaway-spending cut-off, the shared daily ceiling, the swarm defaults, and which projects get their own Overseer.
The hold window only appears while inbox screening is on, since it does nothing otherwise. The
master on/off (overseerEnabled) is the feature toggle and lives in Settings → Lab.
Changes take effect on the next keeper tick (within ~30 seconds) — nothing here needs a restart. The persisted keys behind those controls:
| Setting | Default | What it does |
|---|---|---|
overseerEnabled |
false |
Master on/off. Also the unreleased-feature reveal key (overseer). |
overseerGatekeeperEnabled |
true |
Whether the Overseer holds new inbox items during the window. Can be off independently. |
overseerHoldWindowMinutes |
10 |
How many minutes a new alert is held before the Overseer must decide. Range 1–120 min. |
overseerSweepIntervalMinutes |
10 |
Reads nothing — kept only so an existing config.json still parses. It gated a fleet sweep that was never started; an Overseer is woken by its own check-in schedules instead. |
overseerRestartHours |
24 |
How many hours between automatic session restarts (to prevent context growth). Range 1–168 h. |
overseerSpendBreakerMultiplier |
4 |
Multiplier on rolling baseline before the spend breaker trips. Range 2–50×. |
overseerAutoPerProject |
false |
Give every project its own Overseer. Off by default — each one is a real running session. |
overseerProjectOverrides |
{} |
Per-project enable/disable map. Wins over overseerAutoPerProject in both directions. |
overseerSlots |
{} |
Per-Overseer name + instructions, keyed by slot. A custom: entry here is a custom Overseer. |
overseerSessionAssignments |
{} |
Which Overseer watches which session, keyed by session id. One owner per session; a value naming an Overseer that no longer exists is ignored and routing falls back. |
overseerSelfCloneLimit |
(none) |
How many standing peers of ITSELF one Overseer may create on its own authority, across the whole box. Empty = no limit. It counts the peers that still exist, so deleting one frees the room back — a switched-off peer still counts. A built-in guard refuses a burst of three in an hour regardless. |
Fail-open design
Four independent fail-open paths ensure a broken Overseer can never silence your inbox:
- Dead / paused / breaker-tripped — the hold gate declines to hold; one deduped
overseer-offlinenotice fires. - Alive but silent — the release sweep clears the hold at the window expiry.
- Clock jumped backwards — the clock-jump floor force-releases any hold too far in the future.
- Alert storm — past the concurrently-held ceiling, nothing is held at all.
For agents
For agents and developers working in the repo
- Keeper (spawn lifecycle, scheduled restart, per-slot claim, backoff) — the same tick also holds the two spend gates and re-seeds a required check-in — src/main/services/overseer/overseer-keeper.ts
- Service (spawn, liveness check, source labels) — src/main/services/overseer/overseer-service.ts
- Bootstrap (the workdir, notes seeding and reading, and the per-slot briefing; the base persona is NOT written to disk any more) — src/main/services/overseer/overseer-bootstrap.ts
- The standing persona (delivered as a system-prompt fragment on every turn) — src/shared/overseer-persona.ts
- Wake types (the closed set, its per-type cadence, and the turn-origin stamp) — src/shared/overseer-wake-types.ts
- Wake schedules (the one writer that seeds, repairs and adds an Overseer's check-ins) — src/main/services/overseer/overseer-wake-schedules.ts
- Round brief and round record (
GET /overseer/heartbeatassembles the brief;POST /overseer/roundrecords the submitted round) — src/main/services/overseer/overseer-heartbeat.ts - Action ledger (append + read; every action with its reason) — src/main/services/overseer/overseer-action-ledger.ts
- Hold gate (never-held check, ceiling, fail-open) — src/main/services/overseer/overseer-hold-gate.ts
- Never-held classifier (superset of owner-critical phone-page list) — src/shared/overseer-never-held.ts
- Slot writer (the ONE place an Overseer is created, edited, switched or deleted — the hub's
wizard and Settings tab, and the CLI's
POST /overseer/slots,PATCH /overseer/slots/:slotIdandDELETE /overseer/slots/:slotId, all go through it) — src/main/services/overseer/overseer-slot-writes.ts - Migration cutover (canonical-liveness gate plus per-session conflict-safe assignment moves) — src/main/services/overseer/overseer-session-cutover.ts
- One-time spawn-path migration (terminates every live Overseer once on an upgraded install, so the keeper respawns it through the current path — into its project, with check-ins) — src/main/services/overseer/overseer-spawn-path-migration.ts
- Board read (the Board tab and
GET /overseer/:slotId/board) — since Stage 2 this is the action ledger plus ONE store, not a five-source merge: every peer message, ask and answer is recorded as a board post when it happens — src/main/services/overseer/overseer-board-read.ts - Settings schema + defaults — src/shared/types/settings/overseer-settings.ts
- Full invariants and the tests that lock them — .claude/memory/contracts/overseer-contract.md
Related
- Overseers — part 1, what an Overseer is and the hub you reach it from.
- Overseers part 2 — running one, and steering what it watches.
- ai-spend-alerts.md — the wider spend-warning surface the circuit breaker sits beside.
Last verified 2026-10-05