netlify-ai-gateway について
netlify-ai-gateway は、Netlify Functions と Edge Functions から AI モデルを呼び出すためのスキルです。Netlify アプリの開発者向けに、注入された認証情報と各プロバイダーの公式 SDK を使った複数のモデルサービスへの接続と、ローカル開発を案内します。
主な機能
- 01プロバイダーの SDK によるモデル呼び出し
- 02自動注入される認証情報の利用
- 03OpenAI、Anthropic、Gemini などに対応
- 04ライブエンドポイントでモデルの利用状況を確認
- 05Netlify CLI または Vite プラグインでローカル開発
活用シーン
- 01Function のリクエスト処理で AI コンテンツを生成
- 02Edge Function からモデルを呼び出す
- 03フォーム送信の分類や振り分け
- 04ゲートウェイ呼び出しのローカル開発とテスト
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ netlify/ context-and-tools --skill netlify-ai-gatewayインストール後、Claude Code で/netlify-ai-gatewayを入力して読み込まれたか確認します。
詳細
Netlify AI Gateway
プロバイダー公式の SDK を使用して、Netlify のコンピュートから AI モデルを呼び出せます。ゲートウェイがプロバイダーの認証情報を自動的に注入するため、引数なしで SDK をインスタンス化するだけで動作します。
注入された環境変数の認証情報を使って、プロバイダーの SDK を使用してください。 ゲートウェイ URL に対して生の fetch() を独自に実装したり、デフォルトの方法として NETLIFY_AI_GATEWAY_KEY / NETLIFY_AI_GATEWAY_URL を使った呼び出しを設定したりしないでください。これらはサードパーティ製またはサポート対象外のライブラリ専用です(下記参照)。
落とし穴(最初にお読みください)
- ブラウザーからは呼び出せません。 ゲートウェイの呼び出しは Functions または Edge Functions で行ってください。クライアント側のコードからは絶対に呼び出さないでください。ブラウザーには認証情報が注入されません。
- 認証情報はランタイムでのみ利用できます。 ビルドスクリプト、プリレンダリング/SSG、ビルドプラグインからゲートウェイを呼び出さないでください。これらには認証情報が渡されず、失敗します。AI 処理はリクエスト時に行ってください。出力を事前計算済みのように見せる必要がある場合は、Netlify Blobs にキャッシュしてください。
- 同期処理のタイムアウトは 60 秒です。 同期関数内のゲートウェイ呼び出しには、関数の 60 秒のタイムアウトが適用されます。長い生成処理ではストリーミング(SDK のストリーミング機能と
ReadableStream)を使うか、バックグラウンド関数で出力を保存し、クライアントが取得できるようにしてください。時間のかかる生成処理をストリーミングせずに実行しないでください。 - 本番環境へのデプロイが 1 回必要です。 プロジェクトが本番環境に少なくとも 1 回デプロイされるまで、ゲートウェイは有効になりません。ローカル開発の場合も、まず
netlify deploy --prodを 1 回実行してください。 - モデルのリストをハードコードしないでください。 利用可能なモデルは変更されます。静的なリストをコードに埋め込むのではなく、最新のプロバイダーエンドポイント(
https://api.netlify.com/api/v1/ai-gateway/providers/detailed)を確認してください。 - OpenRouter SDK には 1.2.43 以降が必要です。 それ以前のバージョンは
OPENROUTER_BASE_URLを無視し、openrouter.ai を直接呼び出して401 Missing Authentication headerエラーになります。
コードの配置場所
通常の Function/ハンドラーコードを記述してください。AI 専用のファイル形式はありません。netlify/functions/joke.js に config = { path: "/api/joke" } をエクスポートする関数を置くと、netlify dev と本番環境の両方で /api/joke として提供されます。
プロバイダー SDK(引数なしでインスタンス化)
ゲートウェイが各プロバイダー独自の環境変数を注入するため、公式 SDK は設定なしで動作します。
Anthropic Claude:
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic(); // uses ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Hello!' }]
});
OpenAI:
import OpenAI from 'openai';
const openai = new OpenAI(); // uses OPENAI_API_KEY, OPENAI_BASE_URL
const completion = await openai.chat.completions.create({
model: 'gpt-5',
messages: [{ role: 'user', content: 'Hello!' }]
});
Google Gemini:
import { GoogleGenAI } from '@google/genai';
const genAI = new GoogleGenAI({}); // uses GEMINI_API_KEY, GOOGLE_GEMINI_BASE_URL
const result = await genAI.models.generateContent({
model: 'gemini-2.5-pro',
contents: 'Hello!'
});
TypeSafe (Jev) — 構造化された判断(例:フォーム送信のルーティング/分類):
import type { Config, Context } from '@netlify/functions';
import { choice, TypeSafeClient } from '@typesafe-ai/sdk';
export default async (req: Request, context: Context) => {
const body = await req.json().catch(() => undefined);
if (body === undefined)
return Response.json({ error: 'Request body must be valid JSON.' }, { status: 400 });
const client = new TypeSafeClient(); // uses TYPESAFE_API_KEY, TYPESAFE_BASE_URL
const { answers } = await client.systemOne({
state: body,
questions: {
team: choice('Route this contact form submission', {
sales: null,
support: null,
spam: null,
}),
},
});
return Response.json({ team: answers.team.choice, requestId: context.requestId });
};
export const config: Config = { path: '/api/route', method: 'POST' };
systemOne のデフォルトは jev-latest モデルです。各質問は choice(prompt, options) を使い、名前付きの選択肢を null に対応付けます。結果は answers.<question>.choice にあります。Content-Type: application/json を指定して、JSON 本文(例:{"message":"Can someone help us upgrade to 200 seats?"})を POST してください。
OpenRouter(SDK 1.2.43 以降が必要です。落とし穴を参照):
import { OpenRouter } from '@openrouter/sdk';
const openRouter = new OpenRouter(); // uses OPENROUTER_API_KEY, OPENROUTER_BASE_URL
const result = await openRouter.chat.send({
chatRequest: {
model: 'x-ai/grok-4.5',
messages: [{ role: 'user', content: 'Hello!' }]
}
});
OpenRouter から利用できるモデルは、OpenRouter SDK または OpenAI SDK のいずれからも、OpenRouter のモデル ID 表記(例:deepseek/deepseek-v4-flash-0731)を使って呼び出せます。ID を model として渡すだけです。
上記のモデル ID(gpt-5、claude-sonnet-4-5-20250929、gemini-2.5-pro、x-ai/grok-4.5 など)は変更される可能性のある例です。最新のプロバイダーエンドポイントを確認してください。
環境変数 — 使用する変数
デフォルト: サポート対象のプロバイダー SDK は、注入されたプロバイダー固有の変数を自動的に使用します。上記のように引数を指定せずに SDK をインスタンス化すると(new OpenAI()、new Anthropic()、new GoogleGenAI({})、new TypeSafeClient()、new OpenRouter())、対応する変数のペアが読み込まれます。
- OpenAI:
OPENAI_API_KEY、OPENAI_BASE_URL - Anthropic:
ANTHROPIC_API_KEY、ANTHROPIC_BASE_URL - Google Gemini:
GEMINI_API_KEY、GOOGLE_GEMINI_BASE_URL - OpenRouter:
OPENROUTER_API_KEY、OPENROUTER_BASE_URL - TypeSafe:
TYPESAFE_API_KEY、TYPESAFE_BASE_URL
明示的に設定する場合: NETLIFY_AI_GATEWAY_KEY と NETLIFY_AI_GATEWAY_URL は常に注入され、ユーザーが設定したプロバイダー変数と競合することはありません。このペアは、サードパーティ製またはサポート対象外のライブラリでキーやベース URL の明示的な設定が必要な場合にのみ使用し、コンストラクターの引数として渡してください。これはデフォルトではありません。サポート対象の SDK では、上記のプロバイダー固有の変数を使用してください。
優先順位: Netlify は、プロジェクトまたはチームレベルで設定されたキーやベース URL を上書きしません。独自のプロバイダーキーを設定すると、ゲートウェイはそのキーを優先します。Gemini の場合、GOOGLE_API_KEY または GOOGLE_VERTEX_BASE_URL が設定されていると、変数の注入はスキップされます(Vertex/Google API キーの設定が優先されます)。
すべての変数の注入を停止するには、AI Features を無効にしてください:https://docs.netlify.com/build/build-with-ai/manage-ai-for-your-team/manage-ai-features/#disable-ai-features
完全な例(Vite + React + Function)
注入された変数を確認してゲートウェイが利用可能かどうかを判定し、その後 SDK を呼び出します。
最初にクライアントをインストールします:npm install openai。次に netlify/functions/joke.js を作成します:
import process from "process";
import OpenAI from "openai";
export default async () => {
if (!process.env.OPENAI_BASE_URL)
return Response.json({ error: "AI Gateway not active — deploy to prod once on a credit-based plan" });
try {
const client = new OpenAI();
const res = await client.responses.create({
model: "gpt-5-mini",
input: [{ role: "user", content: "Give me a short dad joke about coffee" }],
reasoning: { effort: "minimal" },
});
return Response.json({
joke: res.output_text?.trim() || "Out of jokes",
model: res.model,
tokens: { input: res.usage.input_tokens, output: res.usage.output_tokens },
});
} catch (e) {
return Response.json({ error: `${e}` }, { status: 500 });
}
};
export const config = { path: "/api/joke" };
src/App.jsx から /api/joke を取得します:
import { useState } from "react";
export default function App() {
const [joke, setJoke] = useState();
const [loading, setLoading] = useState(false);
const getJoke = async () => {
setLoading(true);
try {
const res = await fetch("/api/joke");
setJoke(res.ok ? await res.json() : { error: res.status });
} finally {
setLoading(false);
}
};
return (
<>
<button onClick={getJoke} disabled={loading}>
{loading ? "Thinking..." : "Get joke"}
</button>
<pre>{JSON.stringify(joke, null, 2)}</pre>
</>
);
}
ローカル開発
2 つの方法があります。どちらも、本番環境へのデプロイが少なくとも 1 回完了している必要があります。
- Netlify CLI:
netlify devを実行すると、ゲートウェイを完全に利用できます。 - Vite プラグイン:
netlify devを使わずに、ローカルでゲートウェイを利用できます。@netlify/vite-pluginを追加し、ネイティブの開発コマンド(npm run dev)を実行してください:
// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import netlify from "@netlify/vite-plugin";
export default defineConfig({ plugins: [react(), netlify()] })
セットアップの流れ:
npm install -g netlify-cli@latest
netlify login
npm create vite@latest dad-jokes -- --template react --no-interactive
cd dad-jokes && npm install
netlify init
netlify deploy --prod --open # required: activates the gateway
請求、上限、制約
- プラン: クレジット制プランのみ対象です(Free、Personal、Pro)。Enterprise の場合は、アカウントマネージャーにお問い合わせください。レガシープランは、先にプランを切り替える必要があります。AI Features を無効にした場合、または独自のプロバイダーキーを設定した場合を除き、デフォルトで有効です。
- 費用: トークン → USD(プロバイダーが公開する料金)→ クレジット。1 USD = 180 クレジットです。
- レート制限(1 分あたり、チーム単位、全プロジェクト合計):Free は 90、Personal は 450、Pro は 1,800、Enterprise は 9,000 クレジットです。
- コンテキストウィンドウ: 入力は 200k トークンまでです。
- プロンプトキャッシュ: Anthropic — デフォルトの 5 分間の一時キャッシュのみ。OpenAI — アカウントごとの
prompt_cache_keyが自動設定されます。Gemini — 明示的なコンテキストキャッシュには対応していません。 - ヘッダーのパススルーには非対応(ヘッダーで有効化する実験的機能は使えません)。バッチ推論には非対応。OpenAI の優先処理には非対応。
- OpenRouter は ZDR のみ: Netlify は、Zero Data Retention ポリシーを持つプロバイダーにのみルーティングします。OpenRouter のディレクトリに掲載されていても、ZDR を保証するホストがないモデルは提供されません。ZDR 対応モデルを確認する:https://openrouter.ai/models?zdr=true
- プライバシー: ゲートウェイはプロンプトやモデルの出力を保存しません。
費用の管理: AI を呼び出す Functions/Edge Functions にレート制限ルールを設定し、訪問者による不正利用や予想外の費用増加を防いでください:https://docs.netlify.com/manage/security/secure-access-to-sites/rate-limiting/ — さらに、自動チャージまたはクレジットパックを設定してください:https://docs.netlify.com/manage/accounts-and-billing/billing/billing-for-credit-based-plans/configure-auto-recharge/ · https://docs.netlify.com/manage/accounts-and-billing/billing/billing-for-credit-based-plans/buy-credit-packs/
参考資料
- 概要:https://docs.netlify.com/build/ai-gateway/overview.md
- クイックスタート:https://docs.netlify.com/build/ai-gateway/quickstart-for-ai-gateway.md
- 例:https://docs.netlify.com/build/ai-gateway/examples.md — AI SEO Image Generator(Gemini による画像生成):https://github.com/netlify/examples/tree/main/examples/ai-seo-image-generator、および TanStack Start のチャットアプリ:https://github.com/netlify-templates/tanstack-template
Netlify のルール(ai-gateway)
これらは組織内の規約であり、ドキュメント上の事実ではありません。ctx-gen によってレンダリングされるスキルに統合され、生成されることはありません。スキルのメンテナーが管理します。
- 注入された環境変数の認証情報を使ってプロバイダーの SDK を使用してください。ゲートウェイに対して生の
fetch()を自分で実装しないでください。生の REST もサポートされていますが、本文では生の REST やNETLIFY_AI_GATEWAY_KEY/NETLIFY_AI_GATEWAY_URLの組み合わせを推奨する方法として提示してはいけません。ただし、事実としてこの組み合わせは必ず注入されること、ユーザーが設定したプロバイダー変数と競合しないこと、サードパーティ製またはサポート対象外のライブラリで明示的な設定が必要な場合に適切な選択肢であることは、必ず記載してください。推奨度は下げつつ、知識としては残してください。 - ゲートウェイはブラウザーから呼び出せません。呼び出しは関数またはエッジ関数で行い、クライアント側のコードでは行わないでください。
- モデルの利用状況は変化します。モデル一覧をハードコードせず、プロバイダーのライブエンドポイントを確認してください。
- ゲートウェイの認証情報は実行時のみ利用できます。ビルドスクリプト、プリレンダリング/SSG、ビルドプラグインからゲートウェイを呼び出さないでください。認証情報が渡されず、呼び出しは失敗します。AI 処理はリクエスト時に行い、事前に計算された状態にしておく必要がある場合は、結果をキャッシュ(例:Netlify Blobs)してください。
- 同期関数でのゲートウェイ呼び出しには、60 秒のタイムアウトが適用されます。長時間の生成ではストリーミング(SDK のストリーミング+
ReadableStream)を使うか、出力を保存してクライアントが取得できるようにするバックグラウンド関数を使用してください。時間のかかる生成をストリーミングせず、完了すると思い込んで放置してはいけません。 - どの環境変数を使うべきか尋ねられた場合は、ゲートウェイの組み合わせについて明示的に尋ねられた場合でも、文字どおりの質問に答える前にデフォルトの方法から説明してください。サポート対象のプロバイダー SDK では、本文に示されているプロバイダーごとのインスタンス化方法をそのまま使って、注入されたプロバイダー固有の変数(
OPENAI_API_KEY/OPENAI_BASE_URLなど)を使用します。ここでは本文の設定を言い換え、コンストラクターの詳細を独自に作り上げないでください。その後、サードパーティ製またはサポート対象外のライブラリで明示的な設定が必要な場合の選択肢として、NETLIFY_AI_GATEWAY_KEY/NETLIFY_AI_GATEWAY_URLを提示してください。ゲートウェイの組み合わせだけを回答すると、手動設定がデフォルトであるかのように伝わりますが、実際にはそうではありません。