対象と根拠
- 情報確認日
- 対象クラウド
- Cloudflare
- 提供状態
- Beta
- 演習の実施状況
- 演習は未実施
条件・制約
- PiHarnessはBeta。Pi Durableも実験的であり、統合APIは変わり得る。
- 再接続はevent cursorを使わずsnapshotから始まる。ツールの承認・権限段階は組み込まれておらず、replayの安全性は外部副作用が1回だけである保証ではない。
- region、plan、account、依存バージョン、モデルの利用条件は、デプロイした検証環境で確認していない。
タブを閉じた後に何を残すか
公開資料3件を比べて、比較メモを作る調査エージェントを考えよう。利用者は資料を送った後にスマートフォンを閉じ、数分後に戻る。画面が答えるべき問いは、依頼が受理されたか、残りの作業は何か、完成したメモはどこか、の3つだ。WebSocketの接続だけを管理しても、この問いには答えられない。
この教材の自作例では、次の3つの識別子を分ける。
| 識別子 | 所有者と寿命 | 例と、設計への影響 |
|---|---|---|
| 接続 | 1つのブラウザーに対する一時的な配送経路 | 接続し直せば識別子は変わる。切断を「メモ作成の中止」と同一視しない。 |
| 会話 | アプリが管理する文脈と権限の境界 | comparison-17 は認証済みの所有者に属する。IDを推測できても履歴を読ませない。 |
| 操作 | 1回の受理済み依頼。再送では同じIDを使う | memo-42 は今回の比較を表す。別の比較には別の操作IDを発行する。 |
これらのIDは架空の演習用データであり、完成したAPIや稼働中のサービスではない。画面にも接続状態と操作状態を別々に出す。「再接続中」でありながら、「依頼は受理済み」である状態を表現できるようにする。
モデルを選ぶ前に、状態の所有者を決める
Cloudflareは2026年10月2日にPiHarnessの統合を発表した。PiHarnessはBetaであり、基盤となるPi Durableも実験的なパッケージだ。Piがモデルとツールを回す処理を担当し、PiHarnessがその仕事をDurable Objectの保存と起動の仕組みにつなぐ。通信方法はアプリ側が選ぶ。ここでの提供状態は10月4日の資料確認に基づき、特定のアカウント、モデル、実行環境で動作確認した結果ではない。
保存の仕組みには前史がある。Cloudflareの2024年9月26日のSQLite発表は、Durable Objectに組み込まれたSQL保存を導入した。Earendilによる2026年10月1日の発表では、エージェントの仕事と保存点からの復旧を説明している。会話の保存と、仕事を再開する仕組みは関連するが、復旧時に確かめる項目は異なる。
図を横にスクロールして読む。
Kumyuが独自に作成した概念図。根拠は統合とDurable Objectの公式資料。矢印はアプリの責務を示し、計測時間や製品内部の図を表すものではない。画面が狭い場合は、以下の番号付きフローでも追える。
- ブラウザーは依頼と安定した操作IDを送る。
- 入口Workerは入力を検証し、認証済みの所有者がその会話へアクセスできるかを確認する。
- 会話のObjectは受理した仕事と復旧に必要な状態を所有する。
- モデルと許可されたツールは、そのアプリの権限の範囲で処理する。
- 戻ってきたブラウザーは現時点の状態から表示を置き換え、その後のイベントを反映する。
この配置は、Durable Objectの設計ガイドにある、協調が必要な小さな単位を選んでそこへ配送する考え方に沿う。この例での単位は1つの会話だ。全利用者を1つのObjectへ集めると、無関係な仕事と権限が同じボトルネックに入る。一方、Objectを分ければ費用と寿命を管理する対象も増える。接続のたびに作るのではなく、実際の所有範囲に合わせよう。
受理の確認と、画面の復元を分ける
PiのAPI資料では、submit() は入力を保存してから受理票を返す。同じ operationId を再送すると、同じ操作に対して accepted: false が返る。イベント配信はsnapshotから始まり、その後に新しいイベントが続く。カーソルを指定した途中再開はない。Objectが再起動した後は、新しいstreamを開く。
比較メモのアプリでは、楽観的に出す「送信済み」の吹き出しと、受理票を分けて管理する。応答を受け取れなければ、同じ論理依頼を再送して返された操作と照合する。IDの範囲は権限確認済みの会話に結び付ける。同じIDに異なる入力が来たときにどう拒否するかも決める。これはアプリ側に提案する規則であり、Piがその入力違いを検証するという確認結果ではない。
再接続した画面はsnapshotからview modelを置き換え、その後のイベントを適用する。残っていた未完成の回答に、新しい未完成の回答を追記すると、段落を二重に出しやすい。操作IDは照合に使えるが、通信イベントそのものを永続的な配送記録に変えるわけではない。
設定を、動作への影響として読む
表は、資料に記されたAPIの意味と、この比較メモに提案する値を並べたものだ。動作検証済みの設定ではない。技術的な参照先はPiHarnessのオプションとsessionメソッド、Pi extensionsである。
| 設定・入力 | 範囲と意味 | 比較メモでの選択と、その影響 |
|---|---|---|
durable_objects.bindings と migrations.new_sqlite_classes |
デプロイ単位。SQLite Objectのクラスをbindingに対応させる | Assistant のbindingとクラスを一致させる。migrationは保存先の契約であり、使い捨てのブラウザー設定ではない。 |
defaults.model |
新しいsessionの初期モデル | 利用できるモデルを明示して選ぶ。未設定ではpromptがunansweredになる。モデルの利用条件と料金は別に確認する。 |
operationId |
安定した依頼の識別子 | memo-42 は今回の依頼の再送だけに使い、再接続をまたいで受理票を保持する。 |
replay: "safe" |
中断後のツール復旧。既定は "unsafe" |
固定入力を決定的に集計するツールに使う。2回目の実行が害を生まないことが条件になる。 |
static options = { hibernate: false } |
Agentクラス単位。既定のhibernationを無効にする | アイドル中も稼働させる具体的な必要がなければ既定のままにする。この設定は会話の何を保存するかを決めない。 |
Piのsession IDはharnessが管理する。sessionの資料は、利用者やチャットを分ける場合、会話のObjectごとにroot sessionを使う構成を示している。アプリの所有者と会話の対応は、クライアントが勝手に決められないようにする。ブラウザーから届いたObject名だけで権限を判断してはいけない。
再実行の安全性は、その操作の性質で決まる
Pi extensionsは復旧の違いを定めている。safeの中断ツールは再実行する。unsafeの中断ツールは自動再実行せず、モデルに中断結果を渡す。この設定が制御するのは、中断した呼び出しの復旧だ。その後にモデルが別の呼び出しを提案する可能性は残る。
固定された文字列の単語数を数える処理は、この例では繰り返しやすい。変わり続けるページの取得は相手への副作用がなくても、答えが変わることがある。比較を再現したいなら、取得した資料の識別情報を残そう。一方、メモのメール送信、残高の加算、カードへの課金には、別の副作用の契約が必要になる。送信先に安定したidempotency keyを認識させ、実行する意図と結果を保存し、結果が不明なら再送前に照合する。これらはアプリ側の設計要件であり、harnessが外部処理を1回だけにするという保証ではない。
Piの制約には、ツールの承認・権限段階が組み込まれていないとある。system promptだけに防御を任せない。この演習で登録するのは、決定的な計算と範囲を限定した読み取りだけだ。承認が必要なアプリでは、許可された操作を使えるようにする前に、信頼できるアプリの状態へ承認結果を記録する。
ツールがshellやファイルも必要とする場合は、Sandboxの実行状態を扱う章で、実行環境の所有者を整理しよう。会話の保存点と、コンテナのfilesystem snapshotは、復旧する状態が異なる。それぞれの識別情報を対応させ、一方を戻せばもう一方も戻ると考えない。
アイドル接続、実行中の仕事、Workflow
AgentsのWebSocketは、既定でhibernationを有効にする。永続状態は残るが、通常のクラス変数、timer、処理中のpromiseは残らない。低レベルのWebSocket hibernationガイドは、Objectがメモリから離れてもクライアントの接続を保てることを説明している。アイドル接続のためだけにcomputeを稼働させ続ける必要はない。ただし、実行中のモデルstreamをアイドル状態にできるという意味ではない。
処理の所有者は、後から確認したい仕事の形から選ぶ。
| 仕事 | 出発点にできる構成 | 確認するトレードオフ |
|---|---|---|
| 短い独立した変換 | 通常のWorker | 対象が小さい。ただし、requestを受けただけで永続jobの契約にはならない。 |
| 会話を見て次の読み取り先を選ぶ | 会話ごとのObjectを持つAgent | 文脈と再接続状態を保存し、権限と復旧方針を明示する。 |
| 取得 → 検証 → 承認待ち → 配布 | AgentとWorkflow | 段階と待機を確認しやすいが、管理する状態と運用責務が増える。 |
AgentsとWorkflowsの資料は、リアルタイム通信と、永続的なstepや外部イベント待機を組み合わせる構成を扱う。完了したstepと外部副作用は別の事実だ。相手では処理が成功し、応答だけを失ったrequestには、送信先での結果照合が必要になる。Workflowを追加しただけでは、その不確実性を解消できない。
Piの資料には、1回のモデルrequestのstreamが15分を超えると切断され得るという制約もある。大きな比較を資料ごとの小さなレビューへ分ければ、再試行範囲を小さくする設計にできる。ただし、ここで示したのは設計案であり、計測結果や制限時間内の完了保証ではない。
費用と観測も層ごとに分ける
Durable Objectsの料金は2026年10月4日に確認した。request、稼働時間、保存が課金対象になる。WebSocketの受信messageには、compute request課金で20対1の比率が使われるが、接続開始とalarmも含めて考える。モデルの使用量とobservabilityの費用は別だ。この教材ではデプロイも請求額の計測も行っていない。
試行時は、socket数から総額を予想する前に、小さな記録表を作る。
| 記録する値 | 判断できること |
|---|---|
| 受理した操作と再試行の回数 | クライアントの再送が無駄な仕事を増やしていないか |
| 稼働時間とhibernation可能だった時間 | アイドル通信と実際の仕事のどちらが支配的か |
| モデルの入力・出力使用量と再呼び出し | 復旧と大きすぎるpromptの費用 |
| SQLiteの書き込みと保持データ | 表示断片をすべて保存することが、復旧精度をどこまで改善するか |
| 故障から復旧までの時間と結果不明の操作 | 自分たちの復旧目標を満たしているか |
Agent tracingの資料は、統合方法ごとの計装を区別し、traceを会話の完全な記録と扱わないよう説明している。Pi固有のspanが環境で出るかを確認し、自動表示されると決めつけない。まず架空のIDと状態遷移を記録する。ダッシュボードを埋めるためだけに、本文やツール引数の保存を有効にしない。
未実施の演習: 切断、再送、再起動、中断
以下はまだ実施していない検証計画だ。Cloudflareのプロジェクト、token、モデル呼び出し、課金が発生する実験は作成していない。別途許可された検証環境を使う前に、架空の短いテキストとローカルの模擬送信先を用意する。その環境で解決した依存バージョンをlockfileに固定する。Betaの統合APIは変わり得る。
出力は1つの受理票、整合した進行状況の表示、1つの完成した比較メモに定める。次の4行に、期待、観測、差分、原因を記入しよう。
| 加える故障 | 合格条件 | 残す証拠 |
|---|---|---|
| 完了前にクライアントを閉じ、開き直す | 新しいsnapshotが、1つの実行中または完了した操作を整合して示す | 操作ID、前後の画面、状態遷移 |
| 同じIDを2回送る | 1つの論理依頼として関連付け、重複受理を検知できる | 両方の受理票と操作一覧 |
| 実行中に検証環境を再起動する | 復旧が受理済みの操作を参照し、実際に繰り返した仕事を確認できる | 再起動時刻、復旧時刻、モデル呼び出し回数 |
| unsafeの模擬ツールを中断する | 中断した呼び出しは自動再実行されない。モデルが新たに提案した呼び出しは別に確認する | 模擬送信先への呼び出し、ツールの識別情報、照合状態 |
外部処理の結果が不明になったとき、宣言した検証予算を超えたとき、予期しないツールが現れたときは停止する。足りない証拠を記録し、検証計画を成功結果へ書き換えない。4行を埋めたら、通信が持つ状態、会話が持つ状態、操作の結果を証明する状態を説明してみよう。その区別を理解すれば、別のSDKを使うときにも復旧の設計を考えられる。
MENTAL MODEL / 考える順序
発表から、自分の判断へ。
発表の主張と、論文・公式ドキュメントの条件を並べて読む。
出典
公開日は資料の日付、確認日は内容を参照した日です。コミュニティの観測は公式の確定事項と区別します。
01