← All posts
5 min

How Vexi detects 13 AI providers from your key alone

No provider dropdown, no config file. The format of an API key is enough to identify who issued it. Here is how that works.

Most tools start setup with a question you shouldn't have to answer: which provider are you using? You already know. More importantly, your key already knows. API keys aren't random strings: nearly every provider prefixes them with an identifiable marker.

So Vexi's onboarding is one step. Paste the key. It figures out the rest.

Prefixes are a de facto standard

Providers adopted key prefixes for their own reasons, mostly so that secret scanners can catch a leaked key in a public repo before it gets abused. GitHub's secret scanning depends on exactly this. The useful side effect is that a prefix is a reliable provider fingerprint.

Vexi matches the key against a pattern table, resolves a provider id, and looks up the right base URL:

openai      https://api.openai.com/v1
anthropic   https://api.anthropic.com/v1
groq        https://api.groq.com/openai/v1
openrouter  https://openrouter.ai/api/v1
gemini      https://generativelanguage.googleapis.com/v1beta/openai
mistral     https://api.mistral.ai/v1
cerebras    https://api.cerebras.ai/v1
deepseek    https://api.deepseek.com/v1
glm         https://open.bigmodel.cn/api/paas/v4
qwen        https://dashscope-intl.aliyuncs.com/compatible-mode/v1
moonshot    https://api.moonshot.cn/v1
minimax     https://api.minimax.chat/v1

Anthropic gets its own client because its Messages API isn't OpenAI-shaped. Everything else runs through a shared OpenAI-compatible client, which is why adding a provider is usually a one-line change rather than a new integration.

Keys arrive dirtier than you'd think

A detector that only handles clean input fails constantly in practice, because of how keys actually reach the terminal. People copy them out of web consoles, PDFs, Slack messages, and password managers. What lands on the clipboard often includes:

  • Leading or trailing whitespace, and sometimes a trailing newline
  • Zero-width characters and non-breaking spaces from rich-text copy
  • Smart quotes wrapped around the key by a document editor

Any of these produce the same useless outcome: a 401 that looks like a bad key when the key is fine. Vexi strips non-ASCII characters and trims the input before matching. That fix shipped in 0.9.1 specifically because invisible characters were the single most confusing failure mode people hit.

Detection is a guess until it's verified

Pattern matching is a heuristic, not proof. Prefixes get reused, providers change formats, and a key can be perfectly well-formed but revoked, out of credit, or scoped to the wrong project.

So since 0.9.2, setup doesn't trust its own detection. Before writing config to disk, Vexi sends a real inference request to the resolved endpoint. If that request fails, nothing is saved and you see the actual provider error.

This matters more than it sounds. The alternative, save now and fail later, means your first real prompt dies on an error that looks like a bug in the tool, and you have no idea whether the problem is the key, the endpoint, the model name, or your network. Verifying at setup time collapses four possible failures into one clear message, at the moment you can still do something about it.

When there's no pattern to match

Local models and proxies have no meaningful key format at all; Ollama will accept nearly anything. For those, detection is the wrong tool, so vexi setup takes the endpoint URL directly, queries its /models list, and lets you pick from what's actually available rather than typing a model name from memory and hoping.

Try Vexi

Free, open source, MIT licensed. One command.

$npm install -g vexi-cli