cloudflare

Stars and mentions

Last 30 days, Oct 4 – Nov 2

GitHub stars29,033
mentions505
06691.3K2K2.7KOct 4Oct 18Nov 2
UTC days · repositories cloudflare owns54 repositories

Package downloads

Cumulative recorded downloads · since 2025-10-18

crates.io—
npm—
PyPI204
02.4B4.7B7.1B9.5BOct 4Oct 18Nov 2
Nov 1crates.io: 0/40 packages observed · npm: 0/55 packages observed · PyPI: 1/1 packages observed

Across 96 known packages in repositories cloudflare owns. Cumulative totals include recorded downloads before the selected range. Missing observations leave gaps; totals may be incomplete. PyPI excludes known mirrors.

Top repositories

cloudflare’s repositories ranked by pull request authors, as on trending.

Loading

Contributes to

Repositories outside cloudflare’s account where cloudflare opened or reviewed pull requests in the past 365 days.

Who noticed cloudflare

Everyone who starred or forked cloudflare’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

503posts
Nov 38 posts
  1. 初めてのCI/CD。pushしただけで公開まで流れる理由を、図で理解した(GitHub Actions + Cloudflare Workers) 1. はじめに CI/CDという言葉は知っていましたが、なかなか勉強するまでには至りませんでした。それが仕事で使うことになり、とうとう勉強を始めることにしました。 とはいえ、どこから手をつければいいのか分かりません。調べると記事はたくさんあり、手順も丁寧に書かれています。ただ、どれも「こう書けば動く」が中心で、なぜpushしただけで最後まで流れるのかは、読んでもいまいち分かりませんでした。 幸い、今はAIという優秀なパートナーがいます。そこで今回は、AI(Claude Code)に助けてもらいながら、自分の環境で1つずつ検証していきました。 まず作ったのは、GitHubにpushすると、GitHub ActionsがCloudflare Workersへ自動で公開してくれるしくみです。画面で操作したのは3つ、書いたファイルも3つだけで、pushすると公開まで勝手に進んでいきます。実際に動かしてみても、やはり疑問は「何で流れるの?」、これだけでした。 この記事では、手順に加えて、なぜ最後まで自動で流れるのかを図で説明します。同じところでもやもやしている人の参考になればうれしいです。 なお、記事の内容はすべて自分の環境で動かして確かめていますが、CI/CDは初心者です。間違いなどがあれば、コメントで教えていただけるとうれしいです。 2. 作ったもの GitHubのmainブランチにpushすると、約30秒で https://test.tobaru.net のページが更新されるしくみです。ページはHTMLファイル1つだけの、いちばん小さなものにしました。 ひとことで言うと、GitHubに置いたファイルを、GitHubのロボット(Actions)がCloudflareまで運んでくれます。運ぶときにCloudflareのドアを開けるので、ロボットに合鍵(APIトークン)を預けてあります。 !04_overview.png 自分で用意したサーバーはありません。DNSのレコードとhttpsの証明書も、手では作っていません。 3. 環境 | 項目 | 内容 | |---|---| | GitHub | Freeプラン、Privateリポジトリ | | Cloudflare | Freeプラン | | ドメイン | Cloudflare Registrarで取得したtobaru.net(DNSもCloudflare) | | デプロイの道具 | cloudflare/wrangler-action@v4、wrangler 4 | | 作業したPC | Windows 11、VS Code、Git | 自分のPCにNode.jsやwranglerは入れていません。wranglerはGitHub Actionsの中でだけ動きます。 ドメインのDNSがCloudflareにあることが、後で出てくる「1行でDNSと証明書ができる」の条件になります(5章の(5))。 4. 手順 画面で操作したのは(1)〜(3)の3つだけです。(4)はファイルを書くだけ、(5)はpushするだけです。 (1) GitHubにリポジトリを作る - 名前はtobaru-net-test、Privateにしました - README・.gitignore・ライセンスは付けず、空のリポジトリにします(ローカルで作ったファイルをそのままpushするため) (2) CloudflareでAPIトークンを作る 1. 右上の人のアイコン → プロフィール → APIトークン → トークンを作成する 2. テンプレート「Cloudflare Workers を編集する」を使う 3. 範囲を絞る - アカウントリソース: 自分のアカウントだけ - ゾーンリソース: 特定のゾーン → tobaru.netだけ 4. 作成する。トークンは一度しか表示されないので、そのまま(3)に貼る 範囲を絞っておくと、万一トークンが漏れても、できることは「Workersの更新」と「tobaru.netの設定」だけです。 (3) GitHubのSecretsに登録する リポジトリの Settings → Secrets and variables → Actions → New repository secret で、2つ登録します。 | Name | 値 | |---|---| | CLOUDFLARE_API_TOKEN | (2)で作ったトークン | | CLOUDFLARE_ACCOUNT_ID | CloudflareのアカウントID | (4) ファイルを3つ書く tobaru-net-test/ ├─ public/ │ └─ index.html … 見せるページそのもの ├─ wrangler.jsonc … Cloudflareへの注文書(何を・どこで出すか) └─ .github/ └─ workflows/ └─ deploy.yml … Actionsへの指示書(いつ・何をするか) public/index.htmlは、ふつうのHTMLです(中身は省略)。 wrangler.jsoncです。ふつうのJSONはコメントが書けませんが、jsonc(JSON with Comments)は//で書けます。 { // Cloudflare側でのWorkerの名前(名札)。 // この名前のWorkerがなければ新しく作り、あれば中身を置き換える "name": "tobaru-net-test", // Workersの動き方の基準日 "compatibility_date": "2026-10-01", // 静的なファイル(HTML・画像など)の置き場所。この中身がそのままサイトに並ぶ "assets": { "directory": "./public" }, // どのURLで出すか。custom_domain: true でDNSレコードと証明書も作ってくれる "routes": [ { "pattern": "test.tobaru.net", "custom_domain": true } ], // xxx.workers.dev というCloudflareのURLでは公開しない "workers_dev": false } .github/workflows/deploy.ymlです。 name: Deploy # いつ動くか(イベントの条件) on: push: branches: [main] # mainブランチにpushされたとき workflow_dispatch: # Actionsタブの「Run workflow」ボタンで手動でも動かせる jobs: deploy: runs-on: ubuntu-latest # GitHubが数十秒だけ貸してくれるLinux permissions: contents: read steps: # 1. このcommitのファイル一式をランナーに取り出す - uses: actions/checkout@v5 # 2. wranglerをインストールして動かす(commandを書かなければ wrangler deploy) - name: Deploy to Cloudflare Workers uses: cloudflare/wrangler-action@v4 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} # 金庫の合鍵 accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} # どのアカウントに送るか wranglerVersion: "4" (5) pushする git init -b main git add -A git commit -m "最初のページとデプロイ設定" git remote add origin https://github.com/<ユーザー名>/tobaru-net-test.git git push -u origin main pushしてから約30秒で、https://test.tobaru.netが開けるようになりました。10秒おきに確かめると、最初の3回はつながらず、4回目で200が返ってきました。 5. なぜ最後まで自動で流れるのか 答えを先に書くと、何かがずっと監視しているわけではありません。「イベントが起きたら、こう動く」という小さな決まりが、前の結果を受け取ってつながっているだけです。 pushしてから公開されるまでを、5つの段階に分けました。 !05_sequence.png 画像をクリックすると、大きく表示されます。 ここからは、私が分からなかったところを順に説明します。 (1) GitHubはフォルダを監視しているの? 監視はしていません。pushやプルリクエストなどのイベントが起きたときにだけ、GitHubがそのcommitの.github/workflows/を開きます。中のYAMLを全部読んで、on:の条件に合うものだけを動かします。 それが分かる例です。 | こんなとき | デプロイは動く? | |---|---| | README.mdだけ変えてpush | 動く。deploy.ymlは変わっていないが、「mainへのpush」というイベントが起きたから | | deploy.ymlを書き換えたが、pushしていない | 動かない。GitHubは自分のPCの中を見ていない | | deploy.ymlを書き換えてpush | 書き換えた後の内容で動く。そのcommitのファイルを読むから | | 別のブランチにpush | 動かない。on:がbranches: [main]だから | | プルリクエストをmainにマージ | 動く。マージするとmainにcommitが入り、mainへのpushと同じになるから | 「受付の人がマニュアルをずっと見張っている」のではありません。「呼び鈴が鳴ったらマニュアル棚を開いて、今回の用件に当てはまるページを探す」イメージです。マニュアル棚が.github/workflows/、ページの見出しがon:です。 (2) ファイルを指定していないのに、なぜwrangler.jsoncが使われるの? deploy.ymlのデプロイの手順には、「どのファイルを送るか」を書いていません。それでも動くのは、書かなかったときの決まり(既定値)が2段階あるからです。 1. wrangler-actionの決まり: commandを書かなければdeployを実行する(action.ymlに「Defaults to "deploy"」とあります)。workingDirectoryも書かなければ、リポジトリのいちばん上で実行する 2. wranglerの決まり: wrangler deployは、実行したフォルダでwrangler.jsonc / wrangler.json / wrangler.tomlを探して読む しかも、wrangler.jsoncそのものは送られません。「何を・どこに・どんな名前で」の指示として読まれ、送られるのはassets.directoryに書いたpublic/の中身です。 決まった名前・決まった場所に置けば何も書かなくても動き、変えたいときだけ書く。この考え方を「設定より規約(Convention over Configuration)」と呼ぶそうです。(1)の.github/workflows/も同じです。 (3) Cloudflareで何も作っていないのに、なぜWorkerができるの? wrangler.jsoncの"name": "tobaru-net-test"で、「この名前のWorkerを、この中身にして」と頼んでいるからです。Cloudflareは、その名前のWorkerがなければ新しく作り、あれば中身を置き換えます。上の図のaltのところです。 どのアカウントに作るかはaccountId、入っていいかはapiTokenで伝えています。どちらもSecretsから渡しているので、deploy.ymlには値そのものを書いていません。 (4) Secretsは何のため? Secretsは合鍵を入れておく金庫です。deploy.ymlには${{ secrets.CLOUDFLARE_API_TOKEN }}と、「金庫のこの引き出しを使って」とだけ書きます。合鍵そのものはどのファイルにも書かないので、コードを人に見せても漏れません。 (5) 1行でDNSと証明書までできるの? できました。routesに"custom_domain": trueと書くと、「このホスト名をまるごとこのWorkerにする」意味になり、CloudflareがDNSのレコードとhttpsの証明書を作ってくれます。 ただし、次の2つがそろっているからできることです。 - tobaru.netのDNSが、同じCloudflareアカウントにある(Cloudflareが自分でレコードを書き込める) - APIトークンにtobaru.netを触る権限がある(4章の(2)でゾーンを絞って許可した) DNSが別の会社にあるドメインでは、この1行だけでは済みません。 custom_domainを付けずに"pattern": "test.tobaru.net/api/*"のように書くと、「このURLに来たアクセスだけWorkerが受け取る」という別の使い方になります。この場合、DNSのレコードは自分で作ります。 6. 警告が出たところ 最初は、他の記事と同じくcloudflare/wrangler-action@v3を使っていました。デプロイは成功しましたが、Actionsの結果のAnnotationsに、警告1件とお知らせ1件が出ました。 !01_annotations.png (1) Node.js 20 is deprecated(警告) > Node.js 20 is deprecated. The following actions target Node.js 20 but are being forced to run on Node.js 24: cloudflare/wrangler-action@v3. wrangler-action@v3はNode.js 20向けに作られていて、GitHub側がNode.js 20を廃止していく途中なので、Node.js 24で動かしているという知らせです(GitHubのお知らせ)。今は動いていますが、将来動かなくなるおそれがあります。 調べるとv4が出ていて、action.ymlにusing: "node24"とありました。入力の項目(apiToken・accountIdなど)は同じなので、@v3を@v4に変えるだけで警告が消えました。 この修正もdeploy.ymlを1文字直してpushしただけです。しくみそのものの設定を変えた場合も、ページを変えた場合と同じ流れで反映されます(5章の(1)の表の3行目)。 (2) ubuntu-latestがUbuntu 26に移る(お知らせ) > The ubuntu-latest label will migrate to Ubuntu 26 beginning October 19, 2026. runs-on: ubuntu-latestの中身が、順に新しいUbuntuに切り替わるという案内です(runner-imagesのIssue)。今回のワークフローはwranglerを動かすだけなので、そのままにしています。 (3) nameを変えるときの注意 つまずいたわけではありませんが、しくみから考えると注意が必要だと分かったところです。 nameを変えてpushすると、Cloudflareは名前が変わったとは受け取りません。「その名前のWorkerがないので新しく作る」と受け取ります(5章の(3))。古いWorkerは残ったままになるので、変えるときは古いほうの片付けも必要です。 7. Cloudflareの画面で確かめる Cloudflareの画面では何も作っていませんが、pushしたあとに開くと、次の2つができていました。 (1) Workersの一覧 「Workers & Pages」を開くと、wrangler.jsoncのnameで付けたtobaru-net-testがあり、routesで頼んだtest.tobaru.netがつながっていました。 !02_workers.png 「デプロイメントを表示」を開くと、pushした回数ぶんの履歴が並んでいます。GitHubのcommitと1回ずつ対応しています。 (2) DNSのレコード tobaru.netのDNSのページには、自動で作られたtestのレコードがありました。自分では1つも作っていないのに、本当にレコードが出ていてびっくりしました。 !03_dns.png | 見えているもの | 意味 | |---|---| | 左端の鍵のアイコン | 自動で作られたレコードなので、ここからは編集できない | | タイプ「Worker」 | AやCNAMEではなく、「このWorkerに届けて」という特別なレコード | | コンテンツ「tobaru-net-test」 | wrangler.jsoncのname。名札でつながっている | | 「プロキシ済み」 | アクセスはいったんCloudflareが受け取る | 外のDNS(1.1.1.1)にtest.tobaru.netを聞いてみると、返ってくるのはCloudflareのIPアドレス(104.21.x.xなど)でした。「プロキシ済み」なので、サーバーの場所ではなくCloudflareのアドレスが返ります。応答のヘッダーにはServer: cloudflareとCF-RAY: …-NRTがあり、東京の拠点から返っていることも分かりました。 8. まとめ 最初は、なぜ自動で最後まで流れるのかが、いまいち理解できませんでした。でも、監視という大掛かりな仕組みではありませんでした。イベントが起きたときの動きが決まっていて、その決まりどおりに動くと、流れるように最後までつながる。それが分かったとき、美しいなーと思いました。DNSの画面に、自分では作っていないレコードが出ていたときも感動しました。 今回分かったことを並べると、次の3つです。 - GitHubは監視していない。イベントが起きたときに.github/workflows/を読み、on:に合うものだけを動かす - 書いていないことは既定値で動く。wrangler-actionはdeployを実行し、wranglerは決まった名前のwrangler.jsoncを探す - CloudflareはnameでWorkerを見分け、なければ作り、あれば置き換える。custom_domain: trueならDNSと証明書も作る 次は、プルリクエストを作ったらチェックだけを動かし、mainにマージしたらデプロイする形(CIとCDの分離)を試す予定です。チェックも、pull_requestというイベントに決まりを足すだけで作れるはずです。

    1 like
  2. > You personally want to believe that LLM usage is somehow essentially solely responsible for the bad product It's been confirmed (at least, in the HN thread) by a representative of Jepsen that Orkes were using adversarial LLM review. And given that even very basic test setups failed instantly, it's hard to believe that this LLM review was coupled with human review. So what I believe is that they likely adopted a form of agentic coding that had no routine human review in the process. And that, I suspect, is how they ended up in the situation of believing their software was well-tested and conformant when it wasn't. More on that in a bit. > history has shown bad products were made by human programmers all the time I've spent an enormous amount of time trying to teach the teams I work with techniques for creating software that isn't bad, including solid and thorough testing and review processes. The all-in LLM approach requires discarding those very techniques in favor of just trusting that enough layers of adversarial agents will get it right. My own direct experience is that this doesn't work. And earlier this year I posted a long piece which, among other things, included a review of some studies into LLM-assisted coding which found that it's not the case that software is just as bad as before: it's the case that with LLMs, software is getting worse than before, quickly. The CircleCI report cited there, for example, is based on a huge sample of CI runs to show both the rate of failures and the time to resolution of failures, and both of those numbers went strongly in the wrong direction. CircleCI has continued to update their data, and though there's been a small rebound the state of software quality, as far as they're able to measure it, still appears to be significantly down from what it was prior to the advent of LLMs. > If you read a positive report that said LLM usage went fine, would you be just as similarly convinced that LLM usage is actually good? My experience is that such reports tend to be one-off anecdotes and also tend to struggle under scrutiny. For example: also noted in that long piece I linked above was Cloudflare's big announcement earlier this year that they had used LLMs to build their own clone of Next.js from the ground up using an agentic coding/review/fix loop. This was, at the time, held up as a triumph and a great success story for LLM coding. Except if you read what I wrote about that, and follow some of the links I provided, you'll see that on release it was unable to run a basic default "Hello, world" Next.js app, and that it was riddled with security issues because, it turned out, their LLM coding agents had simply failed to copy over and use the full original Next.js test suite. Which created the false impression that Cloudflare had a well-tested and verified implementation when in fact they did not. That's the same sort of situation Orkes found themselves in, and yet at the time I don't recall prominent LLM coding advocates accusing Cloudflare (as they are accusing Orkes, now, in various places) of being dilettantes who simply didn't know how to use LLMs properly. > People will read what they want into their report, and invent any number of scenarios that justify it. I pointed out a basic tension with LLM usage: the selling point of LLM coding is that it generates so much software so quickly that no human can keep up with it, so you essentially have to remove human review from the loop. But LLM-only loops with no human review are not reliable enough to actually get away with doing this. ParticleDB is the latest example of this problem, but far from the only one. To the extent that anyone has a "chip on their shoulder" in this thread, it seems to be you, since you're becoming extremely defensive and hostile over what is pretty basic and reasonable criticism of the effectiveness of LLM coding, rooted in the actual observable evidence in front of us.

    14 points
  3. Cloudflare AgentsがPi 1.4に対応したので、Agentの中断・復旧・永続化を検証する > 中断された Agent は、最後のチェックポイントから正しく再開しました。副作用が2回起きたのは、そのせいです。 この記事の結論 Cloudflare Agents SDK が Pi 1.4 に対応したので、Durable Object 上の Agent を実際に停止させ、会話履歴・タスク・ツール実行がどこまで復旧するかを測りました。復旧機構は期待どおり動きましたが、Agent が復旧することと、外部の副作用が重複しないことは別です。 - Pi 1.4 で追加された Hibernation と Parked Tasks は、実際の Durable Object で確認できた - replay: "safe" は冪等性を検査しない。非冪等なツールに付けると、同じ副作用が2回起きる - Storage Error Recovery は進行中の呼び出しを救わず、次の操作から Pi を開き直す仕組みだった - agents@0.30.0 には、別タスクが動いているとリトライ待機中のタスクを起こせない既知の不具合がある。使うなら 0.30.1 以降にする | 観測したもの | 結果 | | --- | ---: | | 再起動後の会話履歴 | 読み戻せた | | 完了済みタスク | 二重実行されなかった | | safe な冪等ツール | 再実行されたが副作用は1回 | | safe と宣言した非冪等ツール | 副作用が2回 | | unsafe ツール | 自動再実行されず、完了もしない | | Hibernation | 待機中に別インスタンスで再開 | 検証コードはこちらです: github.com/tanahiro2010/slides/tree/main/slides/s… そして、この記事で一番伝えたいことを先に書いておきます。 replay: "safe" は、ツールを安全にする機能ではありません。 Pi に対して「このツールは途中で止まったら再実行してよい」と宣言するだけです。副作用が本当に冪等か、同じリクエストを2回受けても外部 API が重複処理しないかは、ツールの実装側が保証しなければなりません。 > この記事は「Cloudflare AgentsがPi 1.4に対応したので、Agentの中断・復旧・永続化を検証する」の登壇内容に、発表で話しきれなかった検証手順・実測値・失敗した測定を足したものです。対象は Cloudflare Agents と Pi Durable を使って、外部 API やデータベースを操作する人です。 --- 1. 「Pi 1.4 対応」の4項目を分解する 2026年10月22日、Cloudflare は Agents SDK の Pi 1.4 対応を発表しました。Changelog には次の4項目が並んでいます。 - Hibernation - Parked Tasks - Storage Error Recovery - Model Stream Retry 最初は、4つとも Pi 1.4 の新機能だと思いました。しかし、配布物と変更履歴を追うと、出どころは2層に分かれていました。 | Changelog の項目 | 実際の変更元 | | --- | --- | | Hibernation | Pi 1.4 の sleeping タスクを Agents SDK が配線 | | Parked Tasks | Pi 1.4 の機能を Agents SDK が公開 | | Storage Error Recovery | Agents SDK 側の修正。Pi のバージョンとは別 | | Model Stream Retry | Agents SDK 側の修正。Pi 1.3 でも成立 | 特に Model Stream Retry の PR には、Pi 1.3.0 と Pi main の両方で判定を確認したと書かれていました。つまり、Storage Error Recovery と Model Stream Retry を Pi 1.3 と 1.4 で比較するのは軸が違います。比較すべきなのは agents@0.29.0 と agents@0.30.x です。 ベンダーの Changelog は、利用者にとって分かりやすい単位で変更をまとめています。一方、障害が起きたときに調べるには、どのパッケージのどの層が責任を持つかを分ける必要があります。 2. Pi、PiHarness、Lifecycleの役割 今回の構成には3つの層があります。 | 層 | 担当 | | --- | --- | | Pi Durable | Agent の実行ループ、タスク、チェックポイント、replay | | PiHarness | Pi に Durable Object の SQLite と起動処理を接続 | | Lifecycle | Durable Object 上で長時間の仕事を実行し、必要なときに起こす | Pi Durable は Cloudflare のパッケージではありません。@earendil-works/pi-durable として提供され、Agents SDK 側の PiHarness が Durable Object に組み込みます。 ここで重要なのは、保存と再開が別の機能だということです。 - 会話履歴やタスクの保存先は、pi_ で始まる SQLite テーブル - 眠っているタスクを再開するのは、Lifecycle の Wake ジョブと Durable Object Alarm 保存できていても、起こす仕組みがなければ再開しません。逆に、再開できてもチェックポイントがなければ、どこから続けるか分かりません。今回の検証では、この2つを混ぜないようにしました。 Pi Durable の設計記事には、次のようにあります。 > every step of a run is a task that stores a checkpoint before it moves on. このチェックポイントが、再起動後に「完了済みのタスクをもう一度実行しない」ための基礎になります。 3. まず、観測そのものを永続化する 障害復旧を測るとき、最初に作るべきなのは実験対象ではなく記録機構です。Durable Object の書き込みは、呼び出した瞬間にすべてがディスクへ確定するわけではありません。 検証用のレコーダは、イベントを SQLite に書いたあと、通常は ctx.storage.sync() を呼ぶようにしました。直後に ctx.abort() を呼び、再起動後にイベントが残っているかを比較します。 | 記録の仕方 | 再起動 | 再起動後に残った行数 | | --- | --- | ---: | | sync() あり | した | 1 | | sync() なし | した | 0 | どちらもコンストラクタで発行したインスタンス ID が変わっていました。本当に同じインスタンスが動き続けたのではなく、再生成後のインスタンスが SQLite を読んでいます。 ctx.abort() は通常の throw とは違います。アプリケーションコードでは catch できず、Durable Object を即座にリセットします。障害注入に通常の例外を使うと、Agent の復旧ではなく「同じインスタンスのエラー処理」を測ってしまいます。 この土台を確認してから、以降のイベントはすべて sync() ありで記録しました。ログに残らなかった観測を、復旧の証拠には使っていません。 4. 会話履歴とタスクは再起動を越えて残る ツールを1回実行する Agent を動かし、処理が完了したあとに ctx.abort() で Durable Object を落としました。再起動後に transcript とイベントを読みます。 | 観測 | 再起動前 | 再起動後 | | --- | ---: | ---: | | インスタンス識別子 | — | 変化した | | transcript のエントリ数 | 5 | 5 | | ツール実行開始 | 1 | 1 | | 副作用 | 1 | 1 | 完了済みのタスクは二重実行されませんでした。同じ operationId を使った submit も、1回目は accepted: true、2回目は accepted: false になりました。異なる ID を使うと accepted: true になるため、submit 全体が壊れたわけではありません。 ここまでは、Pi Durable がチェックポイントと submit の識別子を使って、完了済みの仕事を保護している結果です。 5. クライアントが切れても、Agentは動き続ける 次に、モデルのリトライで処理時間を伸ばし、途中で WebSocket を切断しました。クライアントがいなくなったあとも実行が続くかを確認します。 結果は、最終的に done になりました。モデル呼び出しは「失敗2回、成功1回」の3回です。切断前後でインスタンス IDは変わっていません。 これは「落ちて復旧した」のではありません。Agent の実行がクライアント接続に依存していなかったということです。 再接続後は snapshot から現在の状態を組み立て直せました。ただし、切断中に流れたイベントをカーソルで途中から再生できるわけではありません。イベントストリームは状態を追うためのものではありますが、履歴ストリームの代わりではありません。 6. Parked Tasksはクラッシュループを止める 同じ場所で何度も ctx.abort() を発生させ、restartLimit を2に下げて測りました。 | 落とし方 | 障害発火 | インスタンス生成 | pending() | 次の Alarm | | --- | ---: | ---: | --- | --- | | ctx.abort() | 2 | 2 | parked | なし | | 通常の例外 | 1 | 0 | 空 | なし | 通常の例外は Durable Object をリセットしないため、再起動回数には入りません。Parked に到達するには、実際に再起動される障害が必要です。 Parked になったタスクは、放置しても Durable Object を起こし続けません。手動では2つの抜け方があります。 | 操作 | 戻り値 | wait() | | --- | --- | --- | | session.retry() | true | done | | session.abort() | ok | unanswered / aborted | retry() はやり直す操作、abort() は放棄する操作です。クラッシュループを止めるだけでなく、運用者が判断して再開か放棄かを選べる設計になっています。 なお、ツールが api.output() で進捗を8回出しても、再起動カウントは戻りませんでした。Pi が進捗として扱うのは、ツールの出力ではなく、タスクが次の状態をコミットしたことです。まだ完了していない1つのツールが出力を吐き続けても、クラッシュループの上限はリセットされません。 7. Storage Error Recoveryは「次の操作」から効く Storage Error Recovery は、ストレージエラーが起きたあとに Pi を開き直せる機能です。ここでは Storage を Proxy で包み、次の2種類のエラーを注入しました。 - commit() などから任意のエラーを返す - 読み取りから StorageRequestError を返す どちらも、現在進行中の呼び出しはエラーになりました。しかし、次の submit() は成功し、最終的に done になりました。致命的な Storage エラーでは factory の実行回数が1から2に増えましたが、Durable Object 自体のインスタンス IDは変わっていません。 つまり、これは Durable Object のクラッシュ復旧ではありません。PiHarness が壊れた Pi をキャッシュから外し、次の操作または Wake ジョブの次のステップで Pi を開き直しています。 進行中の呼び出しは救われません。 仕様にも、すでに実行中の呼び出しは SessionFailed で失敗するとあります。factory は何度実行されても正しく初期化できるように書く必要があります。 8. replay: "safe" は副作用を守らない ここが今回の中心です。4種類のツールを用意し、実行開始・副作用の確定・終了を別々に記録しました。副作用確定直後に Durable Object を落とし、再起動後の挙動を比較します。 | ツール | replay | 冪等性 | 実行開始 | 副作用 | 完了 | | --- | --- | --- | ---: | ---: | ---: | | write_record | safe | あり | 2 | 1 | 1 | | bump_unsafe | 未指定 | なし | 1 | 1 | 0 | | bump_safe_unguarded | safe | なし | 2 | 2 | 1 | | bump_safe_guarded | safe | あり | 2 | 1 | 1 | write_record は同じ値を書き込むので、2回実行されても結果は変わりません。bump_safe_unguarded はカウンターを1増やすだけで、実行されるたびに結果が変わります。このツールに safe を付けると、Pi は宣言を信じて再実行し、副作用が2回確定しました。 一方、bump_unsafe は自動再実行されません。副作用確定後に落としたケースでは、副作用は1回だけ残りましたが、ツールは完了していません。Agent は中断されたツール結果をモデルへ渡して run を決着させます。 中断されたツールの transcript は、専用のエントリになるわけではありません。通常と同じ pi.tool-result ですが、内容が次のように変わります。 <harness> [error] Tool bump_unsafe was interrupted and may have partially run </harness> このメッセージは、モデルに「部分的に実行されたかもしれない」と伝える平文です。その後にモデルが同じツールを呼び直すかどうかは、モデルの判断に委ねられます。今回の実モデルによる3試行では呼び直しませんでしたが、1モデル・1プロンプト・3試行だけなので一般化はしません。 bump_safe_guarded には冪等キーを入れました。再実行自体は起きていますが、2回目はキーを見て副作用をスキップし、確定回数は1回に収まりました。 ここから分かることは明確です。safe の判断を間違えても Pi は警告しません。 外部 API、決済、メール送信、データベース更新などをツールに持たせるなら、safe の設定とは別に冪等キーや重複排除を実装する必要があります。 9. Model Stream Retryはエラー文言で判定される Model Stream Retry は、途切れたモデルストリームを一時的なエラーとして扱い、ターン全体を再試行します。配布物を読むと、判定はエラー本文の正規表現でした。 同じ回数だけ失敗させ、エラー文言だけを変えました。 | エラー文言 | 結果 | モデル呼び出し | | --- | --- | ---: | | The stream ended before the model finished its answer. | unanswered | 1 | | The stream ended without the model finishing its answer. | done | 3 | | Model stream stalled: no data received for 60s. | unanswered | 1 | | Model stream timed out: no data received for 60s. | done | 3 | | insufficient_quota: the account has no remaining credit. | unanswered | 1 | 再試行対象の文言では「失敗2回、成功1回」の3回になりました。つまり、再試行は部分的なストリームの続きではなく、モデルリクエスト全体の作り直しです。 baseDelayMs を100秒に設定しても、待機時間の上限は約60秒でした。既定の maxAgentDelayMs が60,000ミリ秒だからです。設定値を大きくしたからといって、無制限に待つわけではありません。 10. Hibernationは、待機中に別インスタンスで再開する Hibernation の測定では、最初に alarm の時刻を比べました。しかし、ローカルの workerd では onWake の有無にかかわらず、alarm の秒数が一致しました。これは測定対象を間違えています。 Hibernation の本質は、alarm の時刻ではなく、待機中に Durable Object がメモリから退避できるかです。そこで実デプロイし、コンストラクタでインスタンス IDを記録して、リトライがどのインスタンスで走るかを見ました。 onWake を渡した場合は、次のようになりました。 model_error@old-instance → instance_started@new-instance → model_request@new-instance onWake を渡さない場合は、次のようになりました。 model_error@same-instance → model_request@same-instance | onWake | リトライを走らせたインスタンス | | --- | --- | | 渡す | 別インスタンス | | 渡さない | 同じインスタンス | リトライ待機中は、測定のために一度もリクエストを送りませんでした。途中で触るとオブジェクトが起きてしまい、退避を観測できないからです。 処理中の work と、リトライ待ちの sleep は別の状態です。work がある間は heartbeat Alarm が30秒ごとに再設定されます。一方、sleep 中は最初に起きるタスクの時刻が次の Alarm になります。この2つを混ぜると、Hibernation の測定結果を誤読します。 11. agents@0.30.0 の不具合を再現する 公式が案内した agents@0.30.0 で検証を始めようとしました。しかし、このバージョンには、別タスクが動いているとリトライ待機中のタスクが起きない既知の不具合があります。 1つの Harness で、次の2本を並行させました。 - セッションA: 60秒走るツールを実行する - セッションB: 再試行対象のエラーを返し、12秒の backoff に入る | | B単独 | 並行する work あり | | --- | ---: | ---: | | agents@0.30.1 | 12秒 | 12秒 | | agents@0.30.0 | 12秒 | 57秒 | 0.30.0 では、B のリトライが A の完了まで止まっていました。0.30.1 では、A が動いていても B は予定どおり12秒後に再開します。 原因は配布物の差分からも確認できます。0.30.0 は Pi が active かどうかだけを見ていました。0.30.1 では、sleep の期限 wake.at を次の待機期限に使い、期限に達したら pi.resume() を呼びます。 これは煽るための話ではありません。PiHarness が Beta と案内されていることの、具体的な例です。Pi 1.4 の Hibernation を検証するなら、agents@0.30.1 以降を使う必要があります。 12. Pi 1.4に上げると、1.3には戻せない Pi 1.4 は session storage の SQLite schema を更新するため、Pi 1.3 へロールバックできません。 実際に Pi 1.4 で1ターン実行したあとの schema version は 2 でした。配布物のマイグレーション定義を比べると、次の差があります。 | バージョン | マイグレーション | | --- | --- | | pi-durable@1.3.0 | version 1 のみ | | pi-durable@1.4.0 | version 1 と version 2 sleepingStatus | Pi 1.3 のマイグレーションランナーは、対応していない新しい schema version を見つけるとエラーにします。追加された sleepingStatus は、Pi 1.4 の Hibernation を支える sleeping タスク状態そのものです。 つまり、Durable Object を退避できるようになったことと、ロールバックできなくなったことは、別々の変更ではありません。同じ schema 変更の表と裏です。 Pi 1.4 と1.3を比較するときは、同じ Durable Object を使い回してはいけません。実験用の名前を分け、マイグレーションを一方向のものとして扱います。 13. 測定をやり直して分かったこと この検証では、最初の測定結果をそのまま記事にしませんでした。対照を組み直した結果、3つの主張を修正または保留にしています。 WebSocketのイベント取りこぼし 最初は、遅いイベントリスナーがイベントを取りこぼすように見えました。しかし、WebSocket を8秒で閉じていたことが原因でした。ドレイン時間を30秒に延ばすと、遅いリスナーでもイベント数は一致しました。 進捗の定義 自前カウンターの更新を Pi の進捗だと思い込んでいました。api.output() を8回呼ぶ対照に変えても、未完了のツールは Parked になりました。ツールの出力ではなく、タスクが状態をコミットしたかどうかが進捗です。 19分のモデルストリーム Worker 内の faux Provider で約19.2分のストリームを流したところ、モデル呼び出し1回のまま完走しました。ただし、これは外部モデル API へのHTTP接続を19分維持した測定ではありません。公式の「15分を越えるリクエストは切断されることがある」という制約を否定する材料にはならないため、結論は保留にしました。 障害復旧の検証では、「結果が出た」だけでは不十分です。そもそも障害が起きていなかった、観測側が先に接続を閉じた、という可能性を対照で潰す必要があります。 14. まとめ Cloudflare Agents と Pi 1.4 の復旧機構は、実際に動きました。会話履歴は再起動後に読み戻せ、完了済みタスクは二重実行されず、クラッシュループは Parked Tasks で止まり、リトライ待機中の Agent は Hibernation によって別インスタンスで再開できました。 しかし、Pi が守っているのは Agent の実行状態です。あなたの外部副作用まで自動的に exactly-once にしてくれるわけではありません。 実装時には、次の点を守る必要があります。 - 外部操作には冪等キーや重複排除を入れる - replay: "safe" は、2回実行しても安全だと自分で証明できるツールだけに付ける - unsafe にしても、確定済みの副作用が消えるわけではない - factory は Storage Error Recovery で何度も呼ばれる前提で書く - Hibernation を使うなら agents@0.30.1 以降を使う - Pi 1.4 に上げた Durable Object は、Pi 1.3 に戻せない 最後に、検証から持ち帰る教訓を1つに絞るならこれです。 「復旧した」と「重複せずに完了した」は、別の主張です。 参考 - Cloudflare Changelog — Agents SDK now supports the latest Pi 1.4 release — Pi 1.4 対応として発表された4項目 - Cloudflare Docs — Pi — PiHarness、Recovery、Hibernation の公式ドキュメント - Cloudflare Docs — Pi Extensions — ツールの replay 設定と復旧時の扱い - agents CHANGELOG — 0.30.0 / 0.30.1 の変更 - cloudflare/agents#2683 — onWake と並行タスクに関する既知の不具合 - pi-durable CHANGELOG 1.4.0 — Pi 1.4 の sleeping タスクと schema migration - Pi Durable の設計記事 — チェックポイントとタスク実行の設計

  4. Cloudflare AgentsがPi 1.4に対応したので、Agentの中断・復旧・永続化を検証する > 中断された Agent は、最後のチェックポイントから正しく再開しました。副作用が2回起きたのは、そのせいです。 この記事の結論 Cloudflare Agents SDK が Pi 1.4 に対応したので、Durable Object 上の Agent を実際に停止させ、会話履歴・タスク・ツール実行がどこまで復旧するかを測りました。復旧機構は期待どおり動きましたが、Agent が復旧することと、外部の副作用が重複しないことは別です。 - Pi 1.4 で追加された Hibernation と Parked Tasks は、実際の Durable Object で確認できた - replay: "safe" は冪等性を検査しない。非冪等なツールに付けると、同じ副作用が2回起きる - Storage Error Recovery は進行中の呼び出しを救わず、次の操作から Pi を開き直す仕組みだった - agents@0.30.0 には、別タスクが動いているとリトライ待機中のタスクを起こせない既知の不具合がある。使うなら 0.30.1 以降にする | 観測したもの | 結果 | | --- | ---: | | 再起動後の会話履歴 | 読み戻せた | | 完了済みタスク | 二重実行されなかった | | safe な冪等ツール | 再実行されたが副作用は1回 | | safe と宣言した非冪等ツール | 副作用が2回 | | unsafe ツール | 自動再実行されず、完了もしない | | Hibernation | 待機中に別インスタンスで再開 | 検証コードはこちらです: github.com/tanahiro2010/slides/tree/main/slides/s… そして、この記事で一番伝えたいことを先に書いておきます。 replay: "safe" は、ツールを安全にする機能ではありません。 Pi に対して「このツールは途中で止まったら再実行してよい」と宣言するだけです。副作用が本当に冪等か、同じリクエストを2回受けても外部 API が重複処理しないかは、ツールの実装側が保証しなければなりません。 > この記事は「Cloudflare AgentsがPi 1.4に対応したので、Agentの中断・復旧・永続化を検証する」の登壇内容に、発表で話しきれなかった検証手順・実測値・失敗した測定を足したものです。対象は Cloudflare Agents と Pi Durable を使って、外部 API やデータベースを操作する人です。 --- 1. 「Pi 1.4 対応」の4項目を分解する 2026年10月22日、Cloudflare は Agents SDK の Pi 1.4 対応を発表しました。Changelog には次の4項目が並んでいます。 - Hibernation - Parked Tasks - Storage Error Recovery - Model Stream Retry 最初は、4つとも Pi 1.4 の新機能だと思いました。しかし、配布物と変更履歴を追うと、出どころは2層に分かれていました。 | Changelog の項目 | 実際の変更元 | | --- | --- | | Hibernation | Pi 1.4 の sleeping タスクを Agents SDK が配線 | | Parked Tasks | Pi 1.4 の機能を Agents SDK が公開 | | Storage Error Recovery | Agents SDK 側の修正。Pi のバージョンとは別 | | Model Stream Retry | Agents SDK 側の修正。Pi 1.3 でも成立 | 特に Model Stream Retry の PR には、Pi 1.3.0 と Pi main の両方で判定を確認したと書かれていました。つまり、Storage Error Recovery と Model Stream Retry を Pi 1.3 と 1.4 で比較するのは軸が違います。比較すべきなのは agents@0.29.0 と agents@0.30.x です。 ベンダーの Changelog は、利用者にとって分かりやすい単位で変更をまとめています。一方、障害が起きたときに調べるには、どのパッケージのどの層が責任を持つかを分ける必要があります。 2. Pi、PiHarness、Lifecycleの役割 今回の構成には3つの層があります。 | 層 | 担当 | | --- | --- | | Pi Durable | Agent の実行ループ、タスク、チェックポイント、replay | | PiHarness | Pi に Durable Object の SQLite と起動処理を接続 | | Lifecycle | Durable Object 上で長時間の仕事を実行し、必要なときに起こす | Pi Durable は Cloudflare のパッケージではありません。@earendil-works/pi-durable として提供され、Agents SDK 側の PiHarness が Durable Object に組み込みます。 ここで重要なのは、保存と再開が別の機能だということです。 - 会話履歴やタスクの保存先は、pi_ で始まる SQLite テーブル - 眠っているタスクを再開するのは、Lifecycle の Wake ジョブと Durable Object Alarm 保存できていても、起こす仕組みがなければ再開しません。逆に、再開できてもチェックポイントがなければ、どこから続けるか分かりません。今回の検証では、この2つを混ぜないようにしました。 Pi Durable の設計記事には、次のようにあります。 > every step of a run is a task that stores a checkpoint before it moves on. このチェックポイントが、再起動後に「完了済みのタスクをもう一度実行しない」ための基礎になります。 3. まず、観測そのものを永続化する 障害復旧を測るとき、最初に作るべきなのは実験対象ではなく記録機構です。Durable Object の書き込みは、呼び出した瞬間にすべてがディスクへ確定するわけではありません。 検証用のレコーダは、イベントを SQLite に書いたあと、通常は ctx.storage.sync() を呼ぶようにしました。直後に ctx.abort() を呼び、再起動後にイベントが残っているかを比較します。 | 記録の仕方 | 再起動 | 再起動後に残った行数 | | --- | --- | ---: | | sync() あり | した | 1 | | sync() なし | した | 0 | どちらもコンストラクタで発行したインスタンス ID が変わっていました。本当に同じインスタンスが動き続けたのではなく、再生成後のインスタンスが SQLite を読んでいます。 ctx.abort() は通常の throw とは違います。アプリケーションコードでは catch できず、Durable Object を即座にリセットします。障害注入に通常の例外を使うと、Agent の復旧ではなく「同じインスタンスのエラー処理」を測ってしまいます。 この土台を確認してから、以降のイベントはすべて sync() ありで記録しました。ログに残らなかった観測を、復旧の証拠には使っていません。 4. 会話履歴とタスクは再起動を越えて残る ツールを1回実行する Agent を動かし、処理が完了したあとに ctx.abort() で Durable Object を落としました。再起動後に transcript とイベントを読みます。 | 観測 | 再起動前 | 再起動後 | | --- | ---: | ---: | | インスタンス識別子 | — | 変化した | | transcript のエントリ数 | 5 | 5 | | ツール実行開始 | 1 | 1 | | 副作用 | 1 | 1 | 完了済みのタスクは二重実行されませんでした。同じ operationId を使った submit も、1回目は accepted: true、2回目は accepted: false になりました。異なる ID を使うと accepted: true になるため、submit 全体が壊れたわけではありません。 ここまでは、Pi Durable がチェックポイントと submit の識別子を使って、完了済みの仕事を保護している結果です。 5. クライアントが切れても、Agentは動き続ける 次に、モデルのリトライで処理時間を伸ばし、途中で WebSocket を切断しました。クライアントがいなくなったあとも実行が続くかを確認します。 結果は、最終的に done になりました。モデル呼び出しは「失敗2回、成功1回」の3回です。切断前後でインスタンス IDは変わっていません。 これは「落ちて復旧した」のではありません。Agent の実行がクライアント接続に依存していなかったということです。 再接続後は snapshot から現在の状態を組み立て直せました。ただし、切断中に流れたイベントをカーソルで途中から再生できるわけではありません。イベントストリームは状態を追うためのものではありますが、履歴ストリームの代わりではありません。 6. Parked Tasksはクラッシュループを止める 同じ場所で何度も ctx.abort() を発生させ、restartLimit を2に下げて測りました。 | 落とし方 | 障害発火 | インスタンス生成 | pending() | 次の Alarm | | --- | ---: | ---: | --- | --- | | ctx.abort() | 2 | 2 | parked | なし | | 通常の例外 | 1 | 0 | 空 | なし | 通常の例外は Durable Object をリセットしないため、再起動回数には入りません。Parked に到達するには、実際に再起動される障害が必要です。 Parked になったタスクは、放置しても Durable Object を起こし続けません。手動では2つの抜け方があります。 | 操作 | 戻り値 | wait() | | --- | --- | --- | | session.retry() | true | done | | session.abort() | ok | unanswered / aborted | retry() はやり直す操作、abort() は放棄する操作です。クラッシュループを止めるだけでなく、運用者が判断して再開か放棄かを選べる設計になっています。 なお、ツールが api.output() で進捗を8回出しても、再起動カウントは戻りませんでした。Pi が進捗として扱うのは、ツールの出力ではなく、タスクが次の状態をコミットしたことです。まだ完了していない1つのツールが出力を吐き続けても、クラッシュループの上限はリセットされません。 7. Storage Error Recoveryは「次の操作」から効く Storage Error Recovery は、ストレージエラーが起きたあとに Pi を開き直せる機能です。ここでは Storage を Proxy で包み、次の2種類のエラーを注入しました。 - commit() などから任意のエラーを返す - 読み取りから StorageRequestError を返す どちらも、現在進行中の呼び出しはエラーになりました。しかし、次の submit() は成功し、最終的に done になりました。致命的な Storage エラーでは factory の実行回数が1から2に増えましたが、Durable Object 自体のインスタンス IDは変わっていません。 つまり、これは Durable Object のクラッシュ復旧ではありません。PiHarness が壊れた Pi をキャッシュから外し、次の操作または Wake ジョブの次のステップで Pi を開き直しています。 進行中の呼び出しは救われません。 仕様にも、すでに実行中の呼び出しは SessionFailed で失敗するとあります。factory は何度実行されても正しく初期化できるように書く必要があります。 8. replay: "safe" は副作用を守らない ここが今回の中心です。4種類のツールを用意し、実行開始・副作用の確定・終了を別々に記録しました。副作用確定直後に Durable Object を落とし、再起動後の挙動を比較します。 | ツール | replay | 冪等性 | 実行開始 | 副作用 | 完了 | | --- | --- | --- | ---: | ---: | ---: | | write_record | safe | あり | 2 | 1 | 1 | | bump_unsafe | 未指定 | なし | 1 | 1 | 0 | | bump_safe_unguarded | safe | なし | 2 | 2 | 1 | | bump_safe_guarded | safe | あり | 2 | 1 | 1 | write_record は同じ値を書き込むので、2回実行されても結果は変わりません。bump_safe_unguarded はカウンターを1増やすだけで、実行されるたびに結果が変わります。このツールに safe を付けると、Pi は宣言を信じて再実行し、副作用が2回確定しました。 一方、bump_unsafe は自動再実行されません。副作用確定後に落としたケースでは、副作用は1回だけ残りましたが、ツールは完了していません。Agent は中断されたツール結果をモデルへ渡して run を決着させます。 中断されたツールの transcript は、専用のエントリになるわけではありません。通常と同じ pi.tool-result ですが、内容が次のように変わります。 <harness> [error] Tool bump_unsafe was interrupted and may have partially run </harness> このメッセージは、モデルに「部分的に実行されたかもしれない」と伝える平文です。その後にモデルが同じツールを呼び直すかどうかは、モデルの判断に委ねられます。今回の実モデルによる3試行では呼び直しませんでしたが、1モデル・1プロンプト・3試行だけなので一般化はしません。 bump_safe_guarded には冪等キーを入れました。再実行自体は起きていますが、2回目はキーを見て副作用をスキップし、確定回数は1回に収まりました。 ここから分かることは明確です。safe の判断を間違えても Pi は警告しません。 外部 API、決済、メール送信、データベース更新などをツールに持たせるなら、safe の設定とは別に冪等キーや重複排除を実装する必要があります。 9. Model Stream Retryはエラー文言で判定される Model Stream Retry は、途切れたモデルストリームを一時的なエラーとして扱い、ターン全体を再試行します。配布物を読むと、判定はエラー本文の正規表現でした。 同じ回数だけ失敗させ、エラー文言だけを変えました。 | エラー文言 | 結果 | モデル呼び出し | | --- | --- | ---: | | The stream ended before the model finished its answer. | unanswered | 1 | | The stream ended without the model finishing its answer. | done | 3 | | Model stream stalled: no data received for 60s. | unanswered | 1 | | Model stream timed out: no data received for 60s. | done | 3 | | insufficient_quota: the account has no remaining credit. | unanswered | 1 | 再試行対象の文言では「失敗2回、成功1回」の3回になりました。つまり、再試行は部分的なストリームの続きではなく、モデルリクエスト全体の作り直しです。 baseDelayMs を100秒に設定しても、待機時間の上限は約60秒でした。既定の maxAgentDelayMs が60,000ミリ秒だからです。設定値を大きくしたからといって、無制限に待つわけではありません。 10. Hibernationは、待機中に別インスタンスで再開する Hibernation の測定では、最初に alarm の時刻を比べました。しかし、ローカルの workerd では onWake の有無にかかわらず、alarm の秒数が一致しました。これは測定対象を間違えています。 Hibernation の本質は、alarm の時刻ではなく、待機中に Durable Object がメモリから退避できるかです。そこで実デプロイし、コンストラクタでインスタンス IDを記録して、リトライがどのインスタンスで走るかを見ました。 onWake を渡した場合は、次のようになりました。 model_error@old-instance → instance_started@new-instance → model_request@new-instance onWake を渡さない場合は、次のようになりました。 model_error@same-instance → model_request@same-instance | onWake | リトライを走らせたインスタンス | | --- | --- | | 渡す | 別インスタンス | | 渡さない | 同じインスタンス | リトライ待機中は、測定のために一度もリクエストを送りませんでした。途中で触るとオブジェクトが起きてしまい、退避を観測できないからです。 処理中の work と、リトライ待ちの sleep は別の状態です。work がある間は heartbeat Alarm が30秒ごとに再設定されます。一方、sleep 中は最初に起きるタスクの時刻が次の Alarm になります。この2つを混ぜると、Hibernation の測定結果を誤読します。 11. agents@0.30.0 の不具合を再現する 公式が案内した agents@0.30.0 で検証を始めようとしました。しかし、このバージョンには、別タスクが動いているとリトライ待機中のタスクが起きない既知の不具合があります。 1つの Harness で、次の2本を並行させました。 - セッションA: 60秒走るツールを実行する - セッションB: 再試行対象のエラーを返し、12秒の backoff に入る | | B単独 | 並行する work あり | | --- | ---: | ---: | | agents@0.30.1 | 12秒 | 12秒 | | agents@0.30.0 | 12秒 | 57秒 | 0.30.0 では、B のリトライが A の完了まで止まっていました。0.30.1 では、A が動いていても B は予定どおり12秒後に再開します。 原因は配布物の差分からも確認できます。0.30.0 は Pi が active かどうかだけを見ていました。0.30.1 では、sleep の期限 wake.at を次の待機期限に使い、期限に達したら pi.resume() を呼びます。 これは煽るための話ではありません。PiHarness が Beta と案内されていることの、具体的な例です。Pi 1.4 の Hibernation を検証するなら、agents@0.30.1 以降を使う必要があります。 12. Pi 1.4に上げると、1.3には戻せない Pi 1.4 は session storage の SQLite schema を更新するため、Pi 1.3 へロールバックできません。 実際に Pi 1.4 で1ターン実行したあとの schema version は 2 でした。配布物のマイグレーション定義を比べると、次の差があります。 | バージョン | マイグレーション | | --- | --- | | pi-durable@1.3.0 | version 1 のみ | | pi-durable@1.4.0 | version 1 と version 2 sleepingStatus | Pi 1.3 のマイグレーションランナーは、対応していない新しい schema version を見つけるとエラーにします。追加された sleepingStatus は、Pi 1.4 の Hibernation を支える sleeping タスク状態そのものです。 つまり、Durable Object を退避できるようになったことと、ロールバックできなくなったことは、別々の変更ではありません。同じ schema 変更の表と裏です。 Pi 1.4 と1.3を比較するときは、同じ Durable Object を使い回してはいけません。実験用の名前を分け、マイグレーションを一方向のものとして扱います。 13. 測定をやり直して分かったこと この検証では、最初の測定結果をそのまま記事にしませんでした。対照を組み直した結果、3つの主張を修正または保留にしています。 WebSocketのイベント取りこぼし 最初は、遅いイベントリスナーがイベントを取りこぼすように見えました。しかし、WebSocket を8秒で閉じていたことが原因でした。ドレイン時間を30秒に延ばすと、遅いリスナーでもイベント数は一致しました。 進捗の定義 自前カウンターの更新を Pi の進捗だと思い込んでいました。api.output() を8回呼ぶ対照に変えても、未完了のツールは Parked になりました。ツールの出力ではなく、タスクが状態をコミットしたかどうかが進捗です。 19分のモデルストリーム Worker 内の faux Provider で約19.2分のストリームを流したところ、モデル呼び出し1回のまま完走しました。ただし、これは外部モデル API へのHTTP接続を19分維持した測定ではありません。公式の「15分を越えるリクエストは切断されることがある」という制約を否定する材料にはならないため、結論は保留にしました。 障害復旧の検証では、「結果が出た」だけでは不十分です。そもそも障害が起きていなかった、観測側が先に接続を閉じた、という可能性を対照で潰す必要があります。 14. まとめ Cloudflare Agents と Pi 1.4 の復旧機構は、実際に動きました。会話履歴は再起動後に読み戻せ、完了済みタスクは二重実行されず、クラッシュループは Parked Tasks で止まり、リトライ待機中の Agent は Hibernation によって別インスタンスで再開できました。 しかし、Pi が守っているのは Agent の実行状態です。あなたの外部副作用まで自動的に exactly-once にしてくれるわけではありません。 実装時には、次の点を守る必要があります。 - 外部操作には冪等キーや重複排除を入れる - replay: "safe" は、2回実行しても安全だと自分で証明できるツールだけに付ける - unsafe にしても、確定済みの副作用が消えるわけではない - factory は Storage Error Recovery で何度も呼ばれる前提で書く - Hibernation を使うなら agents@0.30.1 以降を使う - Pi 1.4 に上げた Durable Object は、Pi 1.3 に戻せない 最後に、検証から持ち帰る教訓を1つに絞るならこれです。 「復旧した」と「重複せずに完了した」は、別の主張です。 参考 - Cloudflare Changelog — Agents SDK now supports the latest Pi 1.4 release — Pi 1.4 対応として発表された4項目 - Cloudflare Docs — Pi — PiHarness、Recovery、Hibernation の公式ドキュメント - Cloudflare Docs — Pi Extensions — ツールの replay 設定と復旧時の扱い - agents CHANGELOG — 0.30.0 / 0.30.1 の変更 - cloudflare/agents#2683 — onWake と並行タスクに関する既知の不具合 - pi-durable CHANGELOG 1.4.0 — Pi 1.4 の sleeping タスクと schema migration - Pi Durable の設計記事 — チェックポイントとタスク実行の設計

  5. *Looks even further* Oh they also explicitly violated the BSD3 licence of boringtun by copy-pasting original source without attribution, and even explicitly deleted copyright notices in files to hide it. github.com/firezone/sanstun/blob/main/src/handsha… github.com/cloudflare/boringtun/blob/master/borin… Cool cool. Fuck this guy.

    7 likes
  6. Reddit · · r/BestGitHubRepos · u/company_url_finder · cloudflare/skills

    Cloudflare Skills: Skills for teaching agents how to build on Cloudflare (3.2k stars) What it does All text below is quoted directly from the project README. >Skills for teaching agents how to build on Cloudflare. Skills: - cloudflare: Helps agents discover which Cloudflare products fit their needs, then find the right skills and docs - agents-sdk: Building stateful AI agents with state, scheduling, RPC, MCP servers, email, and streaming chat - durable-objects: Stateful coordination (chat rooms, games, booking), RPC, SQLite, alarms, WebSockets - wrangler: Deploying and managing Workers, KV, R2, D1, Vectorize, Queues, Workflows - workers-best-practices: Writing, reviewing, or configuring production Workers - web-perf: Auditing Core Web Vitals (FCP, LCP, TBT, CLS), render-blocking resources, network chains >npx skills add https://github.com/cloudflare/skills Repository cloudflare/skills Repository stats |Metric|Value| |:-|:-| |Stars|3,200| |Forks|328| |Last release|None| |Languages|Shell 88.3%, Python 11.7%| |Contributors|46| |AI contributor accounts (Claude / Codex / Cursor / Copilot)|@claude (4 commits), @cursoragent (1 commits)| |AI co-authored commits|Claude: 4| Main contributor |Field|Value| |:-|:-| |Name|Brendan Irvine-Broque| |GitHub|@irvinebroque| |Commits to this repo|20 (top contributor)| |Bio|sr. director of product, workers @cloudflare| |Company / Location|San Francisco, CA| |Followers|281| ────────────────────────────── 📌 How many great GitHub repos have you discovered and completely forgotten about? Don't let another useful tool disappear into your Reddit feed. Get the community's best repos, organized by category, plus key takeaways from real developer discussions, delivered to your inbox twice a week. 📬 Never lose track of great repos again. Subscribe free.

    5 points
  7. How to Install OpenClaw on Mac Mini and OpenClaw on Cloudflare (Step by Step) OpenClaw on Mac Mini and OpenClaw on Cloudflare represent two practical approaches to running a powerful, self-hosted personal AI agent that performs real-world tasks autonomously. OpenClaw functions as an open-source runtime for AI assistants. It connects large language models primarily Anthropic's Claude to local files, system commands, external APIs, and messaging platforms. The agent handles actions such as processing emails, updating calendars, conducting research, automating workflows, and maintaining persistent memory across interactions. Users communicate with it through apps like WhatsApp, Telegram, or Discord, and it executes tasks with high autonomy when configured appropriately. {% cta apidog.com %} Try Apidog today {% endcta %} 💡For developers extending OpenClaw—especially messaging endpoints and tool-calling APIs— Apidog is an invaluable tool. It supports API design, mocking, testing, debugging, and documentation in one place. With Apidog, you can test OpenClaw routes, validate request and response payloads, and ensure smooth integrations throughout the configuration process. What is OpenClaw? Technical Overview OpenClaw (formerly Clawdbot and Moltbot) is a conversation‑first, self‑hosted AI agent framework. !Image Developers install it on local hardware or cloud infrastructure to create a persistent AI assistant. The core runtime bridges: - A large language model backend (Claude) - Executable tools and skills - File system access - Messaging and communication channels Natural‑language instructions can trigger complex, multi‑step actions such as: - Code execution - Browser automation - API orchestration - Cross‑service integrations OpenClaw is open source and actively developed on GitHub. Its philosophy is local‑first execution, prioritizing: - Privacy - Low latency - Full customization You can install OpenClaw on a Mac Mini for total hardware control or deploy OpenClaw on Cloudflare for serverless, edge‑optimized execution. How to Install OpenClaw on Mac Mini (Local Setup) 1. Prepare the Mac Mini Set up a dedicated Mac Mini for OpenClaw (not your personal machine): # Create a fresh Apple ID to avoid iCloud syncing personal data # Connect via Ethernet for stable networking 2. Configure Power Settings Keep machine always running: # System Settings → Battery / Energy Saver # Disable sleep modes # Enable automatic restart after power failure # Install Amphetamine (App Store) for always-on enforcement 3. Install Dependencies Install necessary tools: # Homebrew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # Node.js brew install node 4. Install OpenClaw CLI Install the global package: npm install -g clawdbot 5. Configure API Keys Set up authentication: clawdbot onboard # Provide Anthropic API key from console.anthropic.com 6. Set Up WhatsApp Channel Connect messaging: clawdbot channels login --channel whatsapp # Scan QR with WhatsApp Business (separate phone required) 7. Start Gateway Keep agent listening: clawdbot gateway start 8. Harden Setup Ensure reliability: # Configure auto-launch using macOS LaunchAgents # Enable Screen Sharing for remote management # Install Tailscale for secure VPN access How to Install OpenClaw on Cloudflare (MoltWorker) 1. Prerequisites - Cloudflare Workers paid plan - Access to Workers, Sandboxes, Containers, and R2 !Image 2. Create Cloudflare Services # Set up: # - AI Gateway with Anthropic provider # - R2 bucket for storage # - Browser Rendering API # - Zero Trust policies 3. Clone Repository git clone https://github.com/cloudflare/moltworker.git cd moltworker npm install 4. Configure Wrangler Add to wrangler.toml: [[r2_buckets]] binding = "MOLT_R2" bucket_name = "your-openclaw-r2-bucket" [sandbox] binding = "SANDBOX" 5. Set Environment Variables export ANTHROPIC_BASE_URL="https://your-ai-gateway.cloudflare.com/anthropic" export MOLTBOT_GATEWAY_TOKEN=$(openssl rand -hex 32) 6. Deploy npx wrangler deploy Integrating OpenClaw with Apidog Apidog enhances OpenClaw development by: - Designing custom tool schemas - Testing webhook endpoints (WhatsApp/Telegram/Discord) - Mocking third-party APIs - Validating Claude tool-calling payloads !Apidog Integration testing interface Example workflow: 1. Design API in Apidog 2. Generate mock endpoint 3. Connect to OpenClaw tool registry 4. Validate responses before production // Example tool schema { "name": "send_email", "description": "Send email via SMTP", "parameters": { "to": "string", "subject": "string", "body": "string" } } Choose your deployment based on needs: - Mac Mini for hardware control - Cloudflare for serverless scale

  8. If you are a vibe coder like me. Use this cloudflare auditing skill to audit your web application cloudflare/security-audit-skill #AI #vibecoding You do not know what you do not know. Knowing security and this recipe will help you harden your app.

    6 likes · 1 repost
  9. Reddit · · r/RepoQuarry · u/Obiwayneone · cloudflare/security-audit-skill

    Cloudflare’s free Security Audit skill: fresh agents challenge each finding. Would you trust the report? I’m Obi, the builder of RepoQuarry. Sky breaks down Cloudflare’s Security Audit skill in this one-minute video. Sky is an AI-generated presenter. The interesting part is the verification: separate agents hunt for issues, then fresh verifiers try to disprove each candidate. It is MIT licensed, but the coding agent/model may cost money. The limits matter: this is an on-demand audit of one repo, not ongoing dependency, container or CI monitoring. We reviewed the documentation; we haven’t run the skill ourselves. Stars show popularity, not security assurance. Dashed historical chart points in the video are estimates. Credit to Cloudflare and contributors: cloudflare/security-audit-skill RepoQuarry breakdown and sources: repoquarry.dev What would you want to see in a finding before spending time fixing it: a source trace, a reproducer, or an independent review? reddit.com

    1 point · 2 comments
  10. @samgoodwin89 we're working on merging it into workerd - still very much in progress - but you can see some of it here: github.com/cloudflare/workerd/commit/aa494794c44a… For celld we'll might do some more bug fixes, but the next major release of celld will be workerd

    103 likes · 3 reposts · 2,897 views
Trending awards, every completed day and week
Gold
121st place finishes
Silver
112nd place finishes
Bronze
113rd place finishes
Awarded repositories
11Owned by cloudflare now

Repositories

Ordered by gold, then silver, then bronze.

  1. pingoraBest: 1st by stars, 11,440 stars513
  2. workerdBest: 1st by stars, 3,231 stars500
  3. security-audit-skillBest: 1st by stars, 3,617 stars131
  4. cloudflare-osBest: 1st by stars, 7 stars101
  5. moltworkerBest: 2nd by stars, 656 stars022
  6. computerBest: 2nd by stars, 16 stars020
  7. hellogopherBest: 2nd by stars, 352 stars011
  8. miniflareBest: 2nd by stars, 419 stars010
  9. vinextBest: 2nd by stars, 600 stars010
  10. flanBest: 3rd by stars, 586 stars002
  11. gokeyBest: 3rd by stars, 412 stars001

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.