Every agent I run used to name its own model. llama-3.1-8b-instant here, a Codex id there, a Mistral string in the enricher. It reads fine in a diff and it is a slow-motion outage: the day a provider retires or throttles that id, every agent that named it stops at the same moment, and the fix is a deploy per service.

That is the actual cost of naming a model. Not the price per token, the coupling. You have written a provider's product decisions into your own source.
Ask for the job instead
So SpiderGate takes a different value in the model field. Instead of a vendor's model id, you send the name of the work:
{ "model": "spideriq/coding", "messages": [...] }spideriq/coding, spideriq/extraction, agent/chat. The caller declares what the request is for and the gateway decides what serves it. That is the whole primitive, and everything else here is a consequence of it.

It is an ordinary indirection, the same trick as a DNS name in front of an IP, and it buys the same thing: the right to change what is behind the name without telling everyone who uses it.
An alias is a chain, not a model
The part that makes it hold up under load is that an alias does not resolve to one model. It resolves to a ranked list.
There are 32 aliases today, in three families, and between them they carry 91 ordered slots. That averages 2.8 models deep per alias. When the first choice rate limits, errors or times out, the second slot takes the call.

The three families exist because the traffic is genuinely different. spideriq/* is 18 aliases for workers, the scrapers and batch enrichers where cost dominates. agent/* is 9 aliases for live conversation, where a coherent multi-turn session beats a cheap token. opvs/* is 5 aliases for the OPVS agent platform, which splits by job size rather than by task.
Health decides the order, not a static list
Before the chain is tried it gets reordered. Models on healthy providers move to the front, models on struggling ones move to the back, and nothing is dropped. That last part matters more than it sounds: a provider having a bad ten minutes is deprioritised, not removed, so it comes back on its own without anyone editing a config.

If the whole chain is exhausted the request falls through to its family's general alias rather than failing outright. And when the model that answered is not the one the alias led with, the non-streaming response carries an X-SpiderGate-Fallback-From header naming the first choice, so a fallback is something you can see in your own logs rather than something you infer from a latency graph.
The routing engine underneath is BerriAI's litellm.Router, which does the least-busy selection, the retries and the cooldown. What SpiderGate puts on top is the task alias, the per-tenant auth and a usage record for every call.
The reason I trust this more than my own documentation
Here is the honest part. While writing this I checked the alias list against the database instead of against the docs, and the docs were wrong. The page said 26 aliases. There were 32. An entire family, opvs/*, was undocumented. Sixteen of the 26 rows named a model that no longer led that chain, because the models had moved underneath: spideriq/extraction had gone from Groq to Cerebras, spideriq/fast and spideriq/free to NVIDIA NIM, four agent/* aliases from one Codex id to another.
That drift is not an argument against writing docs. It is the argument for the alias. Sixteen routing changes happened and not one caller had to change a line, because no caller had named a model. The documentation rotted; the callers did not.
It is also why the live list is an endpoint rather than a page. It needs no auth:
curl "https://spideriq.ai/api/gate/v1/aliases"You get every alias, its full chain in priority order, and its 30-day usage. Read models[0] for what an alias currently leads with and the array length for how deep it runs. If you are hardcoding anything, hardcode against that.
Using it
The endpoint is OpenAI-compatible, so an OpenAI client pointed at the base URL works unchanged:
from openai import OpenAI
client = OpenAI(
base_url="https://spideriq.ai/api/gate/v1",
api_key="<client_id>:<api_key>:<api_secret>",
)
resp = client.chat.completions.create(
model="spideriq/coding",
messages=[{"role": "user", "content": "Refactor this function."}],
)One credential, one URL, 1,216 catalogued models with 61 of them key-backed behind it. You can still pass a concrete model id when you genuinely need exactly one model, and you lose the failover in exchange. That trade is worth making occasionally and it should be a decision, not a default.
The full list with each chain is in the task alias reference.
