Skip to main content

Keep the model catalog current

Enterprise Tier

Providers release, reprice, and retire models faster than any deployment upgrades. Tetrate publishes the provider and model data in a public repository, and tare api catalog sync reconciles a deployment against it, reporting by default and writing only under an explicit opt-in.


Persona: Platform operator. The one-shot sync runs anywhere the tare CLI reaches the management plane; the scheduled CronJob applies where the management plane is customer-managed.

Estimated time: 10 minutes for a first dry run; one review cycle before allowing writes.

Where the catalog data comes from

The published catalog lives at github.com/tetrateio/agent-router-models: providers.json lists the providers, and each provider has one JSON file carrying its models with their prices, limits, capabilities, and lifecycle (deprecation and retirement markers; since 0.4.0 the states new, preview, deprecated, and retired are derived from this metadata by one shared policy, so the Console, the sync report, and the gateway read the same verdict). The record formats are defined in the repository's schemas/, and CHANGELOG.md records every update as a dated block, so when a price or a limit changed is answerable from the history. The repository is public: reading it needs no credential.

What a sync does, and deliberately does not do

A sync fetches the published catalog, compares every entry with the management plane, and classifies each difference:

ActionMeaning
createThe published entry does not exist in the deployment yet
updateThe entry exists and a field differs (price, limits, capabilities)
disableThe published catalog marks the model deprecated or past its retirement date, so it is turned off, with the reason in the report
unchangedAlready matching; counted in the report, never listed

The disable action is the one that prevents the worst surprise: a model the provider has retired does not stay selectable until it fails at request time. Since 0.4.0 the sync also warns when a model past its retirement date is still enabled on the management plane, and names the remedy in the report: --apply disables the ones the published catalog still lists, --disable-absent the ones it no longer lists at all.

Three safety properties are deliberate:

  • A sync never deletes anything, and it reports without writing unless --apply is passed.
  • Models the published catalog does not mention are left alone. A deployment's catalog is not required to be a subset of Tetrate's: self-hosted models and operator-added entries never appear in the published catalog, and disabling them automatically would break the deployment's own routing. They are listed in the report, and turned off only under the explicit --disable-absent opt-in.
  • A sync never enables a model an operator disabled. An entry the published catalog would enable is surfaced in the report as staged, and stays off until an operator acts.

Whether a synced model is callable is still governed by enablement and project grants, exactly as for a hand-provisioned one; see Add providers and models to projects.

Run a one-shot sync

Sources are passed explicitly, one --models per provider file, and the run is a dry run unless --apply is added:

tare api catalog sync \
--providers https://raw.githubusercontent.com/tetrateio/agent-router-models/main/providers.json \
--models https://raw.githubusercontent.com/tetrateio/agent-router-models/main/anthropic.json \
--models https://raw.githubusercontent.com/tetrateio/agent-router-models/main/openai.json

The report leads with the shape of the run, then lists only what would change:

providers: 0 create, 1 update, 11 unchanged
models: 4 create, 7 update, 2 disable, 668 unchanged
update provider deepinfra (endpoint)
create model openai/gpt-6-astra
disable model gemini/gemini-1.5-pro -- retired 2026-06-30

dry run: nothing written. 14 entr(ies) would change; pass --apply to write.

Re-run with --apply to write. A by-hand run authenticates as the signed-in session or a user-issued API key against the public catalog API; failures on individual entries are collected and reported rather than aborting the run.

To review updates before they are ever fetchable, pin the URLs to a tag or commit SHA of the published repository instead of main.

Schedule it

Where the management plane is customer-managed, its chart ships a catalog-sync CronJob that runs the same sync nightly. Since 0.4.0 the job authenticates with the plane's own admin key over the admin API surface (the CLI's --admin flag); on earlier releases the scheduled job could not authenticate at all, because the public catalog API accepts only a session token or a user-issued API key, neither of which a scheduled job has. It is off by default, behind two separate opt-ins so it can be watched before it is trusted:

Helm valueWhat it does
catalog-sync.enabledRenders the CronJob. Alone, this buys a nightly dry-run report in the job's logs, and writes nothing
catalog-sync.applyLets the job write
catalog-sync.adminSurfaceOn by default: the job runs tare api catalog sync --admin, driving the admin API surface, which accepts the plane's admin key. Switched off, the job uses the public catalog API, and the secret below must hold a user-issued API key instead. Flip the surface and the secret together, or every run fails before reading anything
catalog-sync.apiKey.secretNameNames the secret holding the credential the job authenticates with: the management plane's admin key with adminSurface on (the default)
catalog-sync.proxyOutbound proxy for a cluster that egresses through one
catalog-sync.sourceWhere to read the catalog: the published repository's main by default, a pinned tag or SHA for review-first change control, or mounted files for a cluster with no egress

The rollout pattern the defaults are built for: enable the job, read a cycle of nightly reports in kubectl logs, and only then allow apply.

Watch catalog freshness

Since 0.5.0 the management plane keeps a record of its catalog syncs: every run updates it, report-only runs included, and tare api catalog status reads it back:

last run 2026-09-17T03:00:04Z (9 hour(s) ago), dry run, by admin-key-7
catalogue 2026-09-16T00:00:00Z
last applied 2026-08-05T03:00:11Z (43 day(s) ago), by admin-key-7
catalogue 2026-08-05T00:00:00Z (43 day(s) old)
wrote 4 provider(s), 700 model(s)

DRIFT: the last run read catalogue 2026-09-16T00:00:00Z, which this plane has not applied.
It is on 2026-08-05T00:00:00Z. Run the sync with --apply to converge.

The two halves answer different questions. Last run says when this deployment last looked at a published catalog, and moves on every run, so a nightly job left in its default report-only mode still reads as checked. Last applied says which catalog the deployment is actually on, and moves only when a run wrote the whole difference: a run that failed part way, lost its publish step, or skipped entries does not claim the new version. The DRIFT block appears when the two disagree, which is the state that needs an operator.

For a monitor, two thresholds turn the same record into exit codes, and they redden on different faults:

FlagFails whenThe fault it points at
--max-since-run 48hNo sync has run inside the window, report-only runs includedThe sync job itself stopped: CronJob suspended, credential expired, cluster egress broken
--max-age 168hThe applied catalog's own publication date is older than the windowThe deployment is on an old catalog: either syncs stopped converging, or the published catalog itself has gone quiet

Set both. A stopped job also makes the applied catalog age, so --max-since-run is checked first and a plane that stopped syncing reports the job rather than the consequence. Like the sync itself, catalog status takes --admin when authenticating with the plane's admin key.

One row in the audit log records each run (RECORD_CATALOG_SYNC, with the catalog version and whether it applied), and since 0.5.0 the sync's individual catalog writes carry batched: true in their audit metadata, so the audit view can be filtered to just the changes a person made.

Air-gapped clusters

Both sources accept a local file path in place of a URL. Download the published catalog out of band, then apply it from files:

tare api catalog sync --providers ./providers.json --models ./anthropic.json --apply

--models-sha256 pins a digest per models document, in the same order as the --models flags, for pipelines that verify what they fetched.