← レポート一覧
INTERNAL APP PLATFORM ON AZURE / 構成案

社内 AI アプリ基盤の構成案

Cloudflare OS の考え方を Azure で作るとどうなるか。
手元の AI エージェントで作り、社内基盤にデプロイし、鍵は配らず、アプリごとに権限を持たせる。
作る側の AI 費用は Claude / Codex のサブスクで済ませる。

1 / ゴール

5つの要件と、先に置いた4つの判断

要件は5つです。Azure で動く。非エンジニアも AI でアプリを作れる。色々なサービスの情報をアプリから使える。各自の手元のエージェントで作って社内基盤にデプロイする。鍵は配らず、アプリ内で社員の権限を設定できる。

この解説では、次の4点を前提として置いています。判断 1 と 3 はまだ確認していない仮置き、判断 2 と 4 は依頼者の方針です。変えると構成も変わります。

判断 1 / アプリの形

1アプリを複数人がロール付きで使う

Cloudflare OS の「1人1インスタンス(Gadget)」ではなく、従来型の共有アプリにする。「アプリ内で社員の権限設定」という要件はこちらの形で自然に満たせるし、実装もずっと簡単。

判断 2 / 作る場所

エンジニアは Claude Code、非エンジニアは claude.ai

基盤の中にエージェントは置かない。エンジニアは手元の Claude Code、非エンジニアは claude.ai(デスクトップ含む)から、同じ経路でデプロイする。claude.ai にはデプロイ用の MCP コネクタと Skill を配る。

判断 3 / 観測追跡

v1 では作らない

Cloudflare OS の「見たデータの由来が成果物に付いて回る」仕組みは Azure に既製品がない。本人権限でデータを取る設計(後述の OBO)で、漏れる経路を構造的に減らすことで代替する。

判断 4 / AI コスト

作る側はサブスク、動かす側だけ API

アプリを作る AI は Claude / Codex のサブスクで済ませる。アプリが実行時に LLM を呼ぶ分だけ API 課金にし、要るアプリだけ承認制で上限付きにする。大半の社内ツールはここがゼロ。

2 / 違い

作る場所が「基盤の中」から「手元」に移る

Cloudflare OS ではエージェントが基盤の中にいて、その場でアプリを生成し、その場で改造します。今回の世界観では、エージェントは各自の手元(Claude Code か claude.ai)にいて、成果物だけを基盤へ送ります。基盤の中にエージェントは置きません。この違いが、基盤に必要なものを変えます。

CLOUDFLARE OS 基盤(ブラウザで使う) エージェント 基盤の中にいる アプリ その場で生成 「ボタンを足して」で、その場で改造 デプロイ工程が存在しない 基盤に必要なもの: エージェント実行環境 今回の構成 Claude Code エンジニアの手元 AGENTS.md を読んで作る サブスク claude.ai 非エンジニアのデスクトップ Skill を読んで作る サブスク 社内基盤(Azure) デプロイ経路 MCP / CLI アプリ 隔離して実行 コネクタ層 基盤に必要なもの: 契約 + デプロイ経路 + 実行環境 エージェント実行環境は持たない(作る側の AI はサブスク)
左は Cloudflare OS、右が今回。右では「契約」と「デプロイ経路」が新たに必要になり、代わりにエージェント実行環境を持たない。入口は2つ、経路は1つ。
基盤が持つべきものは実行環境より先に、どのエージェントが作っても同じ形になる「契約」と、それを検査して載せる「経路」です。
3 / 全体構成

社員のブラウザから外部サービスまで

Cloudflare OS の全体図と同じ並びで描きます。アプリは外部サービスにも鍵にも直接触れず、必ずコネクタ層(API Management)を通る。この一点は同じです。

社員のブラウザ アプリ一覧(ポータル)から開く Microsoft Entra ID SSO・グループ・App Roles Easy Auth アプリごとに自動で認証を挟む アプリ群: Container Apps(コンテナ形式) と Static Web Apps(単一 HTML 形式) アプリごとの ID、scale-to-zero、外向き通信はコネクタ層と AI ゲートウェイだけに制限 本人の ID 付き 提案書管理 営業が作った ロール: 編集者 / 閲覧者 チケット朝会ボード IT が作った ロール: 担当 / 管理者 在庫の確認(単一 HTML) 総務が claude.ai で作った サーバーコードなし・静的配信 コネクタ層: Azure API Management Credential Manager が外部サービスの OAuth トークンを保持 ポリシーで、許可するリソース・レート・返すフィールドを絞る 全呼び出しに本人の ID を付けて記録 同じ API を MCP サーバーとしても公開(エージェント用) 秘密の実体は Key Vault、アプリからは見えない SDK: connectors.github.listIssues() AI ゲートウェイ: APIM 実行時に LLM を使うアプリだけ通る アプリごとの月額上限・コスト計測 Content Safety・ログ 背後: AI Foundry(Claude / OpenAI、従量課金) 外部 SaaS GitHub / Slack / Salesforce Notion / Google など 基盤の共有アカウントで Entra 対応の社内システム Microsoft 365 / Graph Dataverse / 自社 API 本人のトークンで(OBO) Cosmos DB アプリごとに コンテナを分離 アプリの ID だけが読める Log Analytics 誰が・どのアプリで・ 何を呼んだか 監査の一次ソース
上から: 入場 → アプリ群 → 関所2つ(コネクタ層と AI ゲートウェイ) → 外部。緑の矢印が外へ出る唯一の経路。
実行

Container Apps を選ぶ理由

Cloudflare の V8 isolate ほど軽くはないが、コンテナ単位の隔離と scale-to-zero で「アプリ100個」は現実的なコストに収まる。任意言語で書けるので手元のエージェントの得意な言語を使える。

関所

APIM をコネクタ層にも AI ゲートウェイにも使う

Cloudflare OS では Gatekeeper と AI Gateway は別物だが、Azure では同じ API Management が両方の役を担える。運用対象を1つに絞れる。

入口

基盤の中にエージェントは置かない

Claude Code も claude.ai も、基盤が公開するデプロイ用 MCP サーバー(または CLI)を叩くだけ。Cloudflare OS の「隔離環境でエージェントがコードを書く」部分は、各自のサブスクに任せる。

4 / 対応表

Cloudflare OS の部品を、Azure のどれで作るか

Cloudflare OSAzure での対応備考
Cloudflare Access(入場)Entra ID + Easy Authアプリ側の実装なしで SSO が付く。入れる人はグループで制御
Gatekeeper(鍵を握る連携層)API Management の Credential Manager + Key VaultOAuth トークンの保持と付与、スコープ絞り込み、レート制限、フィールドマスク、ログ。承認フローだけは自作
MCP Server PortalsAPIM の MCP サーバー公開同じ API をアプリ用 REST とエージェント用 MCP の両方で出せる
Gadget(隔離実行)Container Apps(コンテナ形式) / Static Web Apps(単一 HTML 形式)エンジニア向けはコンテナ、非エンジニア向けはサーバーコードなしの単一 HTML。第 6 章
Workshop 内のエージェント置かないClaude Code と claude.ai のサブスクに任せる。基盤側はデプロイ用 MCP サーバーと Skill を配るだけ
1インスタンス 1 SQLiteCosmos DB のアプリ別コンテナアプリのマネージド ID にだけ RBAC を付与。Azure SQL のスキーマ分離でも可
AI GatewayAPIM の AI ゲートウェイ + AI Foundryllm-token-limit、トークン計測、Content Safety、モデル振り分け
Shared Permissions(アプリ内権限)Entra App Roles + グループ割当アプリごとにロールを定義し、SDK から user.roles で読む
Skills / Contextテンプレート + AGENTS.md + claude.ai Skill同じ内容を Claude Code には AGENTS.md、claude.ai には組織配布の Skill として渡す
観測追跡(既製品なし)OBO と読み取り専用コネクタで代替。第 12 章
5 / ライフサイクル

手元で作ってから、社員が使えるようになるまで

今回の構成で新しく必要になる「経路」です。どこで作ったかに関係なく、必ずこの経路を通ります

Claude Code(エンジニア) AGENTS.md を読んで生成 CLI か MCP で送る claude.ai(非エンジニア) Skill を読んで生成 MCP コネクタで送る リポジトリ GitHub / Azure DevOps コード + manifest push CI(検査) 依存関係スキャン 秘密の混入チェック manifest の妥当性 コンテナをビルド 承認 要求された コネクタと権限を 管理者が確認 初回と変更時だけ Container Apps に配置 承認済みのコネクタだけがバインディングとして渡る Entra にアプリ登録と App Roles を自動作成 ポータルに並ぶ 社員が一覧から開く 所有者・ロールを表示 「ボタンを足して」は手元で直して再 push(数分で反映) デプロイ用 MCP サーバー / CLI push から配置までを1つの操作に。両入口が同じものを呼ぶ
入口は2つ、経路は1つ。承認は「どのサービスに何の権限で触るか」に対してだけ行い、コードの変更ごとには行わない。
1
作る: テンプレートから始める
Claude Code でも claude.ai でも、同じテンプレートから始める。認証・SDK・ロール判定は最初から入っている。非エンジニア向けは単一 HTML 形式のテンプレート(次章)。
2
宣言する: manifest に「何が要るか」を書く
使うコネクタとスコープ、アプリ内ロール、入れる人のグループ。エージェントはこのファイルも書く
3
検査する: CI が機械的に止める
生成コードに秘密や危険な依存が混ざっていないか、manifest が基盤の許可範囲内か。落ちたらエージェントに差し戻す。
4
承認する: 権限の要求だけを人が見る
「Salesforce の商談を読み取りで使いたい」のような要求を管理者が承認。初回と変更時だけで、コード修正のたびには要らない。
5
配置する: 承認済みの分だけ接続される
Container Apps にデプロイ。Entra のアプリ登録とロールが自動で作られ、ポータルに載る。
6 / アプリの形式

アプリの形式は2つ。非エンジニア向けはサーバーコードなし

claude.ai は単一の HTML を生成するのが得意で、サーバーを含むリポジトリ一式を組み立てるのは苦手です。そこで非エンジニア向けのアプリ形式を「単一 HTML + manifest」に限定し、データの読み書きはブラウザ用 SDK が本人のトークンで基盤の API を呼ぶ形にします。

形式 A: 単一 HTML(非エンジニア向け) index.html UI + ブラウザ用 SDK claude.ai が生成 Static Web Apps に配置 manifest 入れる人・ロール 使うコネクタ 保存領域の有無 サーバーコードは無い ブラウザから、本人の Entra トークン付きで 基盤の API を直接呼ぶ(Easy Auth が入口) 形式 B: コンテナ(エンジニア向け) client + server 言語は任意 Claude Code が生成 Container Apps に配置 manifest 形式 A と同じ + 定期実行・Webhook 実行時 LLM の予算 サーバーが本人の代理で呼ぶ バッチ、Webhook 受信、複雑な集計、 実行時に LLM を使う処理はこちら 共通: コネクタ層(API Management)・アプリ専用ストレージ・権限の3層・ポータル どちらの形式も、鍵を持たず、本人の ID で同じ関所を通る
上が2つの形式、下が共通部分。形式 A はサーバーを持たない分、CI 検査も配置も軽く、claude.ai の出力をそのまま載せられる。
形式 A でできること

社内ツールの大半

一覧・検索・入力フォーム・ダッシュボード・承認ボタン。コネクタからの読み取りと、アプリ専用ストレージへの保存。Cloudflare OS の Gadget から server code を抜いた形に近い。

形式 B が要るとき

裏で動く処理があるとき

定期実行、Webhook 受信、大量データの集計、実行時に LLM を呼ぶ処理。非エンジニアが形式 A で作ったものを、あとからエンジニアが形式 B に昇格させる流れもある。

ブラウザ用 SDK の中身

本人トークンで関所を叩く薄い層

platform.connectors.*platform.store.*。Easy Auth が発行した本人のトークンを付けて API Management を呼ぶだけ。OBO への交換は関所側で行うので、ブラウザに他サービスのトークンは来ない。

7 / 契約

手元のエージェントに読ませる4点セット

Cloudflare OS の Skills にあたるものです。Claude Code でも claude.ai でも同じ形のアプリが出てくるように、基盤側が用意します。

1 / テンプレート

雛形リポジトリ

フレームワーク、認証ヘッダーの読み方、コネクタ SDK、ロール判定、ローカル実行用のモック。エージェントは空から書かず、ここを埋める

const user = platform.currentUser(req);
if (!user.hasRole("editor")) return forbid();
const deals = await platform.connectors
  .salesforce.listOpportunities({ owner: user.id });
2 / MANIFEST

要るものの宣言

コネクタとスコープ、ロール、入れる人。承認と配置はこのファイルだけを見る

name: proposal-manager
owner: sales-team@example.com
access: group:sales-all
roles: [editor, viewer]
connectors:
  salesforce: [opportunities:read]
  sharepoint: [files:read, files:write]
  graph: on-behalf-of
3 / AGENTS.md と Skill

エージェント向けの書き方

基盤の制約、やってはいけないこと(鍵をコードに書く、外部に直接 fetch する)、デプロイの手順。Claude Code には AGENTS.md、claude.ai には組織配布の Skill として、同じ内容を渡す。Team / Enterprise の管理画面から全員に配れる。

4 / MCP サーバー

デプロイ用のリモート MCP

ツールは create_app / deploy / list_my_apps 程度。claude.ai のカスタムコネクタとして Owner が組織に追加し、各自が Entra でログインして使う。claude.ai は Anthropic 側のクラウドから MCP を呼ぶので、インターネットから到達できる場所(API Management の前段)に置き、OAuth で守る。

エージェントが賢いかどうかより、「ここに書けば、あとは基盤が面倒を見る」という境界がはっきりしているかが、非エンジニアでも作れるかを決めます。
8 / 鍵を渡さない

コネクタ層: 資格情報は API Management の中にだけある

Cloudflare OS の Gatekeeper と同じ構造です。API Management の Credential Manager が外部サービスの OAuth トークンを保持し、アプリは Entra の ID だけで呼びます。アプリのコードにも環境変数にも、鍵は現れません。

アプリ connectors.salesforce .listOpportunities() 持ち物: アプリの ID + 本人の ID Entra JWT API Management JWT 検証: このアプリは許可済みか Credential Manager: トークンを付与 ポリシー: 商談のみ・読み取りのみ ポリシー: マスク・レート制限 ログ: 誰が・どのアプリで・何を 秘密の実体は Key Vault。APIM が参照する 外部 SaaS Salesforce / GitHub / Slack 基盤の共有アカウントの トークンで呼ぶ Entra 対応の社内システム Microsoft Graph / Dataverse 本人のトークンに交換して呼ぶ (On-Behalf-Of) 自作が要る部分: 書き込みの承認フロー 「結果を模擬して後で一括承認」は APIM に無い。 v1 は書き込みスコープの付与を承認制にすれば足りる 同じ API を MCP としても公開 APIM は REST API を MCP サーバーとして公開できる。 エージェント(手元・基盤内)も同じ関所を通る
アプリが持つのは自分の ID と本人の ID だけ。外部サービスのトークンは APIM の内側で付与され、絞られ、記録される。
2種類の接続先

共有アカウントか、本人か

Entra に対応していない外部 SaaS は基盤の共有アカウントで呼ぶ(Cloudflare OS と同じ)。Entra 対応の社内システムは本人のトークンで呼ぶ。後者は本人が見られないものはアプリでも見られない。

Cloudflare OS より有利な点

Microsoft 365 圏は「本人権限」で終わる

SharePoint、Teams、Outlook、Dataverse は OBO で本人権限になる。Cloudflare が観測追跡で後追いしている漏洩問題を、この範囲では構造で潰せる

Cloudflare OS より不利な点

承認 UI と型付き SDK は自作

APIM は HTTP の関所であって、「型付きバインディング」も「承認の受信箱」も付いてこない。SDK の生成(OpenAPI から)と承認画面は基盤チームが作る。

9 / 権限

「入れるか」「何ができるか」「何が見えるか」の3層

「アプリ内で社員の権限を設定したい」という要件は、3つの層に分けると Azure の既製機能だけで組めます

層1: 入れるか manifest の access に書いたグループ。入口で Easy Auth が弾く Entra グループ 層2: 何ができるか manifest の roles が App Roles になり、所有者がポータルで割り当てる Entra App Roles。アプリは user.hasRole() で判定 層3: 何が見えるか 社内データは本人のトークンで取るので、本人の権限を超えない On-Behalf-Of。共有アカウントの SaaS はスコープで絞る 営業 A 入れる sales-all 営業 B 入れる sales-all 開発 C 入れない グループ外 営業 A editor 編集できる 営業 B viewer 見るだけ 営業 A 自分の商談 本人の範囲 営業 B 自分の商談 A のは不可
同じアプリを3人が開いたときの結果。層1と層2はアプリの所有者がポータルから設定でき、層3は設定なしで本人の権限に従う。
Cloudflare の5原則の「AI 経由で本人以上の権限は得られない」は、層3を OBO にすることで、設定ではなく構造として成り立ちます
10 / LLM と状態

モデル呼び出しの関所と、アプリのデータ置き場

AI ゲートウェイ

アプリからの LLM 呼び出しも APIM 経由

アプリが要約や分類で LLM を使うときも、SDK の platform.llm.chat() が APIM を通る。llm-token-limit でアプリ/人ごとの上限、トークン計測でコスト帰属、Content Safety でフィルタ。背後は AI Foundry で、モデルは差し替えられる。

状態

Cosmos DB のアプリ別コンテナ

配置時にアプリ専用のコンテナを作り、そのアプリのマネージド ID にだけ RBAC を付与。他のアプリからは見えない。Cloudflare OS の「1インスタンス 1 SQLite」の役。

監査

Log Analytics に全部集める

Easy Auth のログイン、APIM の呼び出し(本人 ID 付き)、AI ゲートウェイのトークン、Container Apps のログ。「誰がどのアプリで何を見たか」はここで引ける。観測追跡の代わりになる範囲はここまで。

11 / AI コスト

作る側はサブスク、動かす側だけ API

AI の費用を「人が作るとき」と「アプリが動くとき」に分けます。前者は Claude / Codex のサブスクで全部まかなえます。後者は API 課金が残りますが、要るアプリだけに限定して上限を掛けられます。

用途費用備考
エンジニアが Claude Code で作るサブスクTeam / Enterprise プランなら席を組織で管理できる
非エンジニアが claude.ai で作るサブスク組織配布のコネクタと Skill は Owner が追加する。個人プランだと各自のアカウントに散らばる
アプリを動かす(一覧・入力・集計・コネクタ経由の表示)AI 費用ゼロ社内ツールの大半はここに収まる。形式 A はほぼ全部これ
アプリが実行時に LLM を呼ぶ(要約・分類・チャット UI)API 課金サブスクの資格情報をアプリから使うことは利用規約上できない。AI Foundry 経由で Claude / OpenAI を従量課金で使い、AI ゲートウェイで上限を掛ける
実行時 LLM の扱い

manifest で宣言、承認制、月額上限

使うアプリは manifest に予算を書く。承認はコネクタと同じ流れ。AI ゲートウェイがアプリ単位で llm-token-limit を掛けるので、1つのアプリが暴走しても全体には波及しない。

llm:
  models: [claude-sonnet]
  budget_monthly_jpy: 5000
Azure 内で完結

Claude も AI Foundry から呼べる

Claude モデルは Microsoft Foundry で一般提供されており、Azure の請求・認証・ガバナンスのまま使える。作る側は Anthropic のサブスク、動かす側は Azure の従量課金、という2本立てになる。

サブスクの限界

席ごとの利用上限がある

ヘビーユーザーが上限に当たると作業が止まる。API 課金の逃げ道を完全にゼロにはしない方が安全。ゼロを目指すより、上限が読める状態を目指す。

12 / 作らないもの

v1 で作らないものと、その代わり

作らない 1

観測追跡(データ由来の伝播)

  • Cloudflare OS 固有の仕組みで、Azure に既製品はない
  • 代わり: 社内データは OBO で本人権限。共有アカウント経由の SaaS は読み取り専用スコープを既定にし、機密度の高い接続先は最初から用意しない
  • 残る穴: 共有アカウントで読んだデータをアプリが別の人に見せる経路。コネクタの選定で塞ぐ
作らない 2

1人1インスタンス(Gadget)モデル

  • 「アプリ内で権限を設定したい」は共有アプリ + ロールの方が合う
  • 代わり: テンプレートを複製すれば「自分用のコピー」は作れる。Blueprint に相当
  • 残る差: 個人用アプリの乱立はポータルの所有者表示と棚卸しで管理する
作らない 3

書き込みの模擬承認

  • 「結果を模擬して先へ進み、後で一括承認」は自作すると重い
  • 代わり: 書き込みスコープの付与自体を承認制にする。付与後の個々の書き込みは止めない
  • 次の段階: 破壊的な操作だけ Durable Functions で承認待ちにする
先に判断すること

Power Platform との線引き

  • Copilot Studio + Power Apps + 900 超のコネクタ + DLP は、Microsoft が用意した「非エンジニア向け」の同じ答え
  • 自作基盤が勝つ条件: エージェントに本物のコードを書かせたい、手元のエージェントで作りたい、ロックインを避けたい
  • M365 中心の会社なら、簡単な用途は Power Platform、コードが要る用途はこの基盤、と分けるのが現実的
13 / リスク

先に知っておくべきこと

生成コードのサプライチェーン

エージェントが持ち込む npm / pip の依存は誰も読んでいない。CI の依存関係スキャンと、許可リスト方式のレジストリが要る。Cloudflare OS がコンテナを敬遠した理由の一つ。

コネクタ経由のプロンプトインジェクション

Slack や Notion から取った文章をアプリが LLM に渡すと、そこに指示が仕込まれている可能性がある。書き込みスコープを最小にすることが唯一の実効的な緩和。claude.ai からの deploy も書き込みなので、MCP 側で「本人のアプリだけ」を強制する。

アプリの乱立

Cloudflare では月 4,000 個生まれた。所有者・最終利用日・コストをポータルに出し、放置アプリを止める運用を最初から入れる。退職者のアプリは引き継ぐ。

Container Apps のコスト

形式 B は scale-to-zero でも、常時稼働が増えると V8 isolate ほど安くはない。アプリごとの上限(レプリカ数・CPU)をテンプレートで固定し、形式 A で済むものは形式 A にする。

プランの選び方

個人の Pro / Max で始めると、コネクタと Skill が各自のアカウントに散らばり、退職時に残らない。最初から Team か Enterprise にして、Owner がコネクタと Skill を配る

基盤チームが要る

SDK、テンプレート、承認画面、コネクタ追加、棚卸し。最初は 2〜3 人で、コネクタが増えるほど増える。「作って終わり」にはならない。

14 / 進め方

段階的に、最小から

0
判断する(1〜2週間)
アプリの形、Power Platform との線引き、Claude のプラン(Team / Enterprise)、最初のコネクタ2〜3種(例: Microsoft Graph、Salesforce、GitHub)。ここが決まらないと基盤の形が決まらない。
1
最小の経路を通す(6〜8週間)
Entra + Easy Auth、Container Apps、APIM にコネクタ2種、テンプレート、manifest、CLI、AGENTS.md。手元の Claude Code でアプリを作って社員が使えるところまで。承認は手動でよい。
2
claude.ai の入口(3〜4週間)
デプロイ用 MCP サーバー、形式 A(単一 HTML)のテンプレートとブラウザ用 SDK、組織配布の Skill。非エンジニアが claude.ai で作って載せられるところまで。基盤内にエージェントを作らないので、ここが軽い。
3
権限とガバナンス(4〜6週間)
App Roles の自動作成、OBO、ポータル(所有者・ロール割当・棚卸し)、承認画面、実行時 LLM の予算と AI ゲートウェイのコスト計測。
実現可能です。Azure に無いのは観測追跡と模擬承認だけで、どちらも v1 には要りません。作る側の AI はサブスクで済み、基盤内にエージェントを持たない分だけ前より軽くなります。先に決めるべきは技術ではなく、アプリの形と Power Platform との線引きと Claude のプランです。
出典(Azure の各機能)
用語メモ / 形式 A / 形式 B=この解説で置いた仮の呼び方。A は単一 HTML でサーバーコードなし、B はコンテナでサーバーコードあり。OBO(On-Behalf-Of)=アプリが受け取った本人のトークンを、別の API 用のトークンに交換して本人として呼ぶ OAuth のフロー。Easy Auth=Container Apps や App Service に組み込みの認証機能。コードを書かずに Entra ログインを挟み、本人の情報をヘッダーで渡す。Credential Manager=API Management の機能で、外部サービスの OAuth 接続を保持し、呼び出し時にトークンを付与する。Dynamic Sessions=Container Apps の、信頼できないコードを Hyper-V 隔離で短時間動かす仕組み。manifest=この解説で置いた仮の名前で、アプリが要るものを宣言するファイル。
← レポート一覧