コンテンツにスキップ

Cloudflare OS アーキテクチャ整理

作成日: 2026-08-19 出典 / きっかけ: blog.cloudflare.com/cloudflare-os、github.com/cloudflare/cloudflare-os 関連: 社内aiエージェント基盤_company_brain_比較_整理(10製品の横断比較)llm_agent_sandbox_隔離技術 ai_agent_identity_標準化2026 手を動かした写経: ~/ai-engineering-study/lectures/cloudflare_os_basics/

Cloudflare が社内向けに開発し 2026年8月に OSS 化した「AI operating system for companies」を、認証・認可・ゲートウェイ・実行分離・監査の5観点で整理する。

社内実績:2026年5月に全社員へ第1版を提供、エンジニア以外を含む数千人が日常利用。直近30日で 4,000超のアプリ/ツールが作られ、営業チームで 10,000時間超を節約。リポジトリは cloudflare/cloudflare-os(core)と cloudflare-os-starter(デプロイ例)の2本立て。

全体像

flowchart TB
    subgraph EXT["外部システム / SoR"]
        GH["GitHub"]
        DWH["データウェアハウス"]
        SAAS["SaaS / MCP サーバー"]
    end

    subgraph CFOS["Cloudflare OS"]
        subgraph GK["Gatekeeper 層"]
            G1["Gatekeeper Worker<br/>OAuth保持 / 認可判定<br/>フィールドマスキング<br/>レート制限 / 承認"]
            OBS["観測ログ<br/>誰が何を見たか"]
        end
        subgraph WS["エージェントワークスペース"]
            AG["エージェント<br/>ゼロ権限で開始"]
            BIND["typed binding<br/>env.PROJECT"]
            APP["生成アプリ<br/>Dynamic Worker + DO Facet"]
        end
        AIGW["AI Gateway<br/>モデル選択 / 予算 / 帰属"]
    end

    USER["社員"] -->|"Cloudflare Access で認証"| WS
    AG --> BIND
    BIND -->|"RPC: 能力の行使"| G1
    G1 -->|"Gatekeeperが持つ資格情報でAPI実行"| EXT
    G1 --> OBS
    AG -.->|"全推論"| AIGW
    AIGW -.-> LLM["各種LLMプロバイダ"]
    APP --> BIND

    style G1 fill:#f9e79f
    style OBS fill:#f9e79f
    style AIGW fill:#aed6f1

1. 認証(authn)

入口は Cloudflare Access(ZTNA) が担当し、「誰が Cloudflare OS に入れるか」を組織自身のポリシーで制御する。ここは既存 Zero Trust 製品の流用で、独自実装ではない。

特徴的なのは、認証の重心が「人の入口」に置かれ、その先はほぼ認可の問題として設計されている点。エージェントに独立したアイデンティティを与える(Microsoft Entra Agent ID のような)アプローチではなく、エージェントは「その人のワークスペースの中で動く実行主体」であり、外部サービスへの認証は Gatekeeper が肩代わりする。エージェント自身が外部に対して認証することがない。

2. 認可(authz)

Cloudflare OS の中核。capability(ケーパビリティ)型で、公式ブログの表現では「すべてのエージェントとアプリはアクセス権ゼロの状態から始まる」。

sequenceDiagram
    participant A as エージェント
    participant C as Core
    participant Ad as 管理者
    participant G as Gatekeeper
    participant S as 外部サービス

    Note over A: 権限ゼロで起動
    A->>C: リソースへのアクセスを要求
    C->>Ad: 承認リクエスト
    Ad-->>C: 許可(範囲・ポリシー付き)
    C-->>A: typed binding を注入<br/>env.PROJECT
    Note over A: 資格情報は渡されない

    A->>G: env.PROJECT.listIssues()
    G->>G: ポリシー評価<br/>スコープ / レート / 承認要否
    G->>S: 自分が保持する<br/>OAuthトークンでAPI呼出
    S-->>G: レスポンス
    G->>G: 禁止フィールドをマスキング
    G-->>A: 結果のみ返却
    G->>G: 観測内容を記録

粒度はサービス単位ではなくリソース・操作・フィールド単位まで下ろせる。ブログの例では、GitHub アカウント全体ではなく「単一リポジトリのみ」「issue の読み取りのみでソースコードは不可」「特定フィールドのマスキング」「PR マージ前に承認要求」。元のサービスの API が提供していない粒度を Gatekeeper が後付けで作れるのがポイント。

データ伝播制御(差別化点)

認可は取得時点で終わらない。エージェントが観測した全リソースを記録し、その記録が成果物に付随する。

flowchart LR
    T["機密テーブル"] -->|"読取"| A["エージェント<br/>観測ログに記録"]
    A --> D["生成ダッシュボード<br/>観測ラベルを継承"]

    D --> Q{"別ユーザーが閲覧"}
    Q --> GK["Gatekeeper が<br/>元データへの権限を検証"]
    GK -->|"権限あり"| OK["表示"]
    GK -->|"権限なし"| NG["拒否"]

    A --> Q2{"外部リクエスト<br/>コラボレーター追加<br/>他エージェントへ委任"}
    Q2 --> GK2["観測内容に応じて制限"]

    style GK fill:#f9e79f
    style GK2 fill:#f9e79f

「機密テーブルを読んだエージェントが作ったダッシュボードの共有が、実質的に元テーブルの横流しになってはいけない」という問題への解。taint tracking 的な情報フロー制御であり、取得時の認可だけでは防げない二次流出を塞ぐ層。他プロジェクトにほぼ実装例がない。

第1版での気づき——「MCP はどのツールを呼べるかは分かるが、エージェントがどの基礎リソースを観測したかは分からない」——を受けて第2版で追加された経緯がある。

3. ゲートウェイ

データゲートウェイ = Gatekeeper

サービスごとに書かれた Worker で、対象 API・管理するリソース・実行可能な操作を理解している。担当するのは OAuth 処理、資格情報の保管、アクセスルールの適用、読み取り内容の記録、外部に影響する操作の仲介。エージェントから見えるのは小さな TypeScript API だけ。

既存の MCP サーバーは MCP Server Portal 経由で別途接続。

モデルゲートウェイ = AI Gateway

全推論リクエストが必ず通る。利用可能モデルの一元管理、リクエストの人・チーム・ワークスペースへの帰属、予算とレート制限、上限到達時の挙動制御。「毎朝の未読メール要約に最高価格のモデルは要らない」というコスト最適化の統制点。

異常検知(AI Spend)は過去30日のセッションコスト95パーセンタイルとの比較で、2倍超を異常候補と判定。

egress 制御

サーバーコードは外向きネットワークを無効化した Dynamic Worker で動き、明示的に許可された capability を経由しない限りインターネットに出られない。「鍵を盗んでも外に送れない」の担保

4. 実行分離

flowchart TB
    subgraph B["ブラウザ"]
        CL["クライアントコード<br/>サンドボックス化フレーム"]
    end
    subgraph CF["Cloudflare エッジ"]
        SV["サーバーコード<br/>Dynamic Worker (V8 isolate)<br/>外向きネットワーク無効"]
        DO["Durable Object Facet<br/>アプリ専用 SQLite"]
    end
    CL <-->|"Cap'n Web<br/>object-capability RPC"| SV
    SV --- DO
    SV -->|"許可された capability のみ"| OUT["外部"]
    CL -.->|"直接は出られない"| X["✕"]

    style X fill:#f5b7b1

コンテナや VM ではなく V8 isolate(Dynamic Workers) を使うのが特徴で、専用サーバーやコンテナなしに「すべてのアプリが独自の隔離実行環境を持つ」ことを実現。Durable Object Facet により各アプリが Cloudflare OS 本体とは分離された専用 SQLite を持つ。

ここは Cloudflare のインフラ資産があって初めて成立する設計で、自前で真似るのが最も難しい部分。

永続性の思想は Anthropic / Shopify の「session は生き残らせ、実行環境は使い捨て」と同じで、それが Durable Object という形で実装されている。アプリは「ファイル」でありながらフルスタックアプリ(クライアント/サーバー/API/永続状態)。

5. 監査・ガバナンス

  • 観測ログが全アクセスの記録を兼ね、単なる監査証跡ではなく認可判断のインプットとして能動的に使われる(他と違う点)
  • HITL は Gatekeeper のポリシーに埋め込まれる(PR マージ前の承認など)。QM のような「全ツールコールを止める posture」ではなく、リソース・操作単位で承認が必要な箇所を宣言する方式
  • コスト統制が AI Gateway 側でガバナンスの一部として統合
  • アプリ共有の二形態:アプリ本体の共有(状態も共有)と blueprint 共有(コードのみ継承、SQLite の中身・会話履歴・資格情報・接続済みリソースは継承しない)。後者が権限の意図せぬ伝播を防ぐ設計

補足:Gatekeeper が「鍵を預かる」とはどういうことか

鍵を渡す方式(QM 等)

エージェントのサンドボックス内:
  環境変数 GITHUB_TOKEN=ghp_xxxx が置いてある
  エージェントが curl -H "Authorization: ghp_xxxx" ... を実行

エージェント自身がトークンを読めて、自分で API を叩く。シンプルだが、プロセスが乗っ取られたらトークンをそのまま外部送信できる。トークンは「アカウント全体に効く鍵」なので、被害は許したかった範囲を超える。

Gatekeeper 方式

トークンはエージェントのいる環境に一度も入らない。エージェントに渡されるのは env.PROJECT という型付きバインディング=「listIssues という関数が呼べる」という能力(capability)であって、鍵ではない。関数を呼ぶとリクエストが Gatekeeper に転送され、Gatekeeper が自分の金庫にあるトークンで本物の API を叩き、結果だけを返す。

貸金庫の例え:鍵を渡す方式は「合鍵を渡す」、Gatekeeper 方式は「窓口の職員に『あの書類を取ってきて』と頼む」。職員は閲覧を許可された書類しか取ってこないし、頼める操作の種類も決まっている。

効く理由:

  1. 盗むものが存在しない — 実行環境をどれだけ探してもトークンがない。乗っ取られたエージェントができるのは「許可された関数を呼ぶこと」までで、それ自体が毎回検査を通る
  2. 鍵より細かく権限を切れる — GitHub のトークンは粗い単位でしか発行できないが、Gatekeeper は「このリポジトリの issue だけ、読み取りだけ、このフィールドは隠す、マージは承認必須」のようにサービス側が提供していない粒度の認可を後付けで作れる
  3. 全アクセスが1点を通るので記録できる — データ伝播制御が成立する前提。鍵を渡す方式ではエージェントが何を読んだかをプラットフォームが完全には把握できない

トレードオフ: サービスごとに Gatekeeper(その API を理解した仲介コード)を書く必要があるため、接続先を増やすコストは「サンドボックスに CLI を入れてトークンを置くだけ」方式より高い。安全性と接続の手軽さの交換。


Medley 文脈での要点

観点 評価
capability 型認可 借りるべき
Gatekeeper(データGW) 借りるべき
AI Gateway(モデルGW) 借りるべき
データ伝播制御 参考にすべきだが自前実装は重い
V8 isolate 実行分離 そのまま真似られない(Cloudflare 依存)

BigQuery + dbt Semantic Layer の構成なら、Gatekeeper 相当の層を Semantic Layer の前に置き、そこで行・カラムレベルのポリシーとフィールドマスキングを強制するのが素直な移植になる。エージェントには「メトリクスを問い合わせる能力」だけを型付きで渡し、SA キーはその層が保持する。認可の粒度を BigQuery の IAM だけに依存させないのがポイント。

関連ノート


作成: 2026-08-19 / 最終更新: 2026-08-19