Signals
A Signal is an immutable, timestamped observation — the unit of evidence every Loop works from. This page covers the four Signal kinds, how provenance and trust are recorded, and how untrusted content is quarantined before it can influence anything downstream.
Four kinds
| Kind | What it records | Typical origin |
|---|---|---|
voice |
Something a person said: a review, a support email, a forum thread | Listening connectors, the feedback widget |
behavior |
Something users did, aggregated from accepted events | Derivation rules over collected events |
outcome |
A measured result attached to a Change or Experiment | Experiments and measurement |
metric_delta |
A Metric moving beyond its expected range | Metric watches |
Every Signal carries the same envelope: its source, references to the objects it concerns, the consent scope it was collected under, provenance and trust labels, and lineage back to whatever produced it.
Immutable, corrected by appending
There is no way to edit a Signal. Corrections are new Signals linked to the original, so analysis can prefer the corrected value while the record of what was observed at the time survives. Evidence that can be quietly rewritten is not evidence.
Provenance and trust
Provenance states where a Signal came from and how far that origin can be trusted:
| Provenance | Meaning |
|---|---|
owned |
Your own product or infrastructure: your events, your support inbox after sender checks |
verified_partner |
A partner integration whose identity is verified |
public_api |
An official public API: app reviews, forum threads |
unverified |
The origin could not be established |
Signals are authored by humans, agents, and connectors, and the source class is enforced at write time: an agent cannot mint a Signal that claims to be a connector or a Metric watch. Author identity on voice Signals is minimized — enough to honor an author’s export or deletion request, never enough to build a profile of them.
Quarantine for untrusted content
Text from the public web, and voice content generally, is treated as hostile by default. It is stored in constrained quarantined fields, and payloads carrying instruction-shaped extra keys are rejected outright. The only way that text leaves quarantine is through an escaping, fenced renderer that displays it alongside its provenance.
Anything derived from quarantined content — Insights, Hypotheses, briefs, notifications, resources served to agents — inherits an untrusted-derived label, so every downstream reader knows the chain includes content nobody vouched for.
Routing to Loops
Loops subscribe to the Signals they care about (see Listening for subscriptions). Routes are committed when the Signal is written; changing a subscription later does not silently re-route history — that takes an explicit, audited backfill. Staging Signals never advance production Loops.
Derived Signals
Versioned derivation rules watch accepted event aggregates and emit behavior Signals. Rules validate event names against the event dictionary, track their position with cursors, and pause visibly on errors instead of skipping data. Quarantined events are excluded from derivation. Metric watches emit metric_delta Signals through their own reserved source path.
Triage
The Signal inbox filters by kind, source, trust, and state, and shows provenance and lineage for each entry. Triage state — seen, archived, promoted — is stored separately, so working the inbox never mutates a Signal. A useful Signal can be promoted into a Loop subscription so its successors route automatically.
The same operations are available to agents over API, CLI, and MCP: structured queries, facets, derivation rules, and triage. Agent-facing responses fence and label untrusted content exactly as the web app does.