AI と通信の制限の全体図
ForgeKairos の AI と外部通信の制限を図で示す。細かい規則は 外部通信の統制 と AI を見る。
1 つの要求が通るか
AI の機能が始める HTTP の要求は、次の順に判定する。
flowchart TD
R["外部への要求"] --> O{"エディター自身の通信の印があるか<br/>(言語サーバー、拡張機能、更新、Git など)"}
O -- "ある" --> FREE["制限しない"]
O -- "無い (AI の通信として扱う)" --> L{"loopback か<br/>127.0.0.0/8、::1、localhost"}
L -- "はい" --> ALLOW["許可"]
L -- "いいえ" --> B{"組み込みの許可か<br/>(マーケットプレイス、ACP レジストリ、<br/>ForgeKairos の更新の確認。決まったパスだけ)"}
B -- "はい" --> ALLOW
B -- "いいえ" --> A{"許可リストのホストに一致するか<br/>network_allowlist.json"}
A -- "はい" --> ALLOW
A -- "いいえ" --> DENY["拒否"]
ALLOW --> RD{"リダイレクトか"}
RD -- "いいえ" --> DONE["送る"]
RD -- "はい: 次の hop も同じ判定へ<br/>(別のホストなら資格情報のヘッダーを外す)" --> L
- 許可リストが空でも loopback は通るので、ローカル LLM (Ollama、LM Studio、llama.cpp) は設定なしで使える。
- ホストを許可すると、そのホストのすべてのポートを許可する。
誰がどの経路で制限されるか
flowchart LR
subgraph APP["ForgeKairos 本体"]
AI["AI の機能<br/>プロバイダー、編集予測、<br/>fetch と Web 検索、MCP (HTTP)"]
TOOLS["エディターの道具<br/>言語サーバー、拡張機能、<br/>更新、Git、リモートのサーバー"]
GATE["許可リストの判定<br/>(loopback + 組み込みの許可 + allowed_hosts)"]
PROXY["loopback のプロキシ<br/>(loopback + allowed_hosts だけ。<br/>組み込みの許可は使わない)"]
end
subgraph CHILD["子プロセス"]
ACP["ACP エージェント"]
MCP["MCP サーバー (stdio)"]
NPM["エージェントを入れる npm"]
end
SB["エージェントのサンドボックス<br/>(WSL / bubblewrap / Seatbelt)"]
BR["内蔵ブラウザー"]
NET(("インターネット"))
AI --> GATE --> NET
TOOLS -- "制限しない" --> NET
ACP & MCP & NPM -- "HTTP_PROXY / HTTPS_PROXY" --> PROXY --> NET
SB -- "サンドボックス自身の許可 ∩ 許可リスト" --> NET
BR -- "既定は制限しない。<br/>browser.use_egress_proxy で許可リストを通す" --> NET
- 子プロセスのプロキシは、プログラムがプロキシの環境変数を読むことに頼る。読まないプログラムは制限できない。
proxy_child_processes: falseで切れる。 - サンドボックスは許可リストを狭めることはできるが、広げることはできない。
クラウドの AI を使い始めるまで
既定ではどの AI も動かず、外部のプロバイダーには何も送らない。
sequenceDiagram
actor U as ユーザー
participant FK as ForgeKairos
participant AL as 許可リスト
participant P as クラウドのプロバイダー
Note over FK: agent.enabled = false (既定)。AI はすべてオフ
U->>FK: 設定 → AI → エージェントを有効にする
Note over FK: ローカル LLM (loopback) はこの時点で使える
U->>FK: 外部のプロバイダーを選ぶ
FK-->>U: 警告 (入力と会話が送られる) と必要なホスト
U->>FK: 確認のチェック
Note over FK: acknowledged_external_ai_providers に記録
U->>AL: 許可リストに追加
FK->>P: ここで初めて要求が通る
Note over U,AL: 承諾を取り消すと、ほかが使わないホストを<br/>許可リストから外すか尋ねる
承諾しても許可リストに足さなければ、そのプロバイダーへの通信は拒否のまま。
エージェントがコマンドやツールを実行するとき
flowchart TD
T["エージェントのツールの呼び出し"] --> AC{"どのモードでも確認するものか<br/>安全の規則、always_confirm、<br/>サンドボックスの外、権限の昇格、<br/>.zed や設定への書き込み、プロジェクトの外"}
AC -- "はい" --> ASK["ユーザーに確認"]
AC -- "いいえ" --> M{"agent.tool_permissions.default"}
M -- "confirm (既定)" --> ASK
M -- "deny" --> NO["実行しない"]
M -- "allow" --> RUN
M -- "auto" --> J{"判定用のモデルに尋ねる<br/>(10 秒の上限)"}
J -- "SAFE" --> RUN
J -- "それ以外" --> ASK
ASK -- "承認" --> RUN["サンドボックスの中で実行"]
RUN --> NETSB["ネットワークは許可リストで制限<br/>資格情報 (~/.ssh、.npmrc など) は読めない"]
RUN --> PAUSE["プロジェクトに書き込んだら、<br/>そのフォルダーのコード (フォーマッター、<br/>言語サーバーのビルドスクリプトなど) を<br/>再開するまで止める"]
autoはコマンドとパスを判定用のモデルのプロバイダーに送るので、ローカルのモデルを勧める。- サンドボックスを切れるのは
agent.sandbox_permissions.allow_unsandboxedだけで、切っている間はすべてのコマンドで確認する。
SSH のリモート
flowchart LR
subgraph LOCAL["手元の PC"]
AL["許可リスト<br/>(手元のものだけ)"]
CL["ForgeKairos"]
end
subgraph REMOTE["リモートのホスト"]
RS["リモートのサーバー"]
RP["リモートの loopback のプロキシ<br/>(Windows のリモートを除く)"]
RA["ACP エージェント / MCP サーバー"]
end
NET(("インターネット"))
AL --> CL
CL -- "接続時と変更のたびに送る" --> RS
RS --> RP
RA -- "HTTP_PROXY" --> RP --> NET
RS -- "ダウンロード<br/>(relay_http_through_client、既定でオン)" --> CL --> NET
インターネットに出られないリモートでも、手元の PC 経由で言語サーバーを取ってこられる。