Scope and evidence

Source review
Cloud scope
Cloudflare
Availability
Beta
Exercise status
Exercises not run

Conditions and limits

  • PiHarness is Beta; Pi Durable is experimental and the integration API may change.
  • Reconnect begins from a snapshot without an event cursor. Tool approval and permission steps are not built in; replay safety does not guarantee external exactly-once effects.
  • Region, plan, account, dependency version and model eligibility have not been verified in a deployed test environment.

What should survive a closed tab?

Imagine a research assistant comparing three public documents. You send the documents, close your phone, and return a few minutes later. The application must answer three questions: was the request accepted, what work remains, and where is the completed memo? A WebSocket connection alone cannot answer them.

Use three identities in this original design exercise:

Identity Owner and lifetime Example and consequence
Connection Temporary delivery path for one browser A replacement socket gets a new identity. Its loss does not mean “cancel the memo.”
Conversation Application-owned context and authorization boundary comparison-17 belongs to one authenticated owner. A guessed identifier must not reveal its transcript.
Operation One accepted request, reused on retries memo-42 identifies this comparison. A new comparison needs a new operation ID.

The identifiers above are synthetic. They illustrate responsibilities rather than a complete API or deployed service. Keep a separate UI indicator for connection status and operation status: “reconnecting” can coexist with “work accepted.”

Put state ownership before model selection

Cloudflare introduced the PiHarness integration on October 2, 2026. PiHarness is Beta, and the underlying Pi Durable package is experimental. Pi runs the model/tool loop; PiHarness connects that work to Durable Object storage and wake-ups. It leaves the transport to the application. This availability check was performed on October 4; it is not evidence that a particular account, model, or environment has been tested.

The storage part has a longer history. Cloudflare's September 26, 2024 SQLite announcement introduced embedded SQL storage for Durable Objects. Earendil's October 1, 2026 announcement adds durable agent tasks and their checkpoints. Stored conversation state and a runnable task are related, but they need different recovery checks.

Scroll horizontally to read the diagram.

Original conceptual diagram: a browser sends a stable operation through an authenticated Worker to a conversation Object; PiHarness owns execution and SQLite state, while reconnects receive a fresh snapshot

Original Kumyu schematic, based on the cited integration and Durable Object docs. The arrows show application responsibilities, not measured timing or an internal product diagram. Follow the numbered path below if reading on a narrow screen.

  1. The browser sends a request and stable operation ID.
  2. The entry Worker validates input and checks the authenticated owner's access to the conversation.
  3. The conversation Object owns accepted work and recoverable state.
  4. The model and permitted tools work within that application's authority.
  5. A returning browser replaces its display from current state, then follows new events.

This placement follows the Durable Object design guide: choose a small unit of coordination and route requests to it. Here the unit is one conversation. A single Object for all users would combine unrelated work and permissions into one bottleneck. Multiple Objects also create an explicit cost and lifecycle inventory, so the boundary should follow real ownership rather than every browser reconnect.

Acknowledgement and display have different contracts

The Pi API documentation states that submit() persists the input before returning a receipt. Reusing operationId returns the same operation with accepted: false. Its event stream starts with a snapshot and follows new events; it has no cursor-based resume. After an Object restart, open a new stream.

For the memo application, record the receipt independently of an optimistic “sent” bubble. If the response is lost, retry the same logical submission, then reconcile the returned operation. Scope the ID to the authorized conversation. Decide how your application rejects the same ID paired with different input; the example is a proposed application rule, not a documented Pi validation result.

On reconnect, replace the view model from the snapshot before applying subsequent events. Appending a new partial answer to the stale partial answer can duplicate paragraphs. An operation ID supports reconciliation, but it does not turn transport events into a durable delivery log.

Read settings as changes to behavior

The table combines documented API semantics with proposed values for our memo fixture. It is not a tested configuration. PiHarness options and session methods and Pi extensions are the technical references.

Setting or input Scope and meaning Choice for the memo fixture; what it changes
durable_objects.bindings and migrations.new_sqlite_classes Deployment: name the bound SQLite Object class Match the Assistant binding and class. A migration is a storage contract, not a disposable browser setting.
defaults.model Initial model for a new session Select an available model deliberately; leaving it unset gives unanswered prompts. Check model eligibility and charges separately.
operationId Stable submission identity Reuse memo-42 only for retries of this request; retain the receipt across reconnects.
replay: "safe" Tool recovery after interruption; default is "unsafe" Use it for a deterministic count over fixed input. The second execution must be harmless.
static options = { hibernate: false } Agent-class opt-out from default hibernation Leave the default unless a specific requirement justifies keeping idle Objects active. This does not choose which conversation data is saved.

Pi's session identifiers are harness-owned. The session docs recommend a conversation Object with its root session for a separate user/chat. Keep the application's owner-to-conversation mapping outside client authority; do not use a browser-supplied Object name as an authorization decision.

Replay safety is a property of the operation

Pi extensions define the recovery distinction: a safe interrupted tool runs again; an unsafe interrupted tool does not automatically replay, and the model receives an interrupted result. That controls recovery of the interrupted call. A later model decision can still propose another call.

For this fixture, a word count over an immutable supplied string is straightforward to repeat. Fetching a changing page may be harmless to the remote server, yet its answer may differ; store the retrieved document identity if reproducible comparison matters. Sending a memo by email, incrementing a balance, or charging a card needs a separate side-effect contract. Ask the destination to recognize a stable idempotency key, persist intent and outcome, and reconcile an unknown result before retrying. These are application design requirements, not an exactly-once promise from the harness.

The Pi limitations say that tool approvals and permissions are not built in. Do not make a system prompt the only guard. This exercise registers only deterministic calculation and bounded reads. If your application needs approval, put its authoritative decision in trusted application state before exposing the permitted action.

When a tool also needs a shell or files, use the Sandbox execution-state chapter to identify the execution environment's owner. A conversation checkpoint and a container filesystem snapshot recover different state. Coordinate their identities rather than assuming that restoring one restores the other.

Idle sockets, active work, and workflows

Agents WebSockets enable hibernation by default. Durable state survives; arbitrary class variables, timers, and in-flight promises do not. The lower-level WebSocket hibernation guide explains that clients can stay connected while the Object leaves memory. An idle connection therefore need not keep compute active. That says nothing about making an actively streaming model call idle.

Choose the execution owner from the work you need to inspect:

Work Useful starting point Tradeoff to review
A short independent transformation Plain Worker Small surface; the request does not establish a durable job contract.
A conversation choosing its next bounded read Agent with a per-conversation Object Persist context and reconnect state; keep permissions and recovery policies explicit.
Fetch → validate → wait for approval → distribute Agent plus Workflow Reviewable stages and waits, with more state and operational ownership.

The Agents and Workflows guide supports durable steps and external waits alongside real-time communication. A completed step and an external side effect are separate facts: a request that succeeded remotely but lost its response still requires destination-side reconciliation. Adding a Workflow cannot remove that uncertainty by itself.

The Pi documentation also limits one model request that streams for longer than 15 minutes: it can be cut off. Splitting a large comparison into bounded source reviews is a proposed way to reduce retry scope; it is not a benchmark or a guarantee of completion within a time limit.

Budget and observe each layer

Durable Objects pricing was checked on October 4, 2026. Billing includes requests, active duration, and storage. Incoming WebSocket messages use a 20:1 compute-request billing ratio; connection establishment and alarms also matter. Model usage and observability are separate costs. No deployment or invoice was measured for this article.

For a pilot, collect a small worksheet rather than predicting a total from socket count:

Record What it helps you decide
Accepted operations and retry attempts Whether client retries create redundant work
Active duration and time eligible for hibernation Whether idle transport or actual work dominates
Model input/output usage and repeated model calls The cost of recovery and oversized prompts
SQLite writes and retained data Whether saving every display fragment adds useful recovery precision
Failure-to-recovery time and unknown outcomes Whether the service satisfies its own recovery target

Agent tracing distinguishes integration-specific instrumentation and warns that traces are not a lossless conversation record. Verify Pi-specific spans in your environment instead of assuming they appear automatically. Begin with synthetic IDs and state transitions; do not enable payload recording simply to make a dashboard look complete.

Unrun lab: close, retry, restart, interrupt

This is a verification plan that has not been executed. No Cloudflare project, token, model call, or paid experiment was created. Use synthetic text and a local mock side-effect sink before trying a separately authorized test environment. Pin the actual dependency versions in that environment's lockfile; the Beta integration may change.

Define the output as one receipt, one coherent view of progress, and one final comparison memo. Then fill all four rows with expectation, observation, discrepancy, and cause:

Fault to inject Acceptance criterion Evidence to retain
Close the client before completion; reopen it The fresh snapshot shows one consistent in-progress or completed operation Operation ID, screenshots before/after, state transitions
Submit the same ID twice One logical submission; duplicate admission is detectable Both receipts and the operation listing
Restart the test environment during work Recovery refers to the accepted operation and shows the actual repeated work Restart time, recovery time, model-call count
Interrupt an unsafe mock tool No automatic replay of that interrupted call; inspect any new model-proposed call separately Mock sink invocations, tool identity, reconciliation state

Stop when an external result is unknown, the declared test budget is exceeded, or an unexpected tool appears. Record the missing evidence rather than converting the plan into a success claim. After the four rows, explain which state belongs to transport, which belongs to the conversation, and which proves the result of the operation. That explanation is the mental model to carry into a different SDK.

MENTAL MODEL / REASONING ORDER

From an announcement to your own decision.

Primary sources

Compare the announcement with the conditions in the paper and official documentation.

Sources

Publication dates belong to the source; access dates record when it was checked. Community observations are separate from official statements.

01
Official documentationCloudflare: Run the Pi Durable harness on Cloudflare with the Agents SDK ↗developers.cloudflare.comPublished: 2026-10-02 · Accessed: 2026-10-04
02
Official documentationCloudflare: Pi harness ↗developers.cloudflare.comPublished: Unknown · Accessed: 2026-10-04
03
Official documentationCloudflare: Pi extensions ↗developers.cloudflare.comPublished: Unknown · Accessed: 2026-10-04
04
Official documentationCloudflare: Rules of Durable Objects ↗developers.cloudflare.comPublished: Unknown · Accessed: 2026-10-04
05
Official documentationCloudflare: Agents WebSockets ↗developers.cloudflare.comPublished: Unknown · Accessed: 2026-10-04
06
Official documentationCloudflare: Durable Objects WebSockets ↗developers.cloudflare.comPublished: Unknown · Accessed: 2026-10-04
07
Official documentationCloudflare: Using Agents with Workflows ↗developers.cloudflare.comPublished: Unknown · Accessed: 2026-10-04
08
Official documentationCloudflare: Durable Objects pricing ↗developers.cloudflare.comPublished: Unknown · Accessed: 2026-10-04
09
Official documentationCloudflare: Agent tracing ↗developers.cloudflare.comPublished: Unknown · Accessed: 2026-10-04
10
Official blogCloudflare: Zero-latency SQLite storage in every Durable Object ↗blog.cloudflare.comPublished: 2024-09-26 · Accessed: 2026-10-04
11
Official blogEarendil: Pi Durable ↗earendil.comPublished: 2026-10-01 · Accessed: 2026-10-04
Saved in this browser only.