[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7523BGF71Q58XMS016VE63T":3,"skill-same:01M7523BGF71Q58XMS016VE63T":49},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":26,"commitSha":27,"skillDirectory":28,"forksCount":29,"repositoryHtmlUrl":30,"repositoryHomepageUrl":31,"ownerHtmlUrl":32,"ownerBlogUrl":31,"ownerDescription":33,"updatedAt":34,"install":35,"resources":48},"01M7523BGF71Q58XMS016VE63T","vercel-ai-gateway",null,"Route every LLM call through one unified API on Vercel - plain \"provider\u002Fmodel\" strings via the AI SDK, automatic provider routing and model fallbacks, observability and per-key cost tracking, and zero data retention. Use when you ask \"how do I add an LLM to my Vercel app\", \"route OpenAI and Anthropic through one API\", \"add model failover \u002F fallback\", \"track LLM cost and spend on Vercel\", \"set a budget per API key\", \"switch providers without changing code\", \"AI_GATEWAY_API_KEY\", or \"stop installing @ai-sdk\u002Fopenai and @ai-sdk\u002Fanthropic separately\". Do NOT use for general AI SDK app code (chat UI, tool calling, structured output) - that is the AI SDK itself; do NOT use for deploy config, env wiring, or edge\u002Fruntime choice - use vercel-deploy-pipeline, vercel-env-management, and vercel-edge-and-isr instead; do NOT use to rate-limit or block abusive AI traffic - use vercel-firewall-and-botid; and do NOT use for app-level latency\u002Fcaching tuning of the route - use next-on-vercel-perf.","SkillMedev\u002Fskills","SkillMedev","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F298078254?v=4","01M74ZSGTQ918CB0VXW4EG3RMX","SkillMe","01M74ZSGVBT497NA95CBT8JTY4",25,"MIT","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fvercel-ai-gateway\u002FSKILL.md",[],[],"2026-11-11 18:27:18",false,"---\nname: vercel-ai-gateway\ndescription: Route every LLM call through one unified API on Vercel - plain \"provider\u002Fmodel\" strings via the AI SDK, automatic provider routing and model fallbacks, observability and per-key cost tracking, and zero data retention. Use when you ask \"how do I add an LLM to my Vercel app\", \"route OpenAI and Anthropic through one API\", \"add model failover \u002F fallback\", \"track LLM cost and spend on Vercel\", \"set a budget per API key\", \"switch providers without changing code\", \"AI_GATEWAY_API_KEY\", or \"stop installing @ai-sdk\u002Fopenai and @ai-sdk\u002Fanthropic separately\". Do NOT use for general AI SDK app code (chat UI, tool calling, structured output) - that is the AI SDK itself; do NOT use for deploy config, env wiring, or edge\u002Fruntime choice - use vercel-deploy-pipeline, vercel-env-management, and vercel-edge-and-isr instead; do NOT use to rate-limit or block abusive AI traffic - use vercel-firewall-and-botid; and do NOT use for app-level latency\u002Fcaching tuning of the route - use next-on-vercel-perf.\nmetadata:\n  title: \"Vercel AI Gateway\"\n---\n\n# Vercel AI Gateway\n\nYou wire an app's LLM calls through **Vercel AI Gateway**: one endpoint, one API\nkey, every provider behind it. The opinionated rule of this pack is *never reach\nfor a provider-specific package by default*. Instead of `@ai-sdk\u002Fopenai` +\n`@ai-sdk\u002Fanthropic` + `@ai-sdk\u002Fgoogle` (each with its own SDK, its own key, its\nown billing), you pass a plain `\"provider\u002Fmodel\"` string to the AI SDK and let\nthe Gateway resolve it. That single decision buys you provider failover, model\nfallbacks, unified cost tracking, and a one-line provider swap - for free, with\nno code change at the call site.\n\nThis is the AI step of the curated *ship-a-Next.js-app-on-Vercel* path. It is\ndeliberately **not** a clone of the official Vercel AI Gateway docs or CLI: it\nsequences the Gateway into the rest of the workflow. Provisioning the key and\npromoting it across environments is `vercel-env-management`; the function it runs\nin (Fluid Compute, full Node.js - the legacy Edge runtime is deprecated) is\n`vercel-edge-and-isr`; shipping it is `vercel-deploy-pipeline`. Rate-limiting or\nblocking abusive traffic to the AI route is `vercel-firewall-and-botid`, and\napp-level latency\u002Fcaching of the route is `next-on-vercel-perf`. This skill owns\nexactly one thing: the call should go through the Gateway as a bare model string.\n\nTrigger eagerly whenever someone is adding an LLM to a Vercel app, juggling\nmultiple providers, wants failover or cost caps, or is about to `npm install` a\nprovider-specific AI package. Catch loose phrasings: \"make it call GPT and Claude\",\n\"add a fallback model\", \"why is my LLM bill a surprise\", \"one API for all my AI\".\n\n## Workflow\n\nRun these in order. Do not skip Step 2 - the whole value of the Gateway is that\nthe call site is provider-agnostic, and a provider-specific package at the call\nsite throws that away.\n\n### Step 1 - Authenticate once, two-line fallback\n\nThe Gateway needs exactly one credential. Locally that is an `AI_GATEWAY_API_KEY`\n(create it in the Vercel dashboard under AI Gateway → API Keys, put it in\n`.env.local`). On a Vercel deployment you do not need a key at all - Fluid Compute\ninjects a `VERCEL_OIDC_TOKEN` automatically and the AI SDK's gateway provider\npicks it up. Write code that works in both places with one fallback:\n\n```ts\n\u002F\u002F Works locally (API key) AND on Vercel (OIDC, auto-injected).\nconst apiKey = process.env.AI_GATEWAY_API_KEY || process.env.VERCEL_OIDC_TOKEN\n```\n\nWhen you use the AI SDK's default gateway provider you usually do not even touch\nthis - the SDK reads `AI_GATEWAY_API_KEY` \u002F `VERCEL_OIDC_TOKEN` for you. Hand the\nactual provisioning and per-environment promotion of `AI_GATEWAY_API_KEY` to\n`vercel-env-management`; do not paste keys into `vercel.ts` or commit `.env.local`.\n\n### Step 2 - Call with a plain \"provider\u002Fmodel\" string (the core move)\n\nInstall **only** the AI SDK. Do **not** install `@ai-sdk\u002Fopenai`,\n`@ai-sdk\u002Fanthropic`, `@ai-sdk\u002Fgoogle`, etc. - the Gateway is the provider.\n\n```bash\nnpm install ai          # the AI SDK. That's it. No provider packages.\n```\n\nThen pass the model as a string `\"\u003Cprovider>\u002F\u003Cmodel>\"`. The AI SDK routes any\nbare model string through the Gateway by default:\n\n```ts\nimport { streamText } from 'ai'\n\nconst result = streamText({\n  model: 'anthropic\u002Fclaude-opus-4.7',   \u002F\u002F \u003C-- provider\u002Fmodel, resolved by the Gateway\n  prompt,\n})\nreturn result.toUIMessageStreamResponse()\n```\n\nSwitching providers is now editing one string - `'openai\u002Fgpt-5.5'`,\n`'google\u002Fgemini-3.1-pro-preview'` - with no new import, no new key, no new SDK.\nThat is the entire reason this skill exists. If you find yourself typing\n`import { openai } from '@ai-sdk\u002Fopenai'`, stop: you have left the Gateway.\n\n(For the wider AI SDK surface - tool calling, structured output, chat UI,\nembeddings - that is the AI SDK itself, a sibling concern, not this skill.)\n\n### Step 3 - Add model fallbacks and provider routing\n\nA single model string can silently fail (provider outage, rate limit, region\nblip). Make the call resilient with `providerOptions.gateway`:\n\n- **`models`** - an ordered list of *fallback models* tried if the primary fails.\n- **`order`** - preferred *provider order* for a model offered by several\n  providers (e.g. Claude via `anthropic`, `bedrock`, or `vertex`).\n- **`only`** - restrict routing to an allow-list of providers (compliance \u002F BYOK).\n\n```ts\nimport { streamText } from 'ai'\n\nconst result = streamText({\n  model: 'openai\u002Fgpt-5.5',                       \u002F\u002F primary\n  prompt,\n  providerOptions: {\n    gateway: {\n      models: ['anthropic\u002Fclaude-opus-4.7',      \u002F\u002F fallback 1 (different provider)\n               'google\u002Fgemini-3.1-pro-preview'], \u002F\u002F fallback 2\n      order: ['azure', 'openai'],                \u002F\u002F provider preference per model\n    },\n  },\n})\n```\n\nKeep the fallback chain to 2-3 models: each failed hop can add up to a full\nrequest timeout to worst-case latency, and if three models across different\nproviders all fail, the outage is systemic - a fourth entry buys nothing. Put at\nleast one fallback on a *different provider* than the primary, or a provider-wide\noutage takes the whole chain down.\n\nThe Gateway records each hop in response metadata (`modelAttempts` →\n`providerAttempts`) so you can see exactly which provider\u002Fmodel served the request\nand why an earlier one was skipped. Use fallbacks for anything user-facing; a\nsingle bare model string is fine only for internal\u002Fbatch work that can retry.\n\n### Step 4 - Turn on zero data retention where data is sensitive\n\nFor PII or regulated content, set `zeroDataRetention: true` so the Gateway routes\nonly to providers that honor ZDR and deletes payloads after processing:\n\n```ts\nconst result = await streamText({\n  model: 'anthropic\u002Fclaude-opus-4.7',\n  prompt: 'Summarize this patient intake form...',\n  providerOptions: { gateway: { zeroDataRetention: true } },\n})\n```\n\nPair this with `only: [...]` when a contract restricts you to specific compliant\nproviders. ZDR narrows the routable provider set, so confirm your fallbacks in\nStep 3 are all ZDR-capable, or the fallback may be dropped.\n\n### Step 5 - Observe spend and cap budgets per key\n\nThe Gateway is also your cost-tracking layer - usage, latency, and spend per model\nland in the AI Gateway dashboard with no instrumentation. For programmatic control,\neach API key carries an optional budget (`limitAmount` + `refreshPeriod`) and you\ncan read live spend from the quotas endpoint:\n\n```bash\n# Live budget + spend for one AI Gateway key.\ncurl \"https:\u002F\u002Fai-gateway.vercel.sh\u002Fv1\u002Fquotas?quotaEntityId=api_key_id_\u003Cyour_key_id>\" \\\n  -H \"Authorization: Bearer $AI_GATEWAY_API_KEY\"\n# -> { \"limitAmount\": 10, \"currentSpend\": 1.04, \"refreshPeriod\": \"monthly\", \"active\": true }\n```\n\nGive each environment its own key (prod, preview) via `vercel-env-management` so\nspend is attributable and a runaway preview cannot drain the prod budget. Keep\npreview\u002Fdev key budgets small - $5-25\u002Fmonth is plenty for testing, and a runaway\nloop then trips at pocket change instead of at the invoice. Size the prod budget\nabout 20% above estimated spend (the calculator below does this) so normal\ntraffic never hits the cap. Note that per-token prices span roughly two orders of\nmagnitude across models - always read the primary *and* fallback models' pricing\nfrom `gateway.getAvailableModels()` rather than assuming they are comparable.\n\n## Quality bar\n\nA Gateway integration is A+ only when all hold:\n\n- The call site uses a **plain `\"provider\u002Fmodel\"` string** through the AI SDK. No\n  `@ai-sdk\u002F\u003Cprovider>` package is installed or imported anywhere.\n- Exactly **one** credential path: `AI_GATEWAY_API_KEY` locally, `VERCEL_OIDC_TOKEN`\n  on Vercel, expressed as the `||` fallback - keys provisioned via\n  `vercel-env-management`, never committed.\n- Any user-facing call has **`models` fallbacks** (2-3 entries, at least one on a\n  different provider); a bare model string is used only for retryable internal work.\n- Sensitive paths set **`zeroDataRetention: true`** and confirm every fallback\n  provider is ZDR-capable.\n- Each environment key has a **budget**, and the launch budget was sized from the\n  cost estimator, not guessed.\n- Switching the primary model is a **one-string edit** - proven by the fact that\n  no provider import exists to change.\n\n## Do NOT\n\n- Do NOT install or import `@ai-sdk\u002Fopenai`, `@ai-sdk\u002Fanthropic`, `@ai-sdk\u002Fgoogle`,\n  or any other provider package \"just to start.\" That is the anti-pattern this\n  skill exists to prevent - it re-introduces per-provider keys, billing, and a\n  hard-coded provider at the call site.\n- Do NOT scatter raw provider API keys (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`)\n  through the app. The Gateway holds provider credentials; your app holds one key.\n- Do NOT hardcode the model string in ten files. Read it from config\u002Fenv so a\n  swap or a fallback edit is one change (still a bare string, still the Gateway).\n- Do NOT ship a single bare model string for user-facing traffic with no\n  `models` fallback - one provider outage becomes a user-visible outage.\n- Do NOT target the deprecated Edge runtime for AI routes to \"save cold starts.\"\n  Default to Fluid Compute (full Node.js, instance reuse cuts cold starts at the\n  same price\u002Fregions) - that runtime choice belongs to `vercel-edge-and-isr`.\n- Do NOT enable `zeroDataRetention` and then list a non-ZDR provider in `models`;\n  the fallback will be silently unavailable.\n- Do NOT hand-roll cost logging. The Gateway dashboard and `\u002Fv1\u002Fquotas` already\n  track spend per key - set a budget instead of building a meter.\n\n## Calculator\n\nSelf-contained Node script. Save as `gateway_cost.js` and run with\n`node gateway_cost.js`. No dependencies. Edit the inputs for your model and\ntraffic; per-token prices come from the Gateway's own model list\n(`gateway.getAvailableModels()` returns `pricing.input` \u002F `pricing.output` per\ntoken) - paste current numbers in. It estimates monthly spend and the per-key\nbudget to set, and warns if a tight budget will throttle traffic.\n\n```javascript\n\u002F\u002F AI Gateway monthly cost + budget estimator. Edit inputs, then: node gateway_cost.js\nconst inputs = {\n  requestsPerDay: 5000,        \u002F\u002F expected requests\u002Fday for this key\u002Fenvironment\n  inputTokensPerReq: 1200,     \u002F\u002F avg prompt tokens (context + user input)\n  outputTokensPerReq: 400,     \u002F\u002F avg completion tokens\n  \u002F\u002F Per-token USD prices from gateway.getAvailableModels() -> model.pricing.*\n  inputPricePerToken: 0.000003,   \u002F\u002F e.g. $3.00 \u002F 1M input tokens\n  outputPricePerToken: 0.000015,  \u002F\u002F e.g. $15.00 \u002F 1M output tokens\n  fallbackOverhead: 0.05,      \u002F\u002F +5% headroom for retries\u002Ffallback attempts\n  budgetRefresh: 'monthly',    \u002F\u002F matches the API key refreshPeriod you set\n}\n\nfunction estimate(i) {\n  const reqsPerMonth = i.requestsPerDay * 30\n  const inputCost = reqsPerMonth * i.inputTokensPerReq * i.inputPricePerToken\n  const outputCost = reqsPerMonth * i.outputTokensPerReq * i.outputPricePerToken\n  const base = inputCost + outputCost\n  const withFallback = base * (1 + i.fallbackOverhead)\n  \u002F\u002F Set the key budget a bit above expected spend so normal traffic isn't capped.\n  const suggestedBudget = Math.ceil((withFallback * 1.2) \u002F 5) * 5 \u002F\u002F round up to $5\n  const costPerThousandReqs = (withFallback \u002F reqsPerMonth) * 1000\n  return { reqsPerMonth, inputCost, outputCost, withFallback, suggestedBudget, costPerThousandReqs }\n}\n\nconst r = estimate(inputs)\nconst usd = (n) => '$' + n.toFixed(2)\nconsole.log('Requests \u002F month:            ', r.reqsPerMonth.toLocaleString())\nconsole.log('Input token cost:            ', usd(r.inputCost))\nconsole.log('Output token cost:           ', usd(r.outputCost))\nconsole.log('Est. monthly spend (w\u002F fallback):', usd(r.withFallback))\nconsole.log('Cost per 1,000 requests:     ', usd(r.costPerThousandReqs))\nconsole.log('Suggested key budget (' + inputs.budgetRefresh + '): ', usd(r.suggestedBudget))\nconsole.log('Set via POST \u002Fv1\u002Fapi-keys aiGatewayQuota.limitAmount =', r.suggestedBudget)\n```\n\n### Worked example output\n\nWith the inputs above the script prints:\n\n```\nRequests \u002F month:             150,000\nInput token cost:             $540.00\nOutput token cost:            $900.00\nEst. monthly spend (w\u002F fallback): $1512.00\nCost per 1,000 requests:      $10.08\nSuggested key budget (monthly):  $1815.00\nSet via POST \u002Fv1\u002Fapi-keys aiGatewayQuota.limitAmount = 1815\n```\n\nRead it: 5,000 requests\u002Fday at this model costs about $1,512\u002Fmonth, roughly $10\nper thousand requests. Set the key's `limitAmount` to ~$1,815 (20% headroom) so\nnormal traffic is never capped but a runaway loop trips the budget instead of the\ninvoice. Re-run with the cheaper fallback's prices to see the floor if the primary\nis failing over - and if `cost per 1,000 requests` is too high, the lever is the\nprimary model, not the Gateway.\n\n## Template: gateway-integration-checklist\n\nCopy this into the PR description for the AI route. Every box must be checked.\n\n```\nAI GATEWAY INTEGRATION. [FILL: route \u002F feature]\n\nCALL SITE\n  [ ] Model passed as plain \"provider\u002Fmodel\" string via the AI SDK\n  [ ] Model string read from config\u002Fenv: [FILL: var name]\n  [ ] NO @ai-sdk\u002F\u003Cprovider> package installed (grep package.json to confirm)\n  [ ] NO raw provider keys in env (only AI_GATEWAY_API_KEY)\n\nAUTH (provisioned by vercel-env-management)\n  [ ] Local: AI_GATEWAY_API_KEY in .env.local (gitignored)\n  [ ] Vercel: relies on auto-injected VERCEL_OIDC_TOKEN (no key needed)\n  [ ] Fallback expressed: AI_GATEWAY_API_KEY || VERCEL_OIDC_TOKEN\n\nRESILIENCE\n  [ ] Primary model:            [FILL]\n  [ ] Fallback models (order):  [FILL, FILL]\n  [ ] Provider order if multi-provider: [FILL]\n  [ ] Sensitive data? zeroDataRetention: true  -> all fallbacks ZDR-capable\n\nCOST\n  [ ] Ran gateway_cost.js - est. monthly spend: $[FILL]\n  [ ] Per-environment key budget set: $[FILL] \u002F [daily|weekly|monthly]\n  [ ] Dashboard reviewed after first day of real traffic\n\nRUNTIME (owned by vercel-edge-and-isr)\n  [ ] Route runs on Fluid Compute (Node.js), not deprecated Edge\n```\n\n## references\u002Fwhy-bare-strings\n\nProvider-specific packages (`@ai-sdk\u002Fopenai`, etc.) were the original AI SDK\npattern: import a provider factory, call `openai('gpt-...')`, supply that\nprovider's key. It works, but it hard-codes the provider at the call site and\nforces a separate key and bill per provider. The Gateway inverts this: the AI SDK\ntreats any bare `\"provider\u002Fmodel\"` string as \"resolve through the configured\ngateway provider,\" so the call site no longer names an SDK at all. The provider\nbecomes data (a string, a config value), not code (an import). That is what makes\nfailover (`models`), provider routing (`order`), one-key auth, and unified billing\npossible without touching the call. The only time you reach back for a\nprovider-specific package is a genuinely provider-exclusive feature the Gateway\ndoes not surface - rare, and worth flagging explicitly when you do.\n\n## references\u002Fprovider-options-cheatsheet\n\nAll live under `providerOptions.gateway` on any AI SDK call:\n\n```\nmodels: ['provider\u002Fmodel', ...]   ordered fallback models if primary fails\norder:  ['azure','openai', ...]   preferred provider order for a multi-provider model\nonly:   ['bedrock','anthropic']   allow-list - restrict routing to these providers\nzeroDataRetention: true           route only to ZDR providers; delete after processing\nbyok:   { azure: [{ apiKey, ... , modelMappings }] }   bring your own provider key\u002Fdeployment\n```\n\nPer-provider reasoning\u002Fthinking options nest under the provider name alongside\n`gateway` (e.g. `providerOptions.anthropic.thinking`, `providerOptions.bedrock.reasoningConfig`)\nso the matching config is applied to whichever provider the Gateway selects.\n\nThe OpenAI-compatible REST surface is `https:\u002F\u002Fai-gateway.vercel.sh\u002Fv1` with\n`Authorization: Bearer $AI_GATEWAY_API_KEY` - handy for non-JS callers (Python,\ncurl, coding agents) that cannot use the AI SDK. Same routing\u002Ffallback semantics\nvia the same `providerOptions.gateway` body.\n","# Vercel AI Gateway\n\nYou wire an app's LLM calls through **Vercel AI Gateway**: one endpoint, one API\nkey, every provider behind it. The opinionated rule of this pack is *never reach\nfor a provider-specific package by default*. Instead of `@ai-sdk\u002Fopenai` +\n`@ai-sdk\u002Fanthropic` + `@ai-sdk\u002Fgoogle` (each with its own SDK, its own key, its\nown billing), you pass a plain `\"provider\u002Fmodel\"` string to the AI SDK and let\nthe Gateway resolve it. That single decision buys you provider failover, model\nfallbacks, unified cost tracking, and a one-line provider swap - for free, with\nno code change at the call site.\n\nThis is the AI step of the curated *ship-a-Next.js-app-on-Vercel* path. It is\ndeliberately **not** a clone of the official Vercel AI Gateway docs or CLI: it\nsequences the Gateway into the rest of the workflow. Provisioning the key and\npromoting it across environments is `vercel-env-management`; the function it runs\nin (Fluid Compute, full Node.js - the legacy Edge runtime is deprecated) is\n`vercel-edge-and-isr`; shipping it is `vercel-deploy-pipeline`. Rate-limiting or\nblocking abusive traffic to the AI route is `vercel-firewall-and-botid`, and\napp-level latency\u002Fcaching of the route is `next-on-vercel-perf`. This skill owns\nexactly one thing: the call should go through the Gateway as a bare model string.\n\nTrigger eagerly whenever someone is adding an LLM to a Vercel app, juggling\nmultiple providers, wants failover or cost caps, or is about to `npm install` a\nprovider-specific AI package. Catch loose phrasings: \"make it call GPT and Claude\",\n\"add a fallback model\", \"why is my LLM bill a surprise\", \"one API for all my AI\".\n\n## Workflow\n\nRun these in order. Do not skip Step 2 - the whole value of the Gateway is that\nthe call site is provider-agnostic, and a provider-specific package at the call\nsite throws that away.\n\n### Step 1 - Authenticate once, two-line fallback\n\nThe Gateway needs exactly one credential. Locally that is an `AI_GATEWAY_API_KEY`\n(create it in the Vercel dashboard under AI Gateway → API Keys, put it in\n`.env.local`). On a Vercel deployment you do not need a key at all - Fluid Compute\ninjects a `VERCEL_OIDC_TOKEN` automatically and the AI SDK's gateway provider\npicks it up. Write code that works in both places with one fallback:\n\n```ts\n\u002F\u002F Works locally (API key) AND on Vercel (OIDC, auto-injected).\nconst apiKey = process.env.AI_GATEWAY_API_KEY || process.env.VERCEL_OIDC_TOKEN\n```\n\nWhen you use the AI SDK's default gateway provider you usually do not even touch\nthis - the SDK reads `AI_GATEWAY_API_KEY` \u002F `VERCEL_OIDC_TOKEN` for you. Hand the\nactual provisioning and per-environment promotion of `AI_GATEWAY_API_KEY` to\n`vercel-env-management`; do not paste keys into `vercel.ts` or commit `.env.local`.\n\n### Step 2 - Call with a plain \"provider\u002Fmodel\" string (the core move)\n\nInstall **only** the AI SDK. Do **not** install `@ai-sdk\u002Fopenai`,\n`@ai-sdk\u002Fanthropic`, `@ai-sdk\u002Fgoogle`, etc. - the Gateway is the provider.\n\n```bash\nnpm install ai          # the AI SDK. That's it. No provider packages.\n```\n\nThen pass the model as a string `\"\u003Cprovider>\u002F\u003Cmodel>\"`. The AI SDK routes any\nbare model string through the Gateway by default:\n\n```ts\nimport { streamText } from 'ai'\n\nconst result = streamText({\n  model: 'anthropic\u002Fclaude-opus-4.7',   \u002F\u002F \u003C-- provider\u002Fmodel, resolved by the Gateway\n  prompt,\n})\nreturn result.toUIMessageStreamResponse()\n```\n\nSwitching providers is now editing one string - `'openai\u002Fgpt-5.5'`,\n`'google\u002Fgemini-3.1-pro-preview'` - with no new import, no new key, no new SDK.\nThat is the entire reason this skill exists. If you find yourself typing\n`import { openai } from '@ai-sdk\u002Fopenai'`, stop: you have left the Gateway.\n\n(For the wider AI SDK surface - tool calling, structured output, chat UI,\nembeddings - that is the AI SDK itself, a sibling concern, not this skill.)\n\n### Step 3 - Add model fallbacks and provider routing\n\nA single model string can silently fail (provider outage, rate limit, region\nblip). Make the call resilient with `providerOptions.gateway`:\n\n- **`models`** - an ordered list of *fallback models* tried if the primary fails.\n- **`order`** - preferred *provider order* for a model offered by several\n  providers (e.g. Claude via `anthropic`, `bedrock`, or `vertex`).\n- **`only`** - restrict routing to an allow-list of providers (compliance \u002F BYOK).\n\n```ts\nimport { streamText } from 'ai'\n\nconst result = streamText({\n  model: 'openai\u002Fgpt-5.5',                       \u002F\u002F primary\n  prompt,\n  providerOptions: {\n    gateway: {\n      models: ['anthropic\u002Fclaude-opus-4.7',      \u002F\u002F fallback 1 (different provider)\n               'google\u002Fgemini-3.1-pro-preview'], \u002F\u002F fallback 2\n      order: ['azure', 'openai'],                \u002F\u002F provider preference per model\n    },\n  },\n})\n```\n\nKeep the fallback chain to 2-3 models: each failed hop can add up to a full\nrequest timeout to worst-case latency, and if three models across different\nproviders all fail, the outage is systemic - a fourth entry buys nothing. Put at\nleast one fallback on a *different provider* than the primary, or a provider-wide\noutage takes the whole chain down.\n\nThe Gateway records each hop in response metadata (`modelAttempts` →\n`providerAttempts`) so you can see exactly which provider\u002Fmodel served the request\nand why an earlier one was skipped. Use fallbacks for anything user-facing; a\nsingle bare model string is fine only for internal\u002Fbatch work that can retry.\n\n### Step 4 - Turn on zero data retention where data is sensitive\n\nFor PII or regulated content, set `zeroDataRetention: true` so the Gateway routes\nonly to providers that honor ZDR and deletes payloads after processing:\n\n```ts\nconst result = await streamText({\n  model: 'anthropic\u002Fclaude-opus-4.7',\n  prompt: 'Summarize this patient intake form...',\n  providerOptions: { gateway: { zeroDataRetention: true } },\n})\n```\n\nPair this with `only: [...]` when a contract restricts you to specific compliant\nproviders. ZDR narrows the routable provider set, so confirm your fallbacks in\nStep 3 are all ZDR-capable, or the fallback may be dropped.\n\n### Step 5 - Observe spend and cap budgets per key\n\nThe Gateway is also your cost-tracking layer - usage, latency, and spend per model\nland in the AI Gateway dashboard with no instrumentation. For programmatic control,\neach API key carries an optional budget (`limitAmount` + `refreshPeriod`) and you\ncan read live spend from the quotas endpoint:\n\n```bash\n# Live budget + spend for one AI Gateway key.\ncurl \"https:\u002F\u002Fai-gateway.vercel.sh\u002Fv1\u002Fquotas?quotaEntityId=api_key_id_\u003Cyour_key_id>\" \\\n  -H \"Authorization: Bearer $AI_GATEWAY_API_KEY\"\n# -> { \"limitAmount\": 10, \"currentSpend\": 1.04, \"refreshPeriod\": \"monthly\", \"active\": true }\n```\n\nGive each environment its own key (prod, preview) via `vercel-env-management` so\nspend is attributable and a runaway preview cannot drain the prod budget. Keep\npreview\u002Fdev key budgets small - $5-25\u002Fmonth is plenty for testing, and a runaway\nloop then trips at pocket change instead of at the invoice. Size the prod budget\nabout 20% above estimated spend (the calculator below does this) so normal\ntraffic never hits the cap. Note that per-token prices span roughly two orders of\nmagnitude across models - always read the primary *and* fallback models' pricing\nfrom `gateway.getAvailableModels()` rather than assuming they are comparable.\n\n## Quality bar\n\nA Gateway integration is A+ only when all hold:\n\n- The call site uses a **plain `\"provider\u002Fmodel\"` string** through the AI SDK. No\n  `@ai-sdk\u002F\u003Cprovider>` package is installed or imported anywhere.\n- Exactly **one** credential path: `AI_GATEWAY_API_KEY` locally, `VERCEL_OIDC_TOKEN`\n  on Vercel, expressed as the `||` fallback - keys provisioned via\n  `vercel-env-management`, never committed.\n- Any user-facing call has **`models` fallbacks** (2-3 entries, at least one on a\n  different provider); a bare model string is used only for retryable internal work.\n- Sensitive paths set **`zeroDataRetention: true`** and confirm every fallback\n  provider is ZDR-capable.\n- Each environment key has a **budget**, and the launch budget was sized from the\n  cost estimator, not guessed.\n- Switching the primary model is a **one-string edit** - proven by the fact that\n  no provider import exists to change.\n\n## Do NOT\n\n- Do NOT install or import `@ai-sdk\u002Fopenai`, `@ai-sdk\u002Fanthropic`, `@ai-sdk\u002Fgoogle`,\n  or any other provider package \"just to start.\" That is the anti-pattern this\n  skill exists to prevent - it re-introduces per-provider keys, billing, and a\n  hard-coded provider at the call site.\n- Do NOT scatter raw provider API keys (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`)\n  through the app. The Gateway holds provider credentials; your app holds one key.\n- Do NOT hardcode the model string in ten files. Read it from config\u002Fenv so a\n  swap or a fallback edit is one change (still a bare string, still the Gateway).\n- Do NOT ship a single bare model string for user-facing traffic with no\n  `models` fallback - one provider outage becomes a user-visible outage.\n- Do NOT target the deprecated Edge runtime for AI routes to \"save cold starts.\"\n  Default to Fluid Compute (full Node.js, instance reuse cuts cold starts at the\n  same price\u002Fregions) - that runtime choice belongs to `vercel-edge-and-isr`.\n- Do NOT enable `zeroDataRetention` and then list a non-ZDR provider in `models`;\n  the fallback will be silently unavailable.\n- Do NOT hand-roll cost logging. The Gateway dashboard and `\u002Fv1\u002Fquotas` already\n  track spend per key - set a budget instead of building a meter.\n\n## Calculator\n\nSelf-contained Node script. Save as `gateway_cost.js` and run with\n`node gateway_cost.js`. No dependencies. Edit the inputs for your model and\ntraffic; per-token prices come from the Gateway's own model list\n(`gateway.getAvailableModels()` returns `pricing.input` \u002F `pricing.output` per\ntoken) - paste current numbers in. It estimates monthly spend and the per-key\nbudget to set, and warns if a tight budget will throttle traffic.\n\n```javascript\n\u002F\u002F AI Gateway monthly cost + budget estimator. Edit inputs, then: node gateway_cost.js\nconst inputs = {\n  requestsPerDay: 5000,        \u002F\u002F expected requests\u002Fday for this key\u002Fenvironment\n  inputTokensPerReq: 1200,     \u002F\u002F avg prompt tokens (context + user input)\n  outputTokensPerReq: 400,     \u002F\u002F avg completion tokens\n  \u002F\u002F Per-token USD prices from gateway.getAvailableModels() -> model.pricing.*\n  inputPricePerToken: 0.000003,   \u002F\u002F e.g. $3.00 \u002F 1M input tokens\n  outputPricePerToken: 0.000015,  \u002F\u002F e.g. $15.00 \u002F 1M output tokens\n  fallbackOverhead: 0.05,      \u002F\u002F +5% headroom for retries\u002Ffallback attempts\n  budgetRefresh: 'monthly',    \u002F\u002F matches the API key refreshPeriod you set\n}\n\nfunction estimate(i) {\n  const reqsPerMonth = i.requestsPerDay * 30\n  const inputCost = reqsPerMonth * i.inputTokensPerReq * i.inputPricePerToken\n  const outputCost = reqsPerMonth * i.outputTokensPerReq * i.outputPricePerToken\n  const base = inputCost + outputCost\n  const withFallback = base * (1 + i.fallbackOverhead)\n  \u002F\u002F Set the key budget a bit above expected spend so normal traffic isn't capped.\n  const suggestedBudget = Math.ceil((withFallback * 1.2) \u002F 5) * 5 \u002F\u002F round up to $5\n  const costPerThousandReqs = (withFallback \u002F reqsPerMonth) * 1000\n  return { reqsPerMonth, inputCost, outputCost, withFallback, suggestedBudget, costPerThousandReqs }\n}\n\nconst r = estimate(inputs)\nconst usd = (n) => '$' + n.toFixed(2)\nconsole.log('Requests \u002F month:            ', r.reqsPerMonth.toLocaleString())\nconsole.log('Input token cost:            ', usd(r.inputCost))\nconsole.log('Output token cost:           ', usd(r.outputCost))\nconsole.log('Est. monthly spend (w\u002F fallback):', usd(r.withFallback))\nconsole.log('Cost per 1,000 requests:     ', usd(r.costPerThousandReqs))\nconsole.log('Suggested key budget (' + inputs.budgetRefresh + '): ', usd(r.suggestedBudget))\nconsole.log('Set via POST \u002Fv1\u002Fapi-keys aiGatewayQuota.limitAmount =', r.suggestedBudget)\n```\n\n### Worked example output\n\nWith the inputs above the script prints:\n\n```\nRequests \u002F month:             150,000\nInput token cost:             $540.00\nOutput token cost:            $900.00\nEst. monthly spend (w\u002F fallback): $1512.00\nCost per 1,000 requests:      $10.08\nSuggested key budget (monthly):  $1815.00\nSet via POST \u002Fv1\u002Fapi-keys aiGatewayQuota.limitAmount = 1815\n```\n\nRead it: 5,000 requests\u002Fday at this model costs about $1,512\u002Fmonth, roughly $10\nper thousand requests. Set the key's `limitAmount` to ~$1,815 (20% headroom) so\nnormal traffic is never capped but a runaway loop trips the budget instead of the\ninvoice. Re-run with the cheaper fallback's prices to see the floor if the primary\nis failing over - and if `cost per 1,000 requests` is too high, the lever is the\nprimary model, not the Gateway.\n\n## Template: gateway-integration-checklist\n\nCopy this into the PR description for the AI route. Every box must be checked.\n\n```\nAI GATEWAY INTEGRATION. [FILL: route \u002F feature]\n\nCALL SITE\n  [ ] Model passed as plain \"provider\u002Fmodel\" string via the AI SDK\n  [ ] Model string read from config\u002Fenv: [FILL: var name]\n  [ ] NO @ai-sdk\u002F\u003Cprovider> package installed (grep package.json to confirm)\n  [ ] NO raw provider keys in env (only AI_GATEWAY_API_KEY)\n\nAUTH (provisioned by vercel-env-management)\n  [ ] Local: AI_GATEWAY_API_KEY in .env.local (gitignored)\n  [ ] Vercel: relies on auto-injected VERCEL_OIDC_TOKEN (no key needed)\n  [ ] Fallback expressed: AI_GATEWAY_API_KEY || VERCEL_OIDC_TOKEN\n\nRESILIENCE\n  [ ] Primary model:            [FILL]\n  [ ] Fallback models (order):  [FILL, FILL]\n  [ ] Provider order if multi-provider: [FILL]\n  [ ] Sensitive data? zeroDataRetention: true  -> all fallbacks ZDR-capable\n\nCOST\n  [ ] Ran gateway_cost.js - est. monthly spend: $[FILL]\n  [ ] Per-environment key budget set: $[FILL] \u002F [daily|weekly|monthly]\n  [ ] Dashboard reviewed after first day of real traffic\n\nRUNTIME (owned by vercel-edge-and-isr)\n  [ ] Route runs on Fluid Compute (Node.js), not deprecated Edge\n```\n\n## references\u002Fwhy-bare-strings\n\nProvider-specific packages (`@ai-sdk\u002Fopenai`, etc.) were the original AI SDK\npattern: import a provider factory, call `openai('gpt-...')`, supply that\nprovider's key. It works, but it hard-codes the provider at the call site and\nforces a separate key and bill per provider. The Gateway inverts this: the AI SDK\ntreats any bare `\"provider\u002Fmodel\"` string as \"resolve through the configured\ngateway provider,\" so the call site no longer names an SDK at all. The provider\nbecomes data (a string, a config value), not code (an import). That is what makes\nfailover (`models`), provider routing (`order`), one-key auth, and unified billing\npossible without touching the call. The only time you reach back for a\nprovider-specific package is a genuinely provider-exclusive feature the Gateway\ndoes not surface - rare, and worth flagging explicitly when you do.\n\n## references\u002Fprovider-options-cheatsheet\n\nAll live under `providerOptions.gateway` on any AI SDK call:\n\n```\nmodels: ['provider\u002Fmodel', ...]   ordered fallback models if primary fails\norder:  ['azure','openai', ...]   preferred provider order for a multi-provider model\nonly:   ['bedrock','anthropic']   allow-list - restrict routing to these providers\nzeroDataRetention: true           route only to ZDR providers; delete after processing\nbyok:   { azure: [{ apiKey, ... , modelMappings }] }   bring your own provider key\u002Fdeployment\n```\n\nPer-provider reasoning\u002Fthinking options nest under the provider name alongside\n`gateway` (e.g. `providerOptions.anthropic.thinking`, `providerOptions.bedrock.reasoningConfig`)\nso the matching config is applied to whichever provider the Gateway selects.\n\nThe OpenAI-compatible REST surface is `https:\u002F\u002Fai-gateway.vercel.sh\u002Fv1` with\n`Authorization: Bearer $AI_GATEWAY_API_KEY` - handy for non-JS callers (Python,\ncurl, coding agents) that cannot use the AI SDK. Same routing\u002Ffallback semantics\nvia the same `providerOptions.gateway` body.\n",{"name":5,"metadata":24,"description":7},{"title":25},"Vercel AI Gateway","main","97a13607d669157a4a16d5ba79b77f208319f7b9","skills\u002Fvercel-ai-gateway",3,"https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills","https:\u002F\u002Fskillme.dev","https:\u002F\u002Fgithub.com\u002FSkillMedev","MCP-native catalog of Claude Agent Skills. Browse, recommend, install, and auto-apply skills in chat. Open source, every skill free and clonable on GitHub.","2026-10-14 03:19:31",{"source":8,"skillName":5,"commands":36,"prompt":46,"zipAvailable":47},[37,40,43],{"tool":38,"command":39},"npx","npx skills add SkillMedev\u002Fskills --skill vercel-ai-gateway",{"tool":41,"command":42},"bunx","bunx skills add SkillMedev\u002Fskills --skill vercel-ai-gateway",{"tool":44,"command":45},"pnpm","pnpm dlx skills add SkillMedev\u002Fskills --skill vercel-ai-gateway","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fvercel-ai-gateway\u002FSKILL.md",true,[],[50,59,66,73,80,87],{"skillNo":51,"name":52,"nameZh":53,"description":54,"descriptionZh":55,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":56,"categories":57,"keywords":58,"publishedAt":19},"01M75271B256DF3FX2VG5VRYEE","zone-2-cardio-plan","有氧运动计划","Use when someone asks to build a steady-state cardio plan, train an aerobic base or Zone 2, structure easy or endurance weekly cardio, train by heart-rate zones, or improve resting heart rate, VO2, or endurance. Builds a heart-rate-zone aerobic training block with session structure, modality choice, and progression. General fitness guidance, not medical advice. Do NOT use to design a strength or lifting program (use Strength Training Plan), high-intensity interval conditioning, HIIT, or circuits (use Conditioning & HIIT Program), or a mobility\u002Fflexibility routine (use Mobility Routine).","当有人要求制定稳态有氧训练计划、进行有氧基础训练或达到第二区间、安排轻松或耐力型的每周有氧训练、按心率区间训练，或提高静息心率、最大摄氧量或耐力时，可以使用此方案。该方案构建了一个包含训练计划结构、训练方式选择和进度安排的心率区间有氧训练模块。本方案仅提供一般健身指导，不构成医疗建议。请勿用于设计力量或举重训练计划（请使用力量训练计划）、高强度间歇训练 (HIIT) 或循环训练（请使用体能训练和 HIIT 计划），或灵活性\u002F柔韧性训练（请使用灵活性训练计划）。","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzone-2-cardio-plan\u002FSKILL.md",[],[],{"skillNo":60,"name":61,"nameZh":6,"description":62,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":63,"categories":64,"keywords":65,"publishedAt":19},"01M7526VP1QBBKYBE17S1WR86Y","youtube-script-writer","Writes retention-engineered long-form YouTube scripts on a hook\u002Fbody\u002Fpayoff architecture - a first-30-seconds hook that survives the retention cliff, a beat-sheet body with mini-hooks and bridges, timed pattern interrupts, and a payoff that over-delivers - with B-roll and editing cues marked inline. Use when someone says \"script my next video\", \"my retention graph dies at the start\", \"tighten this draft\", or \"outline a video on X\". Do NOT use for the 3-second opener of TikTok, Reels, or Shorts - use video-hook-writer instead; do NOT use for spoken voiceover synced to on-screen tutorial actions - use narration-script instead; do NOT use for a sales demo built on a buyer's discovery notes - use demo-script instead; do NOT use to design the thumbnail and title - use thumbnail-concept instead.","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fyoutube-script-writer\u002FSKILL.md",[],[],{"skillNo":67,"name":68,"nameZh":6,"description":69,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":70,"categories":71,"keywords":72,"publishedAt":19},"01M7526P2T0WKMHDXS4Q58237T","win-back-campaign","Designs segmented win-back email sequences for dormant users - dormancy tiers, a three-beat sequence with a single proportional incentive, and a suppression rule - and measures success by re-activation, not opens. Use when someone says \"our users went quiet\", \"design a win-back campaign\", \"how do I re-engage lapsed customers\", \"should we email people who haven't logged in for months\", or lifecycle messaging has stopped landing with a lapsed segment. Do NOT use for recovering an unfinished checkout - use abandoned-cart-sequence instead. Do NOT use for diagnosing and fixing why active customers cancel - use churn-reduction instead. Do NOT use for building always-on onboarding or nurture flows - use email-drip-builder instead.","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fwin-back-campaign\u002FSKILL.md",[],[],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":19},"01M7526HF2RCDJ50P93WRZRHVV","wikipedia-style","Writes neutral, verifiable, encyclopedic prose following Wikipedia's core content policies and manual of style - NPOV, inline citations, notability-backed claims, and a strict ban on promotional language. Use when someone asks \"write this like a Wikipedia article\", \"draft a Wikipedia page for this company or person\", \"make this neutral and encyclopedic\", or \"why does my article draft keep getting rejected\". Do NOT use for persuasive or opinion writing - use op-ed-writer instead; for thesis-driven academic papers, use academic-essay; for verifying claims in existing text, use fact-checker.","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fwikipedia-style\u002FSKILL.md",[],[],{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":86,"publishedAt":19},"01M7526D43CTGRKGKNQ2GB0KVX","whitepapers","Structures and writes authoritative B2B whitepapers - a standalone executive summary, a data-sized problem statement, methodology, evidence-driven findings, recommendations, and a soft call to action - flagging every claim that needs a real citation. Use when a marketer asks \"write a whitepaper on this topic\", \"turn our research into a lead-gen asset\", \"make this credible enough for executives\", or a draft reads like a product pitch instead of analysis. Do NOT use for customer-story-driven proof - use case-study-builder instead; for policy audiences, use policy-brief.","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fwhitepapers\u002FSKILL.md",[],[],{"skillNo":88,"name":89,"nameZh":6,"description":90,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":93,"publishedAt":19},"01M75268423Y3K50SY5WC2NX2G","white-space-analysis","Finds unmet market gaps by ranking jobs-to-be-done on importance versus satisfaction, overlaying them against current solutions and workarounds, and validating that each gap is real, winnable, and worth winning. Use when someone asks \"where are the gaps in this market\", \"what's underserved here\", \"where should we play next\", or is hunting for product, feature, or market-entry opportunities. Do NOT use for profiling competitors and building battle cards - use competitive-intelligence instead; for putting a dollar figure on an identified opportunity - use market-sizing instead; for extracting jobs-to-be-done from raw customer interviews - use jtbd-extractor instead.","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fwhite-space-analysis\u002FSKILL.md",[],[]]