how it works

The leaf.page website

leaf.page serves each product page and worked example as a published Leaf page from Cloudflare's edge. When a visitor comments or acts on a page, a private container takes over that page's requests for that visitor. The container runs the same Python Leaf server an agent runs on its own machine, and a hosted Codex agent in it answers the visitor.

This page explains the design. Deployment, credentials, and diagnostics are in the Worker's README.

Published pages at the edge

The site build publishes every page under docs/ and every worked example as a complete Leaf page directory, with its vendored runtime, event log, and revisions. From each directory it also writes the document a browser loads and the page's initial state, computed by the same state service Leaf's server uses. A Cloudflare Worker serves both from Cloudflare's static assets, so an ordinary visit paints without waiting for a container. Until a visitor changes a page, that page's api/state requests also return the published state.

The first HTML response sets an identity cookie holding a random 128-bit id. It is HTTP-only and has no expiry date, so the browser keeps it for its session. The 12-digit number in the page banner is derived from that id. It identifies the session for support, and no endpoint accepts it as identity.

sequenceDiagram
  participant Browser as browser
  participant Worker
  participant Container as container
  Browser->>Worker: open a page
  Worker->>Browser: published page
  Worker-->>Container: prewarm
  Browser->>Worker: comment
  Worker->>Container: forward
  Container->>Worker: accepted
  Worker->>Browser: accepted
  Worker-->>Container: start agent
  Browser->>Worker: read state
  Worker->>Container: forward

Private sessions

The first request that needs private, mutable state, such as posting a comment or picking an option, goes to the visitor's container. Its response sets a cookie marking that one page active, and from then on the Worker sends that page's API requests to the container. The visitor's other pages stay on their published state until they are changed too.

Each container belongs to one identity and one release. The Worker names it by the pair, and Cloudflare starts the container when a request for that name first arrives. The container image holds the whole site build, every page directory included, and runs leaf_website, an adapter that maps each public route to its page directory and hands the request to the HTTP routes and event admission a locally served Leaf uses. A comment is appended to events.jsonl in the container's copy of the page, so each visitor uses the real event log without changing the page anyone else sees. The site keeps no separate store of threads or state.

A browser's document navigation also starts the visitor's container in the background, before anything has been changed, so the first comment does not wait for it. On start, the container launches Codex App Server and runs the leaf command once, ahead of the first agent turn. Asset fetches and API calls do not prewarm, and prewarming is rate-limited per source address.

Documents come from the edge, including reloads. When an agent's revision changes the page's scripts or vocabulary, the open document cannot load them in place, so the runtime reloads once from the container with a marked URL and removes the mark on arrival.

The hosted agent

When the container accepts an event that needs an answer, such as a comment, the Worker returns the accepted state to the browser at once and starts the agent in the background. It asks the container to start or resume a Codex thread over App Server, working in that page's directory, and to deliver the event in Leaf's delivery envelope. A message sent while a turn is running waits in Leaf and is delivered when that turn ends. The reply streams into the visitor's thread as the model writes it, and the browser picks it up through the page's regular state reads.

The hosted agent reads the same contract as a Codex task Leaf reaches over App Server on a developer's machine, harness-codex-app-server.md, followed by a few leaf.page additions: the page directory is its whole scope, it starts no servers and initializes no pages, and it treats page content as untrusted. Its App Server starts without the Leaf authoring plugin, so a short reply does not turn into a full authoring workflow.

The visitor's container is the agent's sandbox, with no public internet. An outbound handler in the Worker lets through only Responses API requests to api.openai.com, and replaces the dummy credential the container holds with the real key, which never enters the container. Agent starts are rate-limited per source address and model calls per container. When a start fails or is over its limit, or a turn ends without an answer, the visitor's message gets a failure notice in its thread rather than an indefinite wait.

Releases and deploys

Every build has one release identity. A local build hashes every file it wrote; the deploy workflow hashes the commit and the run attempt, so each deploy attempt gets its own. Each page's runtime files are served under /_leaf-release/<release>/ with immutable cache headers. The document names its release, the browser sends it with every API request, and each API response names the release that produced it.

The runtime refuses a response from another release. The page's state is read by the scripts and widgets the document has loaded, and a document cannot replace those in place, so state from another build would be read by code not built for it. The runtime then asks the document's source whether it now serves a different release. If it does, the page says Leaf has been updated and reloads; if not, it waits for the server to finish updating.

Cloudflare activates a new Worker and its assets before the new container image has rolled out, so for some minutes a new container can still start on the previous release. When a container answers with a release other than the Worker's, the Worker does not pass that answer on. It clears the page's active cookie, serves the published state for api/state, and answers other requests with a 503 asking the browser to retry, until containers on the new release answer.

A push to main that changes the site runs the publish-site workflow. It builds the site, checks the bundle locally through the Worker and a container, pushes the container image, and deploys the Worker with that image pinned by its digest and an immediate container rollout. The deploy passes only once Chrome sees the new release in the edge document, its modules, and a newly started container, and a hosted agent on leaf.page has answered a real turn.

Private state and its lifetime

A visitor's comments, choices, agent replies, and revisions exist only in their container's copy of the page directories. No other visitor reads them, and the published pages never change. The container's filesystem is ephemeral, and the site has no durable store for page directories, so this state lasts as long as the container:

When a page's container has been replaced, the page notices the new server, reloads, and starts again from the published state.

The site counts accepted events in Analytics Engine without their content, widget ids, IP addresses, or cookies. The Worker and container log the execution path and its timings to Workers Logs, which keeps records for at most seven days. The Worker's README describes what each record carries.