Skip to Content
Concepts

Concepts

This page defines the terms used throughout NavFlow: sources ingest events; events carry labels, one of which is the key; a label value is an entity; the catalog is the registry of configured objects; a view correlates sources for a key; a trigger watches a view.

Sources

A source is a configured connector instance. It has a name, a connector type, and a config object. Each source produces a single stream of events.

Sources have one of two modes:

  • Pollnavflowd fetches from the upstream on an interval (poll, e.g. 5s, 1m). Used by GitHub, Prometheus, Postgres, Docker logs.
  • Push — producers send events to navflowd over HTTP. Used by Vercel, OTLP, and webhooks. A push source has a generated ingest_key; producers POST to /ingest/<ingest_key> (OTLP uses /v1/{logs,traces,metrics}).

Sources are added, edited, paused, and removed at runtime; no restart is required.

Events

Every event is stored with the same fields:

fieldtypedescription
sourcestringthe source that produced the event
event_timetimestampwhen the event occurred (source time if available, else ingest time)
event_typestringa coarse type, e.g. commit, 5xx_rate, error
textstringthe rendered line an agent reads
fieldsobjecttyped values extracted for filtering and triggers, e.g. { "status": 500 }
labelsobjectnamed correlation axes, e.g. { "service": "checkout" }
payloadobjectthe original event, unmodified (lossless)
key_valuestringthe value of the primary label (the key)

Labels, keys, and entities

A label is a named axis carried by an event. It is declared on the source as one of:

  • const — a fixed value applied to every event from the source, or
  • field — read per-event from a field in the connector’s normalized event.

Example label declarations on a source:

labels: - { name: service, field: service, primary: true } - { name: env, const: prod }

The label marked primary: true is the keykey_value is set from it. There is no separate key field to configure; the key is just the label you marked primary. If no label is marked primary, the connector’s default key is used.

An entity is a (label, value) pair, e.g. (service, checkout) or (repo, acme/api). The console’s Explore page lets you pick any entity and read its correlated timeline; it lists each label’s distinct values with event counts. Because labels are indexed, selecting events by { service: "checkout" } is a lookup, not a text scan.

A source’s Fields view (console, or GET /api/sources/<name>/fields) reports each label/field’s coverage — how many sampled events actually carry it — and its top values. Use it to choose a key that is reliably present.

Reading

The core read is read(selector, window): a correlated, time-ordered timeline of every event matching a { label: value } selector across all sources, in one response — no view required. The selector is a strict-AND conjunction, so { service: "checkout" } returns that service’s logs, metrics, and deploys merged on one clock, and adding a label narrows it. Each row carries the labels it matched on, so a read is self-describing.

A view (below) is an optional, saved refinement — a named, narrowed set of sources you reuse and attach triggers to. Reading through a view is query(view, key | where, window).

The catalog

The catalog is the set of configured sources, views, and triggers. It is stored in the embedded database and is also expressible as YAML: GET /api/catalog/export returns it, and importing YAML (or seeding from a file on first boot) recreates it. The MCP catalog_describe tool (and, in the console, a source’s detail page) reports any object’s schema (event types and inferred typed fields), the entities it carries, freshness, lineage, and sample events.

Views

A view is a saved, narrowed read: a named set of sources (with optional filters) you reuse and attach triggers to. Where read spans every source, a view fixes the source set. A view is defined by:

  • sources — the sources to merge,
  • key_field — the label used to identify the entity across those sources,
  • filters — optional [{ field, op, value }] (ops: eq, neq, contains, gt, lt, gte, lte).

A view is virtual: it is evaluated at query time and stores no data. Reading a view for a key (or a { label: value } selector) over a time window returns the merged events in order. Views can be created over MCP with the derive tool; agent-created views are recorded with created_by set to the agent.

Triggers and subscriptions

A trigger evaluates a condition over a view as events arrive. A condition is an aggregate of a field, grouped by key, compared to a threshold over a window — for example max(rate_5xx) > 1.0 per key over 1m. When the condition holds, the trigger emits a dispatch.

A subscription is a webhook URL registered by an agent (over MCP, with subscribe). On a dispatch, NavFlow POSTs to each subscriber, optionally attaching the entity’s timeline. Firings and delivery status are listed on the console’s Agents → Trigger dispatches page.

Object graph

connector → source → event → labels → entity ├→ read · view → query (read; agents + console) └→ trigger → dispatch → subscription (push; agents woken)

See Connectors for what can be ingested, and Connecting agents for the read/watch surface.

Last updated on