---
title: Overseers — the work, the settings and the internals (part 3)
---

# Overseers — the work, the settings and the internals (part 3)

## What it is

This is part 3 of the [Overseers](overseers.md) 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`:

```jsonc
{ "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:

1. **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.
2. **The role** — the trusted per-type instructions above.
3. **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:

```jsonc
{ "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?".

```jsonc
{
  "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, or `crew:<id>` for one crew's private board. 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:

1. **Dead / paused / breaker-tripped** — the hold gate declines to hold; one deduped
   `overseer-offline` notice fires.
2. **Alive but silent** — the release sweep clears the hold at the window expiry.
3. **Clock jumped backwards** — the clock-jump floor force-releases any hold too far in the
   future.
4. **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](/src/main/services/overseer/overseer-keeper.ts)
- **Service** (spawn, liveness check, source labels) —
  [src/main/services/overseer/overseer-service.ts](/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](/src/main/services/overseer/overseer-bootstrap.ts)
- **The standing persona** (delivered as a system-prompt fragment on every turn) —
  [src/shared/overseer-persona.ts](/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](/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](/src/main/services/overseer/overseer-wake-schedules.ts)
- **Round brief and round record** (`GET /overseer/heartbeat` assembles the brief;
  `POST /overseer/round` records the submitted round) —
  [src/main/services/overseer/overseer-heartbeat.ts](/src/main/services/overseer/overseer-heartbeat.ts)
- **Action ledger** (append + read; every action with its reason) —
  [src/main/services/overseer/overseer-action-ledger.ts](/src/main/services/overseer/overseer-action-ledger.ts)
- **Hold gate** (never-held check, ceiling, fail-open) —
  [src/main/services/overseer/overseer-hold-gate.ts](/src/main/services/overseer/overseer-hold-gate.ts)
- **Never-held classifier** (superset of owner-critical phone-page list) —
  [src/shared/overseer-never-held.ts](/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/:slotId`
  and `DELETE /overseer/slots/:slotId`, all go through it) —
  [src/main/services/overseer/overseer-slot-writes.ts](/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](/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](/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](/src/main/services/overseer/overseer-board-read.ts)
- **Settings schema + defaults** —
  [src/shared/types/settings/overseer-settings.ts](/src/shared/types/settings/overseer-settings.ts)
- **Full invariants and the tests that lock them** —
  [.claude/memory/contracts/overseer-contract.md](/.claude/memory/contracts/overseer-contract.md)

## Related

- [Overseers](overseers.md) — part 1, what an Overseer is and the hub you reach it from.
- [Overseers part 2](overseers-part-2.md) — running one, and steering what it watches.
- [ai-spend-alerts.md](ai-spend-alerts.md) — the wider spend-warning surface the circuit breaker sits beside.

