AI Assistant API
AIアシスタントのチャットエンドポイントのAPI仕様です。
エンドポイント
POST / api/ ai- chat
Content- Type: application/ jsonリクエストボディ
interface AiChatRequest {
message: string;
history?: ChatMessage[];
}
interface ChatMessage {
role: "user" | "assistant";
content: string;
}| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
message | string | はい | ユーザーの現在のメッセージ。空でないこと。 |
history | ChatMessage[] | いいえ | 過去の会話メッセージ。不正な形式(非配列、50件超、コンテンツが8192文字超、またはインジェクション一致)の場合はHTTP 400で拒否。 |
成功レスポンス (200)
interface AiChatResponse {
response: string;
}responseフィールドはアシスタントの返答をマークダウン文字列として含みます。
例:
// Request
{
"message": "How do I add a new page?",
"history": []
}
// Response
{
"response": "Create an MDX file in `src/content/docs/`:\n\n1. Add frontmatter with `title`\n2. Write your content in MDX\n3. The page appears in the sidebar automatically"
}エラーレスポンス (400 / 500)
interface AiChatErrorResponse {
error: string;
}| ステータス | 条件 |
|---|---|
| 400 | 無効なJSONボディ |
| 400 | messageが空でない文字列ではない |
| 400 | messageが4000文字の制限を超えている |
| 400 | 入力スクリーニング(プロンプトインジェクションガード)で拒否された |
| 400 | historyの形式が不正(フィールド説明を参照) |
| 405 | リクエストメソッドがPOSTでもOPTIONSでもない |
| 415 | Content-Typeがapplication/jsonではない |
| 429 | レート制限超過(Retry-Afterヘッダーを含む) |
| 500 | Anthropic APIコール失敗 |
このエンドポイントはPOST(チャット)とOPTIONS(CORSプリフライト)のみを受け付けます。それ以外のメソッドはすべて{ "error": "Method not allowed" }とともに405を返します。
CORS
このエンドポイントはオリジンごとの許可リストを使用します。aiChatDemoModeがfalseの場合、Access-Control-Allow-OriginはaiChatAllowedOrigins設定にリストされたリクエストオリジンに対してのみエコーされます。それ以外のオリジンにはallow-originヘッダーが返されず、ブラウザによってブロックされます。(デモモードでは後方互換性のため常に*が返されます。)これはワイルドカードCORS(*)を使用するSearch Workerよりも意図的に厳格です。各コールに実際のAnthropic APIコストが伴うAIチャットエンドポイントはオリジンでゲートしますが、検索はメーター課金のないオプトインサービスだからです。2つのエンドポイントが同じCORSポリシーを共有していると仮定しないでください。
CF環境バインディング
| バインディング | 種別 | 必須 | 説明 |
|---|---|---|---|
ANTHROPIC_API_KEY | secret | はい | Anthropic APIキー |
DOCS_SITE_URL | var | はい | デプロイ済みのドキュメントサイトURL(llms-full.txtの取得に使用) |
RATE_LIMIT | KV namespace | はい | レート制限のカウンタと監査ログを保存 |
RATE_LIMIT_PER_MINUTE | var | いいえ | IPあたりの1分間の最大リクエスト数(デフォルト10) |
RATE_LIMIT_PER_DAY | var | いいえ | IPあたりの1日の最大リクエスト数(デフォルト100) |
PUBLIC_ENABLE_MOCKS | var | いいえ | "true"に設定するとMSWのモックレスポンスが有効になる(開発モードのみ) |
設定
以下のsrc/フィールドがエンドポイントの動作を制御します(上記のCF環境変数とは
別のもので、こちらはCloudflare側のランタイム設定です)。
| 設定 | 型 | デフォルト | 説明 |
|---|---|---|---|
aiChatDemoMode | boolean | true | エンドポイントを固定返答でショートサーキット。APIキーやKVにアクセスしない |
aiChatAllowedOrigins | string[] | [] | CORSオリジン許可リスト(非デモ時のみ有効)。空配列 = 全クロスオリジンリクエストをブロック |
aiChatGlobalDailyLimit | number | false | false | 全IPを合算した1日のリクエスト上限。false = 上限なし |
セキュリティ
このエンドポイントは、レガシーのスタンドアロンWorkerから移植された多層的な防御を備えています:
ハードニングされたシステムプロンプト — XMLタグでコンテキストを区切り、明示的なガードレールによってモデルが設定情報を漏洩したり、トピック外の指示に従ったりすることを防ぎます。さらに、過去の会話ターンはすべてクライアント由来の信頼できない入力として扱うようモデルに指示します(下記の チャット履歴の信頼モデル を参照)
入力スクリーニング — 一般的なプロンプトインジェクションパターンを正規表現の事前フィルタで弾き、Claude APIに到達する前に拒否します。スクリーニングはレート制限チェックの後に実行されるため、インジェクションガードで拒否されたリクエストでも呼び出し元のレート制限の枠は消費します(リミッターはKV書き込みの増幅を防ぐため先に実行する必要があります)
レート制限 —
RATE_LIMITKVを使ったIPごとの制限。aiChatDemoModeがfalseの場合は フェイルクローズ(KV障害時 → HTTP 429)。デモモードではフェイルオープン(デモのショートサーキットが先に実行されるため、実際にはレートリミッターには到達しない)CORSオリジン許可リスト — 非デモ時、
Access-Control-Allow-OriginはaiChatAllowedOriginsに含まれるオリジンにのみエコーされます。リスト外のオリジンからのクロスオリジンリクエストはブラウザでブロックされます。デモモードは後方互換性のため常に*を送信しますグローバル1日上限 — IPローテーションやボットネットへの対策として
aiChatGlobalDailyLimitでオプションのバックストップを設定できます。デフォルトは無効監査ログ — すべてのインタラクションを
audit:プレフィックスでRATE_LIMITKVに記録(7日のTTL、ファイア・アンド・フォーゲット)メッセージ長制限 — 4000文字を超えるメッセージはAPIに到達する前に拒否されます
cf-connecting-ipの注意点 — IPごとのレート制限にはこのヘッダーを使用しており、WorkerがCloudflareのネットワーク経由でデプロイされている場合にのみ信頼できます
チャット履歴の信頼モデル
history配列はクライアント由来かつステートレスです。サーバーはセッション記録を一切保持しないため、assistantロールのターンが実際に過去のモデル応答によって生成されたものかを検証できません。各エントリは依然としてハードニングされています。すなわち、user/assistantへの厳格なロールホワイトリスト、上記のエントリ件数および1エントリあたりの長さ制限、そして紛れ込んだ余分なフィールドを取り除く{ role, content }への再構築です。userロールのターンはインジェクションスクリーニングされますが、assistantロールのターンはされません(本物のアシスタント応答はインジェクションのような文面を正当に引用しうるためです)。
ロールが検証不可能であるため、呼び出し元は敵対的な指示を含むassistantターンを偽造してユーザーターンのスクリーニングを回避できます。この残存リスクは意図的に受容しています。本チャットはブラスト半径の小さいドキュメントアシスタントであり、システムプロンプトはすべての過去ターンを、自身のルールを上書きできない信頼できない入力として扱うようモデルに指示しているためです。堅牢な対策(サーバー発行の署名付き履歴)はシークレットのプロビジョニングとクライアント/サーバー間ペイロード契約の変更を必要とし、この機能には見合いません。決定の全記録はissue #2036を参照してください。
ドキュメントコンテキスト
このエンドポイントは、llms.txtインテグレーションで生成されたllms-full.txtをDOCS_SITE_URLから取得し、CF Workersのアイソレートが生きている間メモリにキャッシュします(ベストエフォート、約1時間)。取得したコンテンツはシステムプロンプトに<documentation>XMLコンテキストとして含められます。