Prerequisites
- A key with the
plugins:adminaction inQUIVR_OPERATOR_KEY. Organization keys never get it; with the local stack,eval "$(make -s env)"sets one. - The plugin certified by
quivr plugin test, and reachable from the api and the worker processes.
Steps
1
Run the new version
Run it at its own address, next to the version in service. Here, from the folder that holds
my-embedder:2
Register it
Send the exact text of the Quivr refuses at once, with
quivr-plugin.yaml the plugin was built from, its address, and the settings you would give it in a pin: configuration, routes, kinds or spaces.422 invalid_plugin, anything it would refuse at startup, such as a configuration that fails the plugin’s schema. The same idempotency_key returns the same registration.3
Wait for the check
Quivr runs the Contract Runner, the checks of A
quivr plugin test, against the plugin’s address. Read the registration until its state is validated:rejected registration lists every check and its issues in check.checks. The plugin must report the digest of the manifest you sent, so one built from another manifest is rejected. To check a fixed build, register it again with a new idempotency_key.4
Activate it
core.ingest.5
Stop the old version once it is inactive
Work that started before the switch finishes on the old version (see below). Until that work is done, the old registration reads Stop the old version once its
draining and its pinned_work counts what is left:state is inactive. Earlier plans stay readable at GET /v0/admin/plugins/plans/{plan_id}.Check it worked
plugin_plan_poll in the configuration) and swaps in a new one whole. New work and every new search use the new plan.
Roll back
If the new version misbehaves, one call makes the previous plan’s plugins serve again:previous_plan_id names the plan you left. To return to an earlier plan, add its plan_id to the request. The api and the worker follow a rollback as they follow an activation. Nothing already produced is rewritten: articles the version you left processed keep their text and stay searchable.
pinned_work decides what happens to work pinned to the version you left:
Quivr first checks that every plugin the rollback brings back still answers at its address. If one does not, or a different build answers, the call is refused with
409 plugin_unreachable, naming the plugin and the cause, and the plan stays as it was. Start the plugin again, then retry. A rollback that would break one of the rules under Limits is refused like an activation.
GET /v0/admin/plugins/plans lists the latest plans, newest first. Each plan shows what recorded it (source: configuration, activation or rollback) and the plan it replaced.
Work finishes on the version it started with
The processing of a receipt, a connector run and a rebuild each record the plan that was active when they started. Their retries, their later steps and a worker restart keep calling that plan’s plugins, so an article is never processed half by one version and half by the other. Keep the old version running until it isinactive.
If the old version cannot be reached while it drains, its pinned work retries with backoff, up to pinned_plugin_attempts attempts (10 by default). The work then stops with the diagnostic pinned_plugin_unavailable, which names the plan and the plugin: a Version still waiting for its text is quarantined, a searchable Version keeps its text and its enrichment stops, and a rebuild fails. The work is never moved to the new version. A plugin of the active plan, in contrast, may be unreachable for any time: its work keeps retrying. Do not terminate pinned work by hand in Temporal, since its count would never be released.
The configuration and the plan
The plugins pinned inQUIVR_CONFIG are registered at every start. The configuration then applies, role by role, only what changed in it since it last applied. A role whose pinned plugin you changed follows the configuration; a role you did not touch keeps what the plan says, so an activation survives restarts.
Limits
- The check runs the normative fixtures only, since Quivr has just the manifest. A plugin that needs its own fixtures to be certified, such as a connector or a normalizer for a media type other than
text/markdown, is rejected; pin it in the configuration instead. - Alert rules switch through the configuration only: each Subscription names its rule’s version, so its evaluations never change version.
- An activation cannot add or remove the retrieval role; pin or unpin a retrieval plugin in the configuration.
- An activation that would break a startup rule is refused with
409 plugin_conflict: one normalizer per media type, one provider per connector kind, one ingestion and one retrieval plugin, extension namespaces, and vector spaces whose model changes without a new space version.