2026.08.12
Cloudflare OSで社内AIエージェント基盤を立ち上げるまで|導入でつまずいたポイントまとめ
Cloudflareが公開しているオープンソースのAIエージェント基盤「Cloudflare OS」を使って、社内向けAIエージェント「LEAPHのAI Agent」を実際に構築しました。本記事は、その過程で遭遇したつまずきポイントと解決策をまとめた導入記録です。公式ドキュメントだけでは分かりにくい箇所がいくつかあり、同じように自社導入を検討している方の参考になればと思い公開します。

対象読者: Cloudflareアカウントの初期設定から、GitHub・Google Workspace・Slack・Supabaseとの連携までを一通り行いたい方
注意: 2026年8月時点で、Cloudflare OSの管理画面・チャットUIは英語UI固定で、日本語UIには対応していません。
Cloudflare OSとは
Cloudflare OSは、Cloudflare Workers上で動く「AIがアプリを作って動かせるOS」のようなプロダクトです。特徴的なのは以下の設計です。
- Gadget: AIとのチャットで生成される、個々のミニアプリ。ユーザーごとにプライベート保つ
- Gatekeeper: GitHub・Google・Slack・Supabaseなど外部サービスへのアクセスを仲介する、権限を絞ったセキュリティレイヤー。人間の承認を挟む「human-in-the-loop」の仕組みが標準搭載
- Context: 組織横断でデータを検索・共有できるRAGの土台
より詳しい仕組みはCloudflare OSとは|全社員がAIエージェントを使える業務基盤の仕組みで解説しています。本体リポジトリは cloudflare/cloudflare-os、デプロイ用の設定・スクリプトをまとめた cloudflare/cloudflare-os-starter という2つのリポジトリで構成されています。
全体構成
最終的にできあがった構成はこうなりました。
├── cloudflare-os/ 本体(自社フォーク)
└── cloudflare-os-starter/ デプロイ設定(自社フォーク、Private)
└── cloudflare-os/ ↑ starterのgit submodule(自分のフォークを参照)
本番で動いているWorkerは以下の7つです。
| Worker | 役割 |
|---|---|
| cloudflare-os-workshop | 本体(フロントエンド+バックエンド) |
| cloudflare-os-context | RAG/Context基盤 |
| cloudflare-os-custom-gatekeeper | 動作確認用のサンプルGatekeeper |
| cloudflare-os-error-reporter | エラーレポート専用Worker |
| cloudflare-os-gatekeeper-github | GitHub連携 |
| cloudflare-os-gatekeeper-google | Google Workspace連携(Gmail/Drive/Docs/Sheets/Calendar) |
| cloudflare-os-gatekeeper-slack | Slack連携 |
| cloudflare-os-gatekeeper-supabase | Supabase(顧客DB)連携 |
デプロイは「pushすれば自動デプロイ」の形にしていて、scripts/deploy.mjs が deployment.jsonc の内容から各Workerのwrangler設定を動的生成し、順番にデプロイします。
Cloudflareアカウントの準備
Workers Paidプランへのアップグレード
Cloudflare OSの中核機能である「Gadgetの動的コード実行」は、Workers Paidプラン限定の機能である Dynamic Worker Loaders に依存しています。 無料プランのままでは本質的に動かないので、最初にアップグレードが必要です。(2026年8月時点では$5)
R2(Cloudflareのストレージサービス)の有効化
ダッシュボードでR2を有効化する際、支払い情報の登録画面(/checkout/payment)が開かないことがありました。Safariで開いたら解決したので、Chromeなどで開かない場合はブラウザを変えて試してみてください(広告ブロッカーがStripeの決済iframeをブロックしているケースが多いようです)。
Cloudflare Access(Zero Trust)の設定
Workshopへのログインには Cloudflare Access を使います。
- Zero Trustダッシュボードでチームドメインを作成
- Access → Applications → Add an application → Self-hosted
- 保護対象のホスト名(<workshop worker名>.<workers.devサブドメイン>.workers.dev)を「パブリックDNS」として登録
- Access Policyの Include に社員のメールアドレスを列挙(管理者権限とは別物。管理者は後述の deployment.jsonc の admins で制御)
デプロイ設定(cloudflare-os-starter)
deployment.jsonc の作成
cloudflare-os-starter をクローンし、deployment.jsonc にアカウントID・Worker名・Access issuer/audience・管理者メールなどを埋めます。
git submodule update --init
pnpm install
pnpm --dir cloudflare-os install
pnpm exec wrangler login
pnpm check → pnpm deploy
pnpm check でdry-run検証してから pnpm deploy を実行します。初回は以下のエラーに順番に当たりましたが、いずれも「前回作成済みのリソースをもう一度作ろうとして衝突する」ものだったので、deployment.jsonc の該当項目(KV Namespace ID・R2バケット名)に既存の値を明示すれば解決します。
- a namespace with this account ID and title already exists
- The bucket you tried to create already exists, and you own it
GitHubからの自動デプロイ
最初にハマった罠: Cloudflare Workers Builds
Cloudflareダッシュボードから「Gitリポジトリと連携してデプロイ」を設定する Workers Builds という機能がありますが、これは「1プロジェクト=1Worker」を前提にした仕組みです。 deploy.mjs は1回の実行で複数のWorkerをまとめてデプロイするため、Workers Buildsは全Workerの名前を強制的に1つに上書きしようとし、本番Workerを壊しかけました。
Failed to match Worker name. Your config file is using the Worker name "cloudflare-os-error-reporter", but the CI system expected "cloudflare-os-workshop". Overriding using the CI provided Worker name.
複数Workerをまとめてデプロイするこの構成では、GitHub Actionsを使うのが正解でした。
GitHub Actionsの設定
# .github/workflows/deploy.yml
on:
push:
branches: [main]
jobs:
deploy:
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ secrets.SUBMODULE_PAT }} # 後述
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: 24, cache: pnpm }
- run: pnpm install --frozen-lockfile
- run: pnpm --dir cloudflare-os install --frozen-lockfile
- run: pnpm deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN は「Edit Cloudflare Workers」テンプレートで発行したAPIトークンをGitHub Secretsに登録するだけです。
独自パッチを当てるならフォークが必要
cloudflare-os-starter の cloudflare-os サブモジュールは、デフォルトでCloudflare公式リポジトリを参照しています。本体側にバグ修正などの独自パッチを当てたい場合は、サブモジュールの参照先を自分のフォークに切り替える必要があります(.gitmodules のURLを変更)。
この時、フォークをPrivateにしていると、GitHub Actionsのデフォルト GITHUB_TOKEN では別リポジトリ(サブモジュール)をcloneできず失敗します。
remote: Repository not found.
fatal: repository '...' not found
Fine-grained PAT(両方のリポジトリへのContents:Read権限)を発行し、Secretとして登録、actions/checkout の token に渡すことで解決しました。
※フォークとは、他人(または他組織)が管理しているGitHubリポジトリを、自分のアカウント配下に複製(コピー)して、独立した別リポジトリとして持つことです。
さらに、サブモジュールのコミットを切り替えると、ルートの pnpm-lock.yaml(pnpm-workspace.yaml がサブモジュール内のパッケージも直接ワークスペースに含めている場合)が古くなり ERR_PNPM_OUTDATED_LOCKFILE になることがあるので、pnpm install でロックファイルを更新してコミットし直します。
外部サービス連携(Gatekeeper)
Cloudflare OSの各種連携(GitHub・Google・Slack・Supabaseなど)は、それぞれが独立したWorkerとして動く「Gatekeeper」という仕組みです。 cloudflare-os 本体にはこれらの実装が最初から入っていますが、cloudflare-os-starter の deploy.mjs は初期状態では配線されていません。追加するには以下の3点セットが必要です。
- deployment.jsonc にWorker名を追加
- deploy.mjs にビルド・デプロイステップとWorkshopへのサービスバインディング(GATEKEEPER_XXX)を追加
- 各サービス側でOAuth Appを作成し、Client ID/SecretをWranglerのシークレットとして登録
この型に沿って、GitHub・Google Workspace・Slack・Supabaseの4つのGatekeeperを追加しました。OAuthのコールバックURLは、いずれも https://<Gatekeeper Worker名>.<workers.devサブドメイン>.workers.dev/gatekeeper/<サービス名>/oauth という形式です。
ポイント: OAuthアプリのスコープはコードから逆算する
各サービスのOAuthアプリ作成時に「どのスコープ(権限)を付与するか」を聞かれますが、READMEやコード(src/*.ts の実際のAPI呼び出し箇所)を確認すれば、必要最小限のスコープが分かります。 例えばSupabaseの場合、コードが呼んでいるManagement APIエンドポイント(/v1/organizations、/v1/projects、/v1/projects/:ref/database/query など)から、Organizations: Read Projects: Read Database: Read and Write が必要と判断できました。権限を必要最小限に絞れるのは、まさにGatekeeperの設計思想そのものです。
AIモデルの有効化
デプロイしただけでは、Workshopのチャットは応答しません。deployment.jsonc の aiGateway.enabled が false のままだと、モデルが1つも設定されていない状態になるためです。
- AnthropicのAPI Keyを取得
- Cloudflareダッシュボードで AI Gateway を新規作成し、Provider Keys(Unified Billing)にAnthropicキーを登録。支出上限(例: $100/月)も設定しておくと安心
- AI Gateway – Edit 権限を持つCloudflare API Tokenを発行し、CF_AI_GATEWAY_API_TOKEN としてWorkshop Workerにシークレット登録
- deployment.jsonc の aiGateway を有効化
"aiGateway": {
"enabled": true,
"name": "<AI Gateway名>",
"accountId": "<account id>",
"providers": ["anthropic"],
"workersAi": { "mode": "direct" }
}
実運用中に出た不具合とその原因
「Couldn’t load connection options / Couldn’t load AI model」
デプロイ直後の一時的なもので、ブラウザのリロードで解消しました。サーバーログを見ても該当リクエストは全て成功しており、キャッシュ・タイミングの問題だったようです。
チャット入力中、変換確定のEnterで誤送信される
コード上、Enterキー送信の判定に event.nativeEvent.isComposing のチェックが漏れていたのが原因でした(IME変換中のEnterも「送信」として拾ってしまう、よくあるバグパターン)。フォーク側に1行修正を加えてデプロイし直しました。
// 修正前
if (e.key === “Enter” && !e.shiftKey) { … }
// 修正後
if (e.key === “Enter” && !e.shiftKey && !e.nativeEvent.isComposing) { … }
「Durable Object reset because its code was updated.」
これはバグではなく仕様です。Workerを再デプロイすると、稼働中のDurable Objectインスタンスがリセットされるため、デプロイ前から開いていたブラウザタブのセッションが切れます。 タブを完全に閉じて開き直す(複数回デプロイをまたいだ場合はキャッシュの完全クリアが必要なことも)で解消します。
まとめ: つまずきやすいポイント
| 症状 | 原因 | 対処 |
|---|---|---|
| Workers Buildsのデプロイで別Workerが壊れかける | 1プロジェクト=1Worker前提と、複数Worker一括デプロイ構成の不一致 | GitHub Actionsに切り替える |
| submoduleのclone失敗(Repository not found) | フォークがPrivateで、既定のGITHUB_TOKENが越境アクセスできない | Fine-grained PATを発行してSecrets登録 |
| ERR_PNPM_OUTDATED_LOCKFILE | submoduleのコミット変更でルートlockfileが追従できていない | ルートでpnpm installしてlockfileをコミット |
| KV/R2の重複作成エラー | 前回失敗デプロイで既にリソースが作成済み | 実際のIDをdeployment.jsoncに明記 |
| チャットが応答しない | AIモデルが1つも設定されていない | AI Gatewayを有効化する |
| 「Durable Object reset」エラー | 直近のデプロイでセッションが切れた | ブラウザタブを開き直す |
| UIが英語のみで分かりにくい | 日本語UIが未対応(2026年8月時点) | 全社展開前に、英語UIに不慣れな社員向けの簡易マニュアルを用意する |
Cloudflare OS自体はよく設計されたプロダクトですが、「複数Workerを1つの単位としてデプロイする」という前提が、Cloudflareの標準的なGit連携機能(Workers Builds)の設計思想とズレているため、この一点だけは事前に知っておくと余計な回り道をせずに済むと思います。
関連記事
- Cloudflare OSとは|全社員がAIエージェントを使える業務基盤の仕組み
- Cloudflare OSの「Gatekeeper」とは|権限管理の仕組みを解説
- Cloudflare OSのアプリ構築基盤とは|Dynamic WorkerとSQLiteの仕組み
自社でのデプロイ・運用を丸ごと任せたい方へ
Cloudflare OSは強力な基盤ですが、Workers Paidプランの契約からOAuth連携、CI/CDの構築まで、非エンジニアの方だけで進めるにはハードルがあります。LEAPHでは、この記事で紹介したデプロイ代行から、GitHub・Google Workspace・Slack・Supabaseなどの各種連携設定、AIガバナンス設計までを伴走支援しています。まずはお問い合わせからご相談ください。