メールの受信・保存・表示・送信と、AI による返信の下書きまでを、自社の Cloudflare アカウントの中だけで動かす。Cloudflare が 2026 年に公開したオープンソースのメールクライアント Agentic Inbox は、そういう作りになっています。外部のメール SaaS にデータを預けず、AI に問い合わせメールを読ませたい会社にとって、候補になり得る仕組みです。
この記事は、GitHub のリポジトリを手元の Mac に落として動かし、日本語のメールを4通流し込んで、何がどこまで動いたかを記録したものです。Cloudflare のアカウントにはログインせず、ローカル実行だけで確かめられる範囲に絞りました。AI 機能はその制約で動かせなかったので、動いたことと動かなかったことを分けて書きます。検証日は 2026 年 9 月 14 日、対象はリポジトリのコミット 48039bb です。
読み手として想定しているのは、問い合わせ窓口のメール対応を AI に手伝わせたいと考えている中小企業の担当者と、その実装を任されるエンジニアです。AI エージェント(人の指示を受けて、道具を使いながら自分で作業を進める AI)の基本は別の記事にまとめてあります。Gmail 側で進む同種の機能はGoogle I/O 2026 の発表を扱った記事を参照してください。
Agentic Inbox は製品ではなく、Cloudflare がメール送信機能の公開ベータに合わせて出した参考実装。日本語メール(UTF-8、JIS コード、日本語ファイル名の添付)の受信と表示は手元で問題なく動いた。AI の要約と返信下書きは、Cloudflare にログインしないと dev サーバーが起動しない構造のため未検証。認証はメールボックス単位ではなく、通った人が全メールボックスを読める設計。実用するなら Workers Paid(月 5 ドル)が前提で、まず捨ててよいドメインで自動下書きと認証が動くかを確かめてから窓口を載せ替えるのが順番。
この記事の要約
Agentic Inbox とは何か
リポジトリの説明文は「A self-hosted email client with an AI agent, running entirely on Cloudflare Workers」です。受信は Cloudflare Email Routing(自分のドメイン宛のメールを Cloudflare が受け取り、転送先や Worker に渡す機能)、保存はメールボックスごとの Durable Object(Cloudflare 上で状態を持てる小さなサーバー。中に SQLite データベースを持つ)、添付は R2(Amazon S3 互換のオブジェクトストレージ)、AI は Workers AI と Agents SDK、送信は 2026 年に公開ベータになった Email Sending を使います。
位置づけを最初に書いておきます。Cloudflare 公式ブログのEmail for Agentsは、メール送信機能の公開ベータを知らせる記事で、Agentic Inbox はその中で参考実装として紹介されています。同記事は、外部の AI ツールから操作できる MCP サーバー(AI ツールに道具を公開する共通規格の窓口)を最初から内蔵している点を売りに挙げています。製品として保守が約束されたものではなく、Cloudflare の各サービスをどう組み合わせるかを示すサンプルです。
README が挙げる機能は次の 5 点です。
- メールクライアント一式。送受信、リッチテキストでの作成、返信と転送のスレッド化、フォルダ、検索、添付
- メールボックスごとの分離。1 メールボックスにつき 1 つの Durable Object と SQLite、添付は R2
- サイドパネルの AI エージェント。持っている道具は 9 個で README の記載と一致する
- 新着メールへの自動下書き。送信前に必ず人が確認する、と README に明記
- メールボックスごとのシステムプロンプト、チャット履歴の保存、道具の呼び出し過程の表示
仕組みの全体像

入口は 1 つの Worker(Cloudflare の端で動く小さなサーバープログラム)で、Hono という軽量フレームワークが API と画面の配信を担います。メールが届くと Worker のメール受信ハンドラが MIME(メールの構造を定めた形式)を解析し、宛先に一致するメールボックスの Durable Object に本文とヘッダを書き込み、添付は R2 に置きます。画面はブラウザ側の React アプリで、AI エージェントとは WebSocket でつながります。
ソースを読んで分かった細かい点を 3 つ挙げます。1 つ目、受信メールの日時はメールの Date ヘッダではなく受信した時刻で記録されます。ソースにもその旨のコメントがあります。過去のメールを流し込む用途には向きません。2 つ目、メールボックスの実体は R2 上の JSON ファイルで、削除 API はこの JSON を消すだけです。本文と添付の実体は残ります。ソースに TODO として明記されています。3 つ目、AI は用途ごとに別のモデルを使い分けています。エージェント本体と自動下書きが Moonshot 社の kimi-k2.5、受信メールに紛れ込んだ指示文の判定が Llama 3.1 8B、下書きの校正が Llama 4 Scout です。
指示文の判定は、失敗したときに「注入あり」と判断する側に倒れます。ただし止まるのは自動下書きだけで、メール自体は受信箱に入ります。安全側の設計ですが、判定モデルが応答しないと下書きが一切作られなくなります。
本番で使うために揃えるもの
README の手順は 5 段階です。Deploy to Cloudflare ボタンからデプロイすると R2、Durable Objects、Workers AI が自動で用意され、受信したいドメインを聞かれます。次に Worker に対してワンクリックで Cloudflare Access(社内向けの認証ゲート)を有効にし、表示される POLICY_AUD と TEAM_DOMAIN の 2 つの値を Worker のシークレットに設定します。3 番目に、ダッシュボードのドメイン設定で Email Routing を開き、すべてのメールをこの Worker に渡す catch-all ルールを作ります。4 番目に送信用の Email Service を有効化し、最後にデプロイ先の画面でメールボックスを作ります。
ボタンを使わない場合の手順は次のとおりです。wrangler は Cloudflare の公式コマンドラインツールです。要求する Node.js は 20 以上ですが、手元の Node.js 20 では起動しなかったため 22.18.0 で検証しました。
npm install
# wrangler.jsonc の DOMAINS に受信ドメインを書く
wrangler r2 bucket create agentic-inbox
npm run deployEmail Routing を使う以上、そのドメインの DNS を Cloudflare で管理している必要があります。今回は手元で確かめておらず、Cloudflare のドキュメントの記載によります。これがないと受信そのものが成立しません。国内のレンタルサーバーやレジストラの DNS をそのまま使っている会社は、ここで一段の作業が入ります。既存のメールを Google Workspace などで受けているドメインに catch-all ルールを入れると、その受信経路と衝突するので、検証は別のドメインかサブドメインで行うのが安全です。

無料枠と有料枠の境界
Cloudflare のサービスは無料枠が広い一方、このアプリに関しては有料プランが事実上の前提になります。各サービスの料金ページを当たった結果を表にまとめます。金額と数量は 2026 年 9 月 14 日時点の公式ページの記載です。
| 使う機能 | 無料プランで動くか | 根拠 |
|---|---|---|
| メール受信(Email Routing) | 動く。受信は無料・有料とも無制限 | Email Service の料金 |
| メール送信(Email Sending) | 動かない。Workers Paid 専用。月 3,000 通込み、以降 1,000 通あたり 0.35 ドル | 同上 |
| Durable Objects(SQLite) | 動く。無料は 1 日あたり書き込み 10 万行、読み取り 500 万行、保存 5 GB まで | Durable Objects の料金 |
| R2(添付・設定) | 動く。月 10 GB、Class A 100 万回、Class B 1,000 万回まで無料 | R2 の料金 |
| Workers AI(エージェント) | 1 日 10,000 Neurons まで無料。ただし Moonshot 系モデルは無料プランでは呼べず、Workers Paid か AI Gateway の前払いクレジットが要る | Workers AI の料金、kimi-k2.6 のモデルページ |
| Workers 本体 | 無料は 1 日 10 万リクエスト、1 回 10 ms の CPU 時間。Paid は月 5 ドルから | Workers の料金 |
有料が前提になる理由は 2 つです。1 つ目は送信が Workers Paid 限定であること。返信できないメールクライアントは用途を成しません。なお、アカウント内で検証済みの転送先に送る分は無料で、送信枠にも数えられないため、自分宛の通知だけなら無料でも動く余地はあります。2 つ目はエージェントが使う Moonshot 系モデルが無料プランでは呼べないことです。
さらに気になる点があります。リポジトリが指定しているモデル ID は kimi-k2.5 ですが、2026 年 9 月 14 日時点の Workers AI のモデル一覧にこの ID はなく、モデルの個別ページも 404 でした。一覧にあるのは kimi-k2.6 と kimi-k2.7-code です。後継の kimi-k2.6 のページには、Workers Free の標準課金では使えず、Workers Paid か AI Gateway の前払いクレジットが要ると書かれています。カタログにないモデル ID を指している可能性があり、本番で実行時エラーになるかどうかは今回確かめられていません。
無料枠で先に上限に達しそうなのは Durable Objects の 1 日あたり書き込み 10 万行です。1 通の受信で本文の行、添付の行、既読の更新、エージェントのチャット履歴が書かれるため、メール数の数倍の行が動きます。今回は実測していないので、目安として受け取ってください。
手元で動かすまでに起きた 3 つのこと
検証環境は macOS 15、Node.js 22.18.0、wrangler 4.74.0 です。Node.js 20 では wrangler が起動を拒否するので、先に 22 系へ切り替えました。リポジトリを clone して npm install までは何も起きません。問題は npm run dev からです。
罠 1。AI バインディングがあるとログインなしでは起動しない
$ npm run dev
Error: Failed to start the remote proxy session, see the error details below:
You must be logged in to use wrangler dev in remote mode. Try logging in, or run wrangler dev --local.wrangler.jsonc の送信バインディングに remote: true が入っていたので false にしましたが、同じエラーです。AI バインディングに remote: false を足しても変わりません。原因は wrangler 4.74.0 の実装で、リモートに向けるバインディングを選ぶ関数が、種類が ai か media なら設定に関わらず必ずリモート扱いにしています。Workers AI にはローカルの模擬実行がないので理屈は通りますが、結果として AI バインディングが 1 つでも定義されていると、ログインしない限り dev サーバー自体が起動しません。
ログインせずに画面を確かめるため、wrangler.jsonc から ai のブロックを丸ごと外しました。これで起動しますが、その瞬間にエージェント機能は使えなくなります。「まず手元で試してから判断する」ができない構成だという点が、この検証で最初に分かったことです。
罠 2。初回アクセスが Application Error になる
Playwright(ブラウザを自動操作するツール)で開くと、画面が Application Error になり、React の useContext が null だという例外が出ました。dev サーバーのログを見ると、初回アクセスの途中で Vite(開発用のビルドツール)が依存パッケージの最適化を 3 回に分けて実行し、そのたびに再読み込みが走っています。今回 1 回の観測ですが、これが原因と見ています。ページを 1 回リロードすれば正常に描画されます。初見では壊れていると判断してしまう挙動です。
罠 3。ローカル受信のエンドポイントが公式ドキュメントと違う
Cloudflare のローカル開発の手順は、/cdn-cgi/local/email に生のメールを POST すると書いています。ところがこのリポジトリでは React Router のキャッチオール経路が POST を受けて 405 Method Not Allowed を返し、しかも「POST したが action がない」というエラー文が出るので、原因にたどり着きにくい。実際に通ったのは /cdn-cgi/handler/email のほうでした。
curl -s -w "nHTTP %{http_code}n"
-X POST "http://localhost:5174/cdn-cgi/handler/email?from=alice@sender.example&to=hello@example.com"
-H 'Content-Type: application/json'
--data-binary "@mail/1-en.eml"
# Worker successfully processed email
# HTTP 200日本語メールを 4 通流した結果
受信箱の動作を確かめるため、次の 4 通を RFC 5322(メールの書式の規格)どおりに手書きして投入しました。
| # | 内容 | 文字コードと形式 |
|---|---|---|
| 1 | 英語の平文。見積依頼 | UTF-8、text/plain |
| 2 | 日本語。件名は MIME encoded-word、本文は base64 | UTF-8 |
| 3 | 日本語。CSV 添付付き。添付ファイル名も日本語(見積明細.csv) | UTF-8、multipart/mixed |
| 4 | 日本語。件名と本文が JIS コード | ISO-2022-JP、7bit |
4 通とも受信箱に入り、日本語の件名、本文、差出人の表示名、添付ファイル名のすべてが正しく復元されました。3 通目の添付を API からダウンロードすると、CSV の中身も壊れていません。

4 通目の JIS コードは、国内の古い業務システムや一部のメールソフトが今も送ってくる形式です。これも件名「納品書の送付について」、本文「いつもお世話になっております。納品書を送付いたします。ご確認ください。」が UTF-8 に変換されて格納されていました。MIME の解析は postal-mime というライブラリが担っていて、文字コード周りで困る場面は考えにくいという結論です。

細かい仕様として、フォルダ ID は小文字です。API に folder=INBOX を渡すと 0 件、folder=inbox なら件数が返ります(3 通目まで投入した時点で 3 件)。受信日時は前述のとおり投入した時刻になり、メールに書いた Date ヘッダは無視されます。
送信(ローカル模擬)と MCP は手元でそのまま動いた
送信は API に日本語の件名と本文を渡すと 202 が返り、miniflare(wrangler が内蔵するローカル実行環境)が送信内容を一時ファイルに書き出してログに表示します。外には飛びません。書き出されたテキストの中身は「お見積りをお送りします。」で文字化けなし、Sent フォルダにも日本語件名のまま入りました。
MCP サーバーは AI を外した状態でも応答しました。/mcp に initialize を投げるとサーバー名 agentic-inbox が返り、tools/call で list_emails を呼ぶと日本語の件名と本文の抜粋を含む JSON がそのまま返ります。他の道具は今回実行していません。手元の Claude Code や Cursor からメールを一覧して下書きを作らせる、という使い方が最初から想定されています。MCP でつなぐ道具の考え方はClaude の MCP コネクタを扱った記事に書きました。

ローカルでは /mcp に認証が一切かかりません。開発モードでは Cloudflare Access の検証を丸ごと飛ばす実装だからです。本番では Access の背後に入りますが、Access を通った相手はメールボックス ID を指定して任意のメールボックスを読み書きできます。次の節で触れる認証モデルの話と同じ問題がここにも出ます。
AI エージェントはローカルでは動かなかった
エージェントパネルの定型質問「Show me the latest inbox emails」を押すと、WebSocket はつながり、メッセージは Durable Object まで届きます。しかし Workers AI の呼び出しで例外が出ます。
Error on server: Error: Invalid Workers AI configuration: you must provide either a binding
(e.g. { binding: env.AI }) or credentials ({ accountId, apiKey }).
at createWorkersAI (...workers-ai-provider.js)
at EmailAgent.onChatMessage (workers/agent/index.ts:279)バインディングを外した以上これは当然の結果ですが、問題は画面に何も出ないことです。パネルは Thinking のまま止まり、エラーは表示されません。ログには「Override onError(error) to handle server errors」と出ていて、エラー処理が実装されていないことが分かります。本番で Workers AI の日次上限に当たったときも同じ見え方になるはずで、利用者は原因が分かりません。
もう 1 つ、受信のたびに dev サーバーのログへ同じ例外が出ました。「Missing namespace or room headers when connecting to EmailAgent」というもので、受信処理の末尾が EmailAgent の Durable Object を直接 fetch しているのに対し、Agents SDK 側は名前空間と部屋のヘッダを要求しています。呼び出しは catch 節でエラーを記録するだけなので受信は成功しますが、自動下書きは一度も作られませんでした。Workers AI に到達する前に例外が出ているので、AI バインディングを外したこととは無関係の経路です。本番でも同じ失敗をする可能性がありますが、ログインした環境で確かめていないので断定はできません。
要約と返信下書きの品質は、したがって今回まったく評価できていません。README が目玉に挙げる機能の評価が空白のままだという点は、この記事の限界として明記しておきます。
認証は「通った人が全部読める」設計
README に次の一文があります。「Any user who passes the shared Cloudflare Access policy can access all mailboxes in this app by design.」つまりメールボックス単位の権限はなく、Access のポリシーを通った人は全員が全メールボックスを読み書きできます。/mcp 経由でも同じです。実装は Cloudflare Access が付ける JWT(署名付きの認証トークン)を検証するだけで、本番で POLICY_AUD と TEAM_DOMAIN が未設定なら 500 を返して閉じます。
この設計は、info@ や support@ のような共有窓口を数人で見る用途なら欠点になりません。役員宛と問い合わせ窓口を同じアプリに同居させる使い方は成り立ちません。社員個人のメールボックスを載せる用途にも向きません。AI にメールを読ませるときのデータの扱いは、顧客データを外に出さずに AI を使うための 6 項目とAI エージェントが企業データを漏らす 5 つの経路で整理した観点がそのまま当てはまります。
プライバシーの面では、メール本文は自社アカウントの Durable Object に、添付は自社の R2 に入ります。外部の SaaS に預けない代わりに、バックアップ、エクスポート、保存期間の仕組みを自分で用意することになります。このアプリにはどれもありません。AI 機能を使うと本文は Workers AI のモデルに渡るので、「外部に出していない」と言い切れるかは Workers AI のデータ取り扱い条項を読んでから判断することになります。
詰まりどころの一覧
実際に踏んだものを、原因と対処付きで並べます。
| 事象 | 原因 | 対処 |
|---|---|---|
| npm run dev がログインを要求して止まる | wrangler 4.74.0 が AI バインディングを無条件にリモート扱いにする | 画面だけ見るなら wrangler.jsonc から ai を外す。AI を試すならログインするしかない |
| 初回アクセスが Application Error | Vite の依存最適化が 3 段階で走り、そのたびに再読み込みが入る(推定) | 1 回リロードする |
| 受信テストが 405 になる | 公式ドキュメントの /cdn-cgi/local/email が、この構成では React Router のキャッチオール経路に届く | /cdn-cgi/handler/email に POST する |
| エージェントが Thinking のまま止まる | サーバー側の例外が画面に伝わらない。エラー処理が未実装 | dev サーバーのログを見る。本番なら Workers のログ |
| 自動下書きが作られない | 受信処理が EmailAgent を直接 fetch していて Agents SDK に弾かれる | リポジトリの Issue を確認する。本番での再現は未確認 |
| モデル ID がカタログにない疑い | 指定は kimi-k2.5、一覧にあるのは k2.6 と k2.7-code | 課金アカウントで 1 回動かして確かめる |
番外として、5173 番ポートが使用中で、npm run dev は 5174 番で起動しました。ポート番号を決め打ちにした手順書を書くと外れます。
中小企業にとって現実的か
向く用途は、共有の問い合わせ窓口を 1〜2 本、数人のチームで見る使い方です。全員が全メールを見てよい前提の箱なら、認可が粗いことは欠点になりません。MCP サーバーが最初から付いているので、手元の AI ツールから未読を一覧して下書きを作る、といった操作を自社のインフラの中で完結させられます。外部 SaaS に API キーを預けるより経路が短い構成です。
向かない用途は 3 つです。社員個人のメールボックス、既存メールの移行を伴う置き換え(インポート機能がなく、受信日時もメールの Date を無視する)、業務の基幹となる連絡経路(送信機能がベータで、新規アカウントの日次送信枠は小さいところから始まり実績に応じて拡大される仕様)。基幹の連絡経路を自社運用に切り替えるなら、n8n をセルフホストしたときの記事で書いた運用負荷の見積もりを、メールでも同じように行うことになります。
費用は小規模なら小さい。Workers Paid の月 5 ドルに月 3,000 通の送信が含まれ、受信は無制限、R2 の無料枠 10 GB は添付の少ない窓口なら当分足ります。数人の会社で窓口を 1 本運用する程度なら、月 5 ドルと Workers AI の超過分で収まる見込みです。
総合すると、既存のメール環境を置き換える候補としては、現時点では勧められません。README が目玉に挙げる自動下書きが手元では例外で動かず本番でも不安が残ること、AI の失敗が画面に出ないこと、そしてリポジトリ自体が送信機能のベータに添えられた参考実装であることが理由です。一方、Cloudflare 上でメールを受けて AI に処理させる仕組みを自社で作るときの土台としては、受信から保存、添付、スレッド化、MCP 公開までが一通り揃っていて、日本語も通ることが確認できたので、読む価値と流用する価値はあります。
導入を検討するなら、この順番で
- 捨てても困らないドメインかサブドメインを 1 つ用意し、ネームサーバーを Cloudflare に向ける
- Workers Paid にしてから Deploy to Cloudflare でデプロイし、Access を有効化する
- Email Routing の catch-all ルールを作り、日本語メールを 1 通送って受信箱に入るか見る
- 自動下書きが作られるか、エージェントパネルが応答するかを確かめる。ここで止まるなら現時点では見送る
- MCP を手元の AI ツールにつなぎ、未読の一覧と下書きの作成を試す
- 動いたら初めて本番の窓口を載せ替える。個人のメールボックスは載せない
この検証で手元に残ったのは、ローカルでの起動手順、受信の再現コマンド、日本語 4 通の結果、MCP の動作確認、そして AI 機能の空白です。Cloudflare にログインして残りを埋めた時点で、続報を書きます。
FDE を募集しています(会計FDE/FDE・業務システム)
経理の月次をAIで本番まで持っていく「会計FDE」(会計士・経理責任者・管理部門経験者)と、要件が固まる前に動くものを出して本番まで運ぶ「FDE(業務システム)」(ITコンサル・PM/PL・情シス出身者)を正社員で募集しています。応募でなくても構いません。まず30分の「キャリア相談」から。採用のお問い合わせフォームに「キャリア相談希望」と書いて送ってください。
問い合わせメールを AI に読ませる仕組みを、自社のアカウントの中で作ります
Agentic Inbox のような参考実装をそのまま入れるか、受信と保存だけ流用して AI の部分を自社の要件で作り直すかは、メールの量と、誰がどのメールボックスを見てよいかで決まります。経理AX・kintone・Claude 導入で本番稼働まで伴走した経験をもとに、いまの問い合わせ窓口の流れを見るところから始められます。