How Vercel AI Gateway Routes Requests Across Anthropic, OpenAI, and Google Models in DeskcommCRM
DeskcommCRM centralizes AI model routing through a unified gateway wrapper that resolves provider-prefixed model strings into concrete SDK clients using a four-tier fallback hierarchy.
DeskcommCRM implements a Vercel AI Gateway routing layer to seamlessly switch between Anthropic, OpenAI, and Google models without modifying application logic. The architecture uses provider-agnostic model identifiers and environment-driven resolution logic defined in lib/ai/gateway.ts. This design ensures that AI features degrade gracefully when credentials are missing while supporting advanced routing through OpenRouter or direct provider APIs.
The Model String Convention
The routing system relies on slash-separated model identifiers that encode both the provider and the specific model. When a component requests AI generation, it passes a string such as:
"anthropic/claude-sonnet-5""openai/gpt-4o-mini""google/gemini-1.5-pro"
These strings remain agnostic to the underlying transport mechanism. The resolveLanguageModel() function in lib/ai/gateway.ts consumes these identifiers and determines the appropriate resolution strategy at runtime.
The Four-Tier Resolution Strategy
The gateway implements a prioritized fallback chain to maximize flexibility while ensuring reliability.
1. Vercel AI Gateway (Primary Route)
If any AI Gateway credentials are present—specifically AI_GATEWAY_API_KEY or ANTHROPIC_API_KEY as a fallback—the function returns the raw model string unchanged. The @ai-sdk/* libraries recognize the slash-separated identifier and forward it to the Vercel gateway, which internally selects the appropriate provider (Anthropic, OpenAI, Google) and handles billing.
This path is the default for fresh self-hosted installations where the gateway represents the only configured route.
2. OpenRouter Proxy
When OPENROUTER_API_KEY is configured, the function builds an OpenAI-compatible client using createOpenAI pointed at https://openrouter.ai/api/v1. The same provider-prefixed model string is passed directly to OpenRouter, which then proxies the request to the underlying provider.
Use this approach when the platform requires cost-control features or custom provider selection logic that OpenRouter provides.
3. Direct Provider SDKs
If the gateway is not configured, the system falls back to direct SDK instantiation based on the prefix:
- Anthropic: Strings starting with
"anthropic/"triggercreateAnthropic()usingANTHROPIC_API_KEY, with the prefix stripped before passing to the client. - OpenAI: The
"openai/"prefix routes tocreateOpenAI()usingOPENAI_API_KEY. - Google: The
"google/"prefix would route to a Google client (the repository currently imports only Anthropic and OpenAI implementations, but the pattern supports Google expansion).
This tier activates when the gateway is not configured and the caller supplies provider-specific API keys.
4. Graceful Degradation
If no credentials match any tier, resolveLanguageModel() returns null. Workers and actions check for this result and skip the AI step with a clear "AI not configured" reason, preventing runtime network errors in environments without AI credentials.
Gateway Headers and Tenant Isolation
The wrapper supplies a gatewayHeaders() function that injects metadata on every request:
X-AI-Gateway-Tenant-Id: Enables per-tenant usage trackingX-AI-Gateway-Zero-Retention: Enforces privacy-by-default policies
These headers ensure that even when routing through third-party providers, the system maintains audit trails and compliance controls.
Implementation Examples
Worker Integration with Gateway Routing
The workers/ai-response-worker.ts file demonstrates the standard consumption pattern:
import { resolveLanguageModel, gatewayHeaders } from "@/lib/ai/gateway";
const model = resolveLanguageModel("anthropic/claude-sonnet-5");
if (!model) {
// AI not configured → skip processing
return { skip: true };
}
const response = await model.generate({
prompt: "Summarise the ticket",
// Attach tenant metadata for the gateway
headers: gatewayHeaders({ organizationId: org.id }),
});
Direct Provider Bypass
For scenarios requiring direct SDK access without the gateway wrapper:
import { createOpenAI } from "@ai-sdk/openai";
const client = createOpenAI({ apiKey: process.env.OPENAI_API_KEY! });
const model = client("gpt-4o-mini"); // Note: no provider prefix
OpenRouter Configuration
To route through OpenRouter instead of the native gateway:
// Environment configuration
process.env.OPENROUTER_API_KEY = "or-key";
process.env.OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
// Usage remains identical
const model = resolveLanguageModel("openrouter/anthropic/claude-3-5-sonnet");
Key Files in the Routing Pipeline
lib/ai/gateway.ts: Central Vercel AI Gateway wrapper containingresolveLanguageModel()andgatewayHeaders().lib/ai/gateway-binding.ts: Demonstrates how workers bind resolved models to concrete SDK calls.workers/ai-response-worker.ts: Example worker consuming the gateway for ticket summarization.workers/ai-sentiment-worker.ts: Sentiment analysis worker using the same routing layer.lib/env.ts: Environment variable definitions includingAI_GATEWAY_API_KEY,OPENROUTER_API_KEY, and provider-specific keys.
Summary
- Provider-agnostic routing uses slash-separated model strings (e.g.,
anthropic/claude-sonnet-5) to decouple application code from specific AI providers. - Four-tier fallback prioritizes Vercel AI Gateway, then OpenRouter, then direct SDKs, then graceful null returns.
- Lazy initialization via
isAiGatewayConfigured()prevents import-time errors when credentials are absent. - Tenant isolation is enforced through
gatewayHeaders()injecting tracking and privacy flags on every request.
Frequently Asked Questions
How does DeskcommCRM handle missing AI credentials?
The system uses lazy initialization to check for credential presence at runtime rather than import time. If resolveLanguageModel() detects no configured keys, it returns null, allowing workers to skip AI processing with a clear status message rather than throwing network errors.
What distinguishes Vercel AI Gateway routing from OpenRouter in this codebase?
Vercel AI Gateway handles provider selection internally using the slash-separated model identifier, requiring only a single API key. OpenRouter requires explicit client configuration pointing to https://openrouter.ai/api/v1 but offers additional cost-control and routing logic. The gateway prefers Vercel's solution when AI_GATEWAY_API_KEY is present, falling back to OpenRouter only when OPENROUTER_API_KEY is set instead.
Can Google models be used with this routing system?
Yes, the architecture supports Google models through the "google/" prefix convention, though the current repository imports only Anthropic and OpenAI SDKs. Adding Google support requires importing the Google AI SDK and extending the prefix-checking logic in lib/ai/gateway.ts following the existing pattern.
How are tenant-specific headers injected into AI requests?
The gatewayHeaders() function in lib/ai/gateway.ts automatically injects X-AI-Gateway-Tenant-Id and X-AI-Gateway-Zero-Retention headers. Workers pass their organization ID to this function, ensuring every request carries metadata for usage tracking and privacy compliance regardless of the underlying provider.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →