Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mnemom.ai/llms.txt

Use this file to discover all available pages before exploring further.

Sideband detection

Sideband detection is the asynchronous half of Mnemom’s Safe House. While the gateway intervenes same-turn at four checkpoints on each agent request, the observer runs a parallel cron sweep across teams of agents and emits advisories the agent receives at the start of its next turn. Four detector axes share this surface:
Source valueDetectorWhat it catches
sideband.driftDrift detectionAn agent’s behavior diverging from declared alignment over time (per-agent, trace-driven).
sideband.coherenceTeam coherenceA team’s pairwise governance scores dropping below threshold; conflict edges accumulating; outlier agents emerging.
sideband.fault_lineFault-line analysisA specific value dimension splits the team — some agents declare it, others miss it, others list it as a conflict.
sideband.fleetFleet patternsThe team partitions into incompatible clusters, the worst pair drops below threshold, or outliers emerge under cluster topology.
All four write to governance_signals (per ADR-048) — the operator-actionable observation surface. Surfaced via UI dashboard, webhook (governance.signal.fired), REST, and CLI. Not auto-injected into agent prompts; that architectural mis-layering is what ADR-048 corrected. See governance signals for the full layering and operator workflow.
Cutover note (2026-05-07): Detection logic on this page (cadence, fire conditions, fan-out fields) is unchanged. Only the delivery surface moved: from pending_advisories (which the gateway injected into agent prompts) to governance_signals (operator-facing). Pre-cutover pending_advisories rows with source LIKE 'sideband.%' will TTL out within 24 hours of the gateway-reader narrowing in mnemom-platform#247.

Why sideband

Some signals only emerge across time, across sessions, or across the team — not on any single request. A single trace might pass every gate. The pattern of dozens of traces, across half the fleet, can still be telling you the agents are drifting apart on transparency or that one agent has quietly stopped escalating high-stakes decisions. The runtime gateway can’t see those patterns — it sees one request, one agent, one moment. The observer has the wider lens: it reads the team’s alignment cards on a configurable cadence, runs the detectors, and writes findings to the carryover surface.
Sideband never intervenes retroactively. When a sideband detector fires on Tuesday, the agent’s Tuesday turns have already happened. The advisory lands on the agent’s next request — Wednesday’s first turn — as a system message at the start of context. From the agent’s perspective: “before you respond, here’s what we noticed about you and your team since we last spoke.” The gateway never goes back and modifies a delivered response.

The two-turn dance

Per ADR-040: runtime checkpoints intervene same-turn under enforce; sideband checkpoints intervene cross-turn via the advisory carryover.
turn N: agent works as usual; observer's cron sweep detects something
        → row written to pending_advisories with source = sideband.<axis>

turn N+1: gateway reads pending_advisories at the start of the request
          → injects the advisory text as a system message
          → agent sees it, references it, responds
          → row marked status = consumed
The advisory text follows a stable wrapper: [Mnemom advisory: <one-sentence finding>. <one-sentence recommendation>.]. The bracket wrapper is what enables Safe House’s I10 invariant (user-visible-explanation 100%) to recognize an injection happened — the gateway suffix-injects its own marker if the wrapper is missing.

How the detectors are wired

The observer’s cron tick (every minute in production, every five minutes in staging) follows a five-step loop per active team:
  1. Enumerate active teams via the internal RPC GET /v1/internal/active-teams-for-sweep (mnemom-api). Filters: not archived, ≥2 non-deleted member agents.
  2. Fetch the team’s effective Trust Posture via GET /v1/teams/:id/effective-posture. The composer folds Platform → Org → Team with strictest-wins semantics per axis.
  3. Fetch member agents and their alignment cards via the canonical card store.
  4. Run the three pure-synchronous detectors (computeTeamCoherence, analyzeFaultLines, checkFleetCoherence) against the posture body’s per-axis thresholds. Each axis runs only if it’s enabled and the team’s per-axis cadence has elapsed.
  5. Fan out advisories per the posture’s fan_out.rule. The default — and only v1 value — is per_named_affected_agent: one row per agent named in the finding.
Each sweep also writes a row to sideband_sweep_log (UPSERT keyed by team_id × axis × day) — proof-of-coverage evidence for SOC 2 / EU AI Act control mappings, even when no findings are produced. Read it via GET /v1/teams/:id/sideband-coverage.

The Posture is the policy surface

Detectors don’t carry their own thresholds. Every per-source firing rule lives in the team’s effective Trust Posture and composes with strictest-wins per layer:
Posture fieldDrivesComposition
sideband.<axis>.enabledWhether the detector runs at all for this teamOR-true wins (any layer enabling fires)
sideband.<axis>.cadence_secondsSweep intervalmin wins (shorter = stricter)
sideband.coherence.fire_on.*Threshold per fire condition (pairwise governance floor, conflict edges, outlier count)min-among-defined wins (lower = stricter)
sideband.fault_line.severity_floorMinimum AAP severity that produces an advisorymin wins (lower floor = more advisories)
sideband.fleet.patterns.*Which fleet patterns fire (outliers / min pair / partition)OR-true wins per pattern
sideband.<axis>.severity_on_fireSeverity stamped on the advisory when the detector firesmax wins (louder advisory)
fan_out.ruleHow many rows to produce when N agents are affectedfixed precedence list
If you want a detector tuned tighter for a banking team, you tighten the posture — never the detector code. See the how-to: Tuning sideband detection via Trust Posture.

Per-pattern emission for the fleet axis

The fleet axis can fire on three independent patterns: outliers, min_pair_score, and cluster_partition. When more than one fires on the same sweep, the observer emits one row per pattern with a distinct source_ref.pattern_type. This mirrors the convention used by leading detection platforms (CrowdStrike Detections, Datadog Security Monitoring signals): one detection event per (rule, target, time-window) — not aggregated.
// outliers fire on team tm-acme-banking
{
  "source": "sideband.fleet",
  "source_ref": {
    "team_id": "tm-acme-banking",
    "pattern_type": "outliers",
    "outlier_agent_ids": ["agt-monitor-3"]
  }
}
// cluster partition fires on the same team in the same sweep
{
  "source": "sideband.fleet",
  "source_ref": {
    "team_id": "tm-acme-banking",
    "pattern_type": "cluster_partition",
    "cluster_count": 2,
    "cluster_ids": ["c-0", "c-1"]
  }
}
Downstream consumers (dashboard, runtime injection, webhook subscribers) treat each row independently. Dedupe at presentation time if needed; the storage layer keeps detection events distinct.

Multi-team agents

An agent that is a member of N teams may receive up to N advisories on a single turn — each team’s effective posture sweeps independently, and strictest-wins does not fold across teams (each team’s posture is its own composition). The gateway’s injectPendingNudges caps each turn at five advisories; if a multi-team agent has more than five queued, the older ones land on subsequent turns until the queue drains.

Webhook events

Each sideband firing emits a <source>.fired webhook event so external subscribers (SIEM, ticketing, alerting) can react. Per ADR-047:
  • sideband.coherence.fired
  • sideband.fault_line.fired
  • sideband.fleet.fired
Drift’s webhook keeps its legacy name (drift.detected) for backwards compatibility — the single documented carve-out from the <source>.fired convention. Subscribe via Webhooks.

Compliance evidence — proof-of-coverage

Operations security buyers comparing Mnemom against CrowdStrike Falcon Audit, Splunk audit.log, or Datadog Security Monitoring expect two artifacts:
  1. Findings — what fired, when, on which agent. Mnemom: pending_advisories rows with sources sideband.*.
  2. Coverage proof — even when nothing fired, evidence that the detector ran during the reporting window. Mnemom: sideband_sweep_log rows.
The sideband_sweep_log table UPSERTs (team_id, axis, day) keys per sweep, incrementing swept_count and fired_count and refreshing last_swept_at. SOC 2 / EU AI Act / HIPAA control mappings can answer “show evidence that team X had its coherence detector swept N times during the audit window” in a single SQL query — or via the public GET /v1/teams/:id/sideband-coverage endpoint, which returns a per-axis 30-day summary.

See also