Concepts
Everything in Tares hangs off one pipeline. Sources ingest events from your systems; the labels on each event say which entity it belongs to. A read returns one entity’s events across all sources, merged in time order. A view saves a narrowed read; a trigger watches a view and, when its condition trips, emits a dispatch to subscribed agents; an agent can write a finding back onto the entity’s timeline.
connector → source → event → labels → entity
├→ read · view → query (read; agents + console)
└→ trigger → dispatch → subscription (push; agents woken)
└→ finding (written back)The rest of this page defines each term in the order the data flows.
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 three modes:
- Poll:
taresdfetches from the upstream on an interval (poll, e.g.5s,1m). Used by GitHub, Prometheus, Postgres, Docker logs. - Push: producers send events to
taresdover HTTP. Used by Vercel, OTLP, Alertmanager, and webhooks. A push source has a generatedingest_key; producers POST to/ingest/<ingest_key>(OTLP uses/v1/{logs,traces,metrics}). - Reference: declarative context, not a stream. The config is the data; it’s re-materialized
on edit and always surfaced regardless of the read window. Used by
reference.
Sources are added, edited, paused, and removed at runtime; no restart is required.
Events
Every event is stored with the same fields:
| field | type | description |
|---|---|---|
source | string | the source that produced the event |
event_time | timestamp | when the event occurred (source time if available, else ingest time) |
event_type | string | a coarse type, e.g. commit, 5xx_rate, error |
text | string | the rendered line an agent reads |
fields | object | typed values extracted for filtering and triggers, e.g. { "status": 500 } |
labels | object | named correlation axes, e.g. { "service": "checkout" } |
payload | object | the original event, unmodified (lossless) |
key_value | string | the 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, orfield: 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 key: key_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, with 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 reference source type
Most sources are time-series: a read applies the window, so old events age out. A
reference source is different: it holds declarative context
(documents attached to an entity by their labels), and its events are always included in an
entity read, regardless of the window. A runbook or schema attached to service=checkout
surfaces on every read of that entity, not just recent ones, so an agent correlating on an entity
always has its reference material to hand.
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: one firing for one entity, carrying the entity’s timeline. Every dispatch is logged, even with no subscribers; firings and delivery status are on the console’s Deliveries page.
A subscription wires an agent to a trigger; on a dispatch, Tares delivers to each subscriber. Two kinds subscribe the same way: an external agent (a webhook URL that gets POSTed the timeline; see the delivery contract) and a Tares agent (a prompt configured in Tares that runs in-process).
Findings
A finding is a conclusion written back onto an entity’s timeline. When a Tares agent runs on a dispatch, it reads the correlated timeline and writes its diagnosis as an event in a findings source (auto-provisioned on first use), labeled with the same axis as the evidence. Because it is a labeled event like any other, every later read of that entity includes it: the next agent (or human) to look starts from the previous conclusion instead of from scratch.
External agents write back the same way with the remember tool, which
stores observations in the agent-memory source.
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.
See Connectors for what can be ingested, and Connecting agents for the read/watch surface.
Deleting
Objects depend on each other downward: a view on its sources, a trigger on its view, a Tares
agent on its trigger. Deleting a source or a view shows what depends on it and offers to delete
those too, in order (agents, then triggers, then views); say no and the delete is refused,
naming what would break. Deleting a project lets you pick which of its objects go with it. On the
API: GET /api/catalog/dependents?kind=&name= lists the dependents, and cascade=true on
DELETE /api/sources/{name} or /api/views/{name} takes them along.