Topology
Layers
Browser client
React 19 with TanStack Router.AgentChat composes InputBar, MessageList, and the right-hand resources and workspace panels. Streaming chat, structured plan cards, and tool cards are rendered with the shared agent-elements integration from packages/hax-design (@workspace/hax-design), the single source of truth for Fleet Pi chat surfaces, the OpenUI kit, and shared Pi protocol types.
State management:
usePiChatorchestrates the NDJSON stream lifecycle, tool rendering, and queued steering / follow-up prompts.useChatStoragekeeps minimal session metadata (sessionFile,sessionId) inlocalStorageso a refresh can hydrate the matching Pi session file.
apps/web — TanStack Start
File-based API routes live under apps/web/src/routes/api/. The Vite dev server serves them locally, and the Cloudflare Worker serves them in hosted deployments:
Internal modules:
lib/pi/server.ts— Pi runtime cache,createPiRuntime,queuePromptOnActiveSession, NDJSON encoding.lib/pi/server-chat-stream.ts— assistant turn lifecycle (beginAssistantTurn,handleSessionEvent,finalizeAssistantTurn).lib/pi/plan-mode.ts— mode allowlists and the plan-mode Pi extension.lib/pi/circuit-breaker.ts—opossumconfiguration around Bedrock invocations.lib/pi/run-provenance.ts— provenance recording around session and tool events.lib/workspace/server.tsandworkspace-contract.ts— durable workspace contract, manifest, and section kinds.lib/pii/sanitizer.ts— input redaction before logging.lib/logger.ts— Pino logger with redaction andrequestIdcorrelation.lib/pi/durable/hosted-agent-turn.tsanduser-pi-durable.ts— hosted Agent turns, forks, and transcript erasure on the per-user Durable Object.
Hosted chat on Cloudflare Workers
On the Cloudflare deployment (FLEET_PI_DEPLOYMENT=cloudflare), the Worker binds one SQLite-backed Durable Object class, UserPiDurable, as USER_PI_DURABLE. Each signed-in user resolves to one object, which opens a Pi Durable harness (@earendil-works/pi-durable) on its own storage.
- Transcript — the object’s SQLite storage is the hosted transcript. Hosted session ids start with
durable:and have nosessionFile. - Neon — keeps auth, settings, and an optional session projection. It is no longer the source of truth for hosted transcripts.
- Daytona — the user’s volume holds the harness workspace and artifacts. Without a Daytona sandbox, the agent works on a built-in workspace stored in the Durable Object.
- Models — each turn sets the conversation’s model, so model switches apply to resumed conversations. Forks inherit the parent conversation’s model.
- Erasure —
DELETE /api/chat/accountclears the object’s storage. Deleting a single hosted session only hides it.
sessionFile keep using the legacy runtime path. See the API reference for the request rules.
Workspace context on hosted turns
On hosted turns, the bundledworkspace-context extension reads Markdown from your workspace (your Daytona volume, or the built-in workspace) and adds three prompt sections. It never runs code from the workspace.
The agent reads a matching skill’s
SKILL.md with the read tool when a task calls for it. If your workspace has no AGENTS.md or system/ policy, the agent is told to read before writing and to ask before destructive changes.
Fleet Pi reads these files once per turn. It reads them again after a write or edit call changes AGENTS.md, system/, memory/project/, or pi/skills/, and after any bash command.
A message of the form /name args expands from pi/prompts/name.md before Fleet Pi submits it, including messages sent mid-turn as steering or follow-ups. The template supports $ARGUMENTS, $@, and positional $1, $2, and so on. If no matching template exists, the message is sent unchanged.
Built-in workspace without Daytona
When you have no Daytona API key, or your sandbox is not ready yet, hosted turns use a built-in workspace stored in your Durable Object. Fleet Pi seeds it from the same versioned template as Daytona volumes. It never overwrites your edits, and changed template files land in.fleet/template-updates/<version>/.
On the built-in workspace:
- The agent gets only the
read,search,write, andedittools. There is no shell, sobash, code mode, and MCP tools are unavailable. - Workspace context and
/nameprompt templates work as described above. - Writes to
memory/project/andplans/still need a rationale, andsystem/andevals/stay protected. - Only text files (
.md,.txt,.json,.yaml,.yml) are stored, underAGENTS.md,README.md,artifacts/,evals/,instructions/,memory/,plans/,pi/skills/,pi/prompts/,scratch/, andsystem/. - Each file can be up to 64 KiB, with at most 2 MiB and 500 files in total.
DELETE /api/chat/account erases it.
After you add a Daytona key, the first sandbox turn copies the files the agent or the Workspace panel wrote in the agent areas to your volume, in the background. If a file already exists on the volume with different content (an empty file counts), Fleet Pi writes the copy to .fleet/do-import/<path> instead. Files it cannot confirm stay pending until the next sandbox turn. After the handover, your volume is the source of truth and the built-in workspace is read-only for the agent.
agent-workspace/
The durable adaptive layer. The workspace server reads memory, plans, skills, and artifacts directly from files so every change shows up in Git diffs. The contract is versioned (WORKSPACE_CONTRACT_VERSION = 1) and the canonical section set is fixed in workspace-contract.ts:
instructions/, system/, memory/, plans/, skills/, evals/, artifacts/, scratch/, pi/, indexes/.
Sections have kinds — canonical, temporary, or projection — that the workspace server enforces.
.pi/
Committed project Pi configuration. settings.json is a compatibility bridge that points Pi at workspace-native resource directories. Built-in Pi extensions and committed skills also live here.
External
Fleet Pi calls whichever model provider is configured — Google Gemini by default (gemini-3.5-flash), or any other supported provider (Amazon Bedrock, OpenAI, Anthropic, Mistral, Groq, Vertex, Ollama). Provider selection lives in .pi/settings.json; credentials live in .env.
Amazon Bedrock specifically is wrapped by a process-wide opossum circuit breaker (bedrock-api). When you switch Fleet Pi to Bedrock, every Bedrock invocation passes through these settings:
When the Bedrock breaker is open, requests fail fast with
"Bedrock API is temporarily unavailable due to repeated failures. Please try again later.". Other providers fail through Pi’s standard error path (no breaker), so reliability tuning for non-Bedrock providers happens upstream in @earendil-works/pi-coding-agent.
Daytona is an optional external service for authenticated user sandboxes — enabled by setting DAYTONA_API_KEY. See the API reference for the sandbox surface.
Packages
Pi SDK packages:
@earendil-works/pi-coding-agent, @earendil-works/pi-ai, and @earendil-works/pi-agent-core at ^1.2.0, plus @earendil-works/pi-durable pinned to 1.2.0.
Other key dependencies: @tanstack/react-start, opossum, pino + pino-pretty, zod + @asteasolutions/zod-to-openapi, vitest, @playwright/test, husky + lint-staged.
apps/web/src/routeTree.gen.ts is generated. Do not edit by hand.
Request lifecycle
- The browser sends a chat message to
/api/chatas JSON. ChatRequestSchema(zod) validates the body.sanitizePiiredacts the message before logging.createRequestLoggerattaches a correlationrequestId.- On the Cloudflare deployment, a hosted session is forwarded to the caller’s
UserPiDurableobject, which streams the turn. OtherwisecreatePiRuntimereturns a warm Pi runtime (TTL controlled byFLEET_PI_RUNTIME_TTL_MS) or builds one. - The Pi runtime invokes the configured model provider. Bedrock calls go through the
opossumcircuit breaker; other providers go through Pi’s standard provider path. - Events are forwarded as NDJSON via
encodeEvent:start,delta,thinking,tool,plan,state,queue,compaction,retry,done,error. Every turn ends with adoneframe. createRunProvenanceRecorderrecords the session lifecycle and tool events.- On client refresh,
POST /api/chat/resumeorGET /api/chat/sessionhydrates the session from the Pi session file or, for hosted sessions, from the Durable Object.
Related
Agent workspace
What lives in
agent-workspace/ and why it is reviewable.Adaptive workspace contract
Canonical sections, manifest, and projection rules.
Runtime SDK seams
Safe extension points around the Pi runtime.
API reference
Endpoint contracts and stream events.