# What isn't covered, and why

The catalog prefixes no descriptor binds, each with the blocker behind it, so you can tell an absence from a misconfiguration.

Source: https://tokentriage.com/docs/build/providers-coverage

---
import Callout from '../../../components/Callout.astro';
import Details from '../../../components/Details.astro';
import NextSteps from '../../../components/NextSteps.astro';

The list you want when you are evaluating a gateway is not the one it publishes. Vendors publish
the providers they support; you need to know about the one you use, and a positive list makes that
a search rather than an answer.

So here is the negative list. Every provider prefix in the vendored price catalog that no
descriptor binds, with the reason it is absent, so you can tell in about a minute whether your
provider is unsupported, differently named, or already reachable under another descriptor.

## The arithmetic, and what each number counts

Two of the numbers on this page are different kinds of claim, and telling them apart matters more
than either figure does on its own.

TokenTriage vendors a price table, `litellm@2026-07-14#179affb`. Its model keys are written
`<prefix>/<model>`, and the distinct prefixes number 107. That is a statistic about a vendored
price table, not a claim about what TokenTriage can reach. The count of covered prefixes is the
claim: descriptors cover 85 of those 107, and 22 are uncovered. A prefix counts as covered when a
descriptor binds it, 83 by an explicit catalog prefix and 2 by a declared-free descriptor whose
name matches one. That is arithmetic the generator derives, not a test result.

Whether a test gates any given descriptor is a separate axis, and it is published separately: the
matrix names the test behind each gated provider-by-endpoint cell and prints the ones carrying
none as `declared (no e2e gate)`, ten descriptors carrying no gated cell at all. Those tests run
against mocks, not against the providers' live endpoints.

Covered is not served. `oci` sits inside the 85 and reaches 19 of its 44 priced keys, and the
generator prints the 25 it cannot reach rather than letting a coverage count imply the rest:

```text
partial reach: "oci" serves 19 of its 44 priced keys; 25 carved out — 19 vendor-excluded 3 surface-not-bound 3 vendor-undocumented
```

Of those 25, 19 are Cohere models that Oracle's own package documentation says do not support the
OpenAI-compatible surface this descriptor binds. 3 sit on a sibling Oracle surface the descriptor
does not bind. The last 3 are a defect in the price catalog itself: it prices
`oci/openai.gpt-5`, `-mini` and `-nano`, which Oracle does not document on OCI, while the two
OpenAI models Oracle does document there carry no price at all. The vendored artifact is not
edited to hide that, because a silently corrected copy would disagree with its source.

The 22 uncovered prefixes account for 121 of the catalog's 2,889 priced model keys, and they
partition into five classes:

```text
gap partition: 22 uncovered catalog prefixes, classified in PROVIDER_GAP.md
  auth-blocked             1 prefixes,    6 models  — blocked on a new credential scheme (Track B)
      gigachat                            6 models
  refused-unverifiable     4 prefixes,   34 models  — REFUSED — no primary documentation exists (H24)
      darkbloom                           2 models
      llamagate                          16 models
      pinstripes                          6 models
      tensormesh                         10 models
  refused-bespoke          5 prefixes,   19 models  — REFUSED — bespoke/uncertain wire, no verifiable contract
      aws_polly                           4 models
      nlp_cloud                           2 models
      palm                                6 models
      sagemaker                           6 models
      sarvam                              1 models
  different-wire-deferral  2 prefixes,    3 models  — deferred — a different wire on a covered provider family
      text-completion-codestral           2 models
      text-completion-inception           1 models
  alias-or-sub-namespace  10 prefixes,   59 models  — not a driver gap — alias / sub-namespace / unwired endpoint
      amazon_nova                         4 models
      bedrock_mantle                     10 models
      chatgpt                            10 models
      codestral                           2 models
      cohere_chat                         7 models
      fireworks_ai-embedding-models       5 models
      meta                                1 models
      vertex_ai-embedding-models         10 models
      vertex_ai-image-models              8 models
      vertex_ai-text-models               2 models
  total: 22 uncovered prefixes / 121 models (of 107 prefixes / 2889 models in litellm@2026-07-14#179affb)
```

Both blocks above are output from `go run ./tools/matrixgen -dump` in the product repo, captured on
2026-08-24 against that pricing artifact. Nothing in them is typed by hand: the counts come from
the descriptor registry, the price file, and the classification markers the gap document carries,
so a clone of the same commit prints the same bytes. `TestGapPartitionExact` fails when an
uncovered prefix escapes its class, and it is a test you can run.

<Details summary="How the partition is checked, and what the check does not cover">

The classification lives in the product's `PROVIDER_GAP.md` as one HTML comment marker per
section, `<!-- gapclass: auth-blocked -->` and so on, over a closed vocabulary of class ids. The
generator reads those markers rather than the headings, so rewording a section's prose cannot move
a prefix between classes.

`TestGapPartitionExact` asserts four things: every uncovered prefix appears in some class, none
appears in two, the class sizes sum to the uncovered count, and at least one marker exists. An
unknown class id is a partition problem, and the generator declines to write the file at all
rather than publish a hole. A heading whose advertised count disagrees with the rows beneath it is
a partition problem too.

What the check does **not** cover: the per-prefix model counts in the gap document's own tables are
hand-typed, and nothing gates them. They agree with the derived figures today. The counts on this
page come from the generator output above rather than from those tables.

</Details>

## The five classes, and what separates them

They are not five flavours of not-yet. One is an engineering lever, two are positions we intend to
keep, one is a deferral with a published condition, and the largest is not a driver gap at all.

### Blocked on a credential the authenticator cannot carry

1 prefix, 6 model rows: `gigachat`.

Its OAuth2 flow is the straightforward half of the problem. The blocker is a TLS **client
certificate**, which belongs to the shared HTTP transport rather than to the per-provider
authenticator, so supporting it means per-upstream transports, which is a subsystem rather than a
descriptor.

**The lever** is per-upstream HTTP transports. **The published condition** is a second provider
needing mutual TLS, at which point those transports become worth building rather than a carve-out
for one vendor.

**What you can do today.** Put GigaChat behind your own certificate-terminating proxy and point a
generic `openai_compatible` upstream at that proxy. You get routing, governance and a ledger row,
and you hold the certificate. What you do not get is a price binding, because the price binds to
the provider prefix and not to the wire.

### Declined because the wire cannot be verified

4 prefixes, 34 model rows.

| Prefix | Model rows | Why it is absent |
|---|---:|---|
| `llamagate` | 16 | no primary API documentation found |
| `tensormesh` | 10 | no primary API documentation found |
| `pinstripes` | 6 | no primary API documentation found |
| `darkbloom` | 2 | no primary API documentation found |

The problem is not effort. Without a first-party description of the wire, any mock built to test
against is a mock of our own guess, and passing our own guess is not verification. These four stay
out, and publishing them with the reason is worth more than quietly omitting them.

**The lever** is a first-party document. No re-entry condition is published for this class, and
that is a position rather than an oversight: closing every other blocker while these four stay out,
in public, with the reason, is a statement about the standard rather than about four vendors.

**What you can do today.** If one of these is your provider and it does publish a wire
description, that document is the thing to send us. Until then `openai_compatible` will relay to
any OpenAI-shaped endpoint.

### Declined because the wire is bespoke, uncertain or gone

5 prefixes, 19 model rows, and 5 different reasons.

| Prefix | Model rows | Why it is absent |
|---|---:|---|
| `sagemaker` | 6 | per-endpoint container contract; there is no fixed wire |
| `palm` | 6 | deprecated upstream, Google PaLM retired |
| `aws_polly` | 4 | the AWS-JSON `SynthesizeSpeech` envelope is not confidently known |
| `nlp_cloud` | 2 | its own non-OpenAI REST API |
| `sarvam` | 1 | one model, OpenAI compatibility unverified |

<Callout type="warning">
**No re-entry condition is published for any of these five.** The other four classes each carry
one. Two conditions were written down while this work was scoped, but they live in a working
document outside the published tree, so there is nothing here to quote, and the other three
prefixes have none anywhere. Saying so is more useful than implying a queue that does not exist.
</Callout>

**What you can do today.** `sarvam` and `nlp_cloud` are the two most likely to work through the
generic escape hatch if their endpoint is OpenAI-shaped: try it, and read the ledger row to see
what arrived. For `palm`, migrate; Google's own replacement is covered under `vertex_ai` and
`gemini`. For `sagemaker` there is nothing generic to offer, because there is nothing general to
bind to.

### Deferred to a different wire on a family already covered

2 prefixes, 3 model rows: `text-completion-codestral` (2) and `text-completion-inception` (1).

The names read like legacy `/v1/completions` providers. They are not. Both are fill-in-the-middle
endpoints served at `POST /v1/fim/completions`. For the Mistral one, Mistral's own reference
documents that path and no `POST /v1/completions` at all. Binding either would forward to a path
the vendor does not serve.

**The lever** is either a `FimCompletions` endpoint kind with its own dated wire notes per vendor,
or a response adapter that translates fill-in-the-middle into a text completion and discloses the
translation on the row. **The published condition** is that either becomes a card, since neither is
a data change.

**What the deferral costs** is small, and the gap document says so: the two
`text-completion-codestral` rows carry no per-token rate in the vendored catalog, so a single
priced row is the whole of what is foregone.

### Not a driver gap

10 prefixes, 59 model rows, and the largest slice of the uncovered set is the least interesting
one. These are not separate providers. A request for them already routes through an existing
driver, or the prefix is an alias or a legacy surface.

| Prefix | Model rows | What it is |
|---|---:|---|
| `bedrock_mantle` | 10 | synthetic or forthcoming model ids on Bedrock |
| `chatgpt` | 10 | OpenAI model aliases; use `openai/` |
| `vertex_ai-embedding-models` | 10 | Vertex `:predict` embeddings, a different wire from `generateContent` |
| `vertex_ai-image-models` | 8 | Vertex Imagen on `:predict`, likewise a different wire |
| `cohere_chat` | 7 | redundant with `cohere/` |
| `fireworks_ai-embedding-models` | 5 | the Fireworks embedding price bucket; the parent is covered |
| `amazon_nova` | 4 | shorthand ids; the Bedrock ids they stand for resolve under `bedrock/` |
| `codestral` | 2 | Mistral models; use `mistral/` |
| `vertex_ai-text-models` | 2 | Vertex text models; the parent prefix is covered |
| `meta` | 1 | a synthetic model id |

Read that table before concluding your provider is missing, because most of these are reachable
today under a name you already have.

**The lever** for 8 of the 10 is a pricing-bucket descriptor: pure data on an existing
pattern, reusing a driver that already ships, the way `bedrock_converse` binds its own price bucket
over the Bedrock wire. **The published condition** is operator demand for a specific bucket's
prices.

2 of the 10 are not that, and the gap document flags them in its own table: the Vertex embedding
and image prefixes sit on a different wire verb, so for those the pure-data description understates
the work.

## The class that emptied

There used to be a sixth class here, and by model rows it was larger than any of the five above:
7 prefixes carrying 92 priced keys, blocked on submit-and-poll execution, where a provider takes a
job and hands back something to poll instead of answering in the response. `replicate`, `fal_ai`, `black_forest_labs`, `runwayml`, `stability`,
`assemblyai` and `soniox` were all waiting on one piece of infrastructure.

All 7 now ship. The class stays in the published list with a count of zero rather than being
removed, because an empty class says *nothing is blocked on this any more*, where a deleted one
says nothing at all.

<Callout type="key">
That is a convention the gap document keeps and explains, not a structure the build enforces.
`TestGapPartitionExact` ranges over the uncovered prefixes, so it would still pass if the empty
section were deleted tomorrow. Read the zero as an editorial choice with a stated reason, which is
what it is.
</Callout>

## Covered is not the same as priced

Closing that class did not turn its 92 priced model keys into dollars, and the two kinds of unpriced
row it left behind are the clearest illustration of what this page is for. That 92 counts catalog
keys under those seven prefixes, not descriptors: `replicate` 40, `stability` 23, `fal_ai` 14,
`black_forest_labs` 8, `runwayml` 3, `assemblyai` 2, `soniox` 2.

**Replicate is a coverage win with no priced dollars.** Its prediction wire reports elapsed seconds
and no token count anywhere, while every `replicate/` row in the vendored catalog is priced per
token. The unit the price needs is absent from the wire, so all 40 rows settle
`UNPRICED(unit_missing)` instead of guessing. No catalog edit fixes that, and anyone quoting the 40
in a spend or savings sentence is quoting the wrong number.

**Soniox is the mirror image, and it is a data gap.** Soniox reports a measured audio duration in
milliseconds, which is what a per-second rate consumes, and the driver settles with that figure as
the provider reported it. Both of its catalog rows carry no rate at all, so the pricing key
resolves and then has no rate units to apply, which is what `unit_missing` means. One `per_second`
rate on those two rows would make Soniox priceable with no driver change.

A driver gap and a data gap look identical from a dashboard and cost completely different things to
close. Classifying by blocker rather than by vendor is what keeps them apart.

## What this list is not saying

**It is not a claim about breadth.** The price table these counts are measured against belongs to
somebody else, and it lists more than this build binds. The claim here is about verification, not
size.

**It is not a roadmap.** Each group above carries a count, a blocker, and where one exists, the
condition under which we would look again. A named condition is not a commitment, a date or a place
in a queue. Two of the five groups are positions we intend to keep, and one of those two has no
condition published at all.

**It is not the whole story of an absence.** A provider missing from the price catalog entirely
does not appear here, because these 22 are prefixes the catalog knows about. If your provider is
OpenAI-shaped and absent from the catalog, you can reach it today, and
[adding a provider](/docs/build/providers-custom) covers both routes.

<NextSteps items={[
  {title: "Add a provider TokenTriage doesn't ship", href: "/docs/build/providers-custom", description: "The two routes that reach a provider this page says is absent, and what each one costs you."},
  {title: "Provider reference", href: "/docs/build/providers-reference", description: "The covered set instead of this one, with the wire, scheme, prefix and endpoints behind each row."},
  {title: "Endpoints and cost shapes", href: "/docs/build/providers-endpoints", description: "Coverage counts prefixes; this counts surfaces, which answers a different question about the same descriptor."},
  {title: "Providers that take a job and answer later", href: "/docs/build/providers-async-jobs", description: "Where those providers went when this page's largest class by model rows emptied."}
]} />
