- A saved search says what to look for and in which collections. An alert switches it on and names the rule that judges, where to send notices and, optionally, which of your users it belongs to.
- Each document that becomes searchable in a watched collection goes to the alert rule, a plugin. It answers match, no match or not ready.
- Not ready means the rule needs the document’s meaning vectors. Quivr waits and asks it again once they arrive.
- A match is stored with its reason. Quivr then sends a notice: a webhook to your receiver, which can arrive more than once, and an event in the change feed.
- A first no-match decision sends nothing. What happens when a matched document later changes is below.
The parts of an alert
The API keeps the parts of an alert as separate objects, so you can change one without the others. Each name below is the one the API reference uses; the Subscription names its alert rule in itsevaluator field:
Changing a Saved Query’s expression or a Subscription’s settings creates a new Version instead of editing the old one. A Subscription keeps the Saved Query Version it names until you point it at a new one, and documents that arrive afterwards are judged by its new Version. Earlier Matches keep the Version that decided them. Several Subscriptions can share one Saved Query, for example one per user, each with its own
owner.
An alert judges only documents that become searchable after it is switched on. To see what a query would have caught in the past, preview it with POST /v0/subscription-previews before saving it.
Choose a check
The first-partyalerts plugin offers three checks. Pick the one that fits how your users describe a topic:
keywords_or_meaning and keywords_and_meaning combine a keyword tree with one meaning check.
The local check’s default threshold, 0.80, was measured on 156 pairs of articles and descriptions in French and English. It matched all 16 related pairs, and also 11 of the 140 pairs labelled unrelated. Results depend on the model and the threshold: treat the score as closeness, not a probability, and tune the threshold on your own examples.
The local check never calls Jev, but it is not private by itself: document and description text go to whatever embedding provider the operator configured. To keep that text inside your installation, the operator must use a local embedding provider, such as the default core-ingest plugin, which calls an embedding server the operator runs (the local stack starts one). Meaning alerts has the details.
Not ready
A rule answers not ready when it needs information Quivr is still computing, usually the document’s meaning vectors (enrichment). Meaning checks wait for them by default; keyword checks do not. A Subscription can change this withwait_for_enrichment in its evaluator.configuration.
When the vectors arrive, Quivr asks again only the alerts that have not decided yet. An alert that already matched or did not match that version keeps its decision, so the second question never creates a duplicate Match. If the vectors never arrive, or the rule still answers not ready, the alert does not judge that version.
Corrections and withdrawals
A correction is a new version of a document. When the earlier version matched an alert, the correction goes back to the alert rule, and the alert sends a follow-up notice once the rule decides. A withdrawal sends one without asking the rule: In words: a correction that still matches stores a new Match and sendsmatch.corrected. A correction that no longer matches sends match.no_longer_matches, and a withdrawal sends match.withdrawn; neither stores a Match. Each notice is a webhook and a change feed event:
match.created: a new document fits. Quivr stores a Match.match.corrected: a correction still fits. Quivr stores a new Match, linked to the earlier one byprevious_match_id.match.no_longer_matches: a correction no longer fits. The notice points to the earlier Match; no Match is stored.match.withdrawn: the matched document is withdrawn. The notice points to the earlier Match; no Match is stored.
Delivery
Each event creates a delivery to the Subscription’s destination and an entry in the change feed. Quivr holds a delivery while its Subscription is paused, but its retry window keeps running: a delivery whose window ends during the pause is never sent. It never sends the webhook of a notice that became obsolete: the Subscription was deleted, the document was withdrawn, or a later correction replaced it. The change feed still has the event. Delivery is at least once:- Quivr retries a timeout, a connection failure or a
408,429or5xxanswer, with growing delays, for up to 24 hours by default. The window normally starts when Quivr creates the delivery; a withdrawal recorded while the Subscription was paused starts its window when you resume it. The operator can change the window’s length. - Every retry sends the same event id (
webhook-id) and the same body, so your receiver deduplicates on it. - Retries stop at the end of the window or on any other answer. A receiver that stays down misses those webhooks. Your application can still list Matches with
GET /v0/matches, which covers first matches and corrections that still match. The other follow-ups store no Match: an application that already follows the change feed from a saved position finds them there, for as long as the operator keeps events, 7 days by default.
Who does what
Your application, through the API:- Creates a Saved Query and a Subscription.
- Receives each webhook and verifies its signature.
- Deduplicates on
webhook-idand reads the Match’s evidence. - Changes, pauses or deletes alerts.
- Installs the
alertsplugin and chooses the checks it offers (First-party plugins). - Configures the webhook destinations (Configuration).
- Maps your metadata fields for keyword filters (Configure alert fields).
- Moves existing alerts to a new rule version (Upgrade an alert rule), or abandons evaluations whose old rule is gone (Retire alert evaluations).
Next
Keyword alerts
Save a keyword alert, receive its webhook and verify it.
Meaning alerts
Alert on a subject described in plain words, with stored vectors or with Jev.