2026.08.22The Agent Runtime Problem: Four Things a while-Loop Doesn't Give You15 min read What a runtime owns that a framework does not Four quadrants, each naming a problem an agent runtime has to own. One, durable state: a crash between the tool and the push, answered by two commits around one uncertain call. Two, session ownership: the terminal dies with the agent, answered by a daemon that reports working or blocked. Three, the orchestration loop: the author reviews its own diff, answered by splitting the context window rather than the model. Four, identity and money: no name to present and no way to pay, answered by HTTP 402 plus a delegation boundary. The four are independent, and no project has all four. What a runtime owns that a framework does not four independent problems — no project on this list has all four 1. durable state crash between the tool and the push→ two commits per uncertain effect 2. session ownership the terminal dies with the agent→ a daemon that owns the session 3. the orchestration loop the author reviews its own diff→ split the context, not the model 4. identity and money no name to present, no way to pay→ HTTP 402 plus a delegation boundary a framework gives you a while-loop and tool plumbing a runtime owns what survives the process
2026.08.20gpui and the Mail Client Problem: A Text Field Costs 778 Lines28 min read The same event, two boundaries Two columns on a shared five-row grid, tracing the same event — a message landing in the mailbox while the user scrolls the thread list. Left column, Tauri or Electron: a sync task in the Rust core owns the store and the socket; the envelope is serialised to JSON, which is the only wire format the event system offers; the payload crosses into the WebView as evaluated JavaScript; a listener rebuilds the row, producing a second copy of the same data on the JavaScript heap; and a virtual list finally writes it into the DOM of WebView2, WKWebView or WebKitGTK depending on the user's operating system. Right column, gpui: the sync task runs on the background executor inside the same crate and the same address space; cx.spawn hops back to the main thread with an AsyncApp held across the await; store.update leases the state out, mutates it and returns it; cx.notify queues an effect that is flushed after the update completes; and the uniform list paints only the visible range on the next GPU frame. The left path buys a serialiser and a runtime you do not own, but gets a text field, a table and accessibility for free. The right path is a function call, and a design system you now maintain yourself. The same event, two boundaries a message lands in the mailbox while the user is scrolling the thread list Tauri / Electron sync task, Rust core owns the store and the socket serialise the envelope JSON — the only wire formatevents "are always JSON strings" cross into the WebView payload arrives as evaluated JS listener rebuilds the row a second copy on the JS heap virtual list, then DOM WebView2 / WKWebView / WebKitGTK gpui sync task, background executor same crate, same address space cx.spawn back to the main thread AsyncApp held across the await store.update(cx, ..) state leased out, mutated, returned cx.notify() effect queued, flushed after update uniform_list, next frame visible range only, painted by the GPU left: a serialiser, and a runtime you do not own right: a function call, and a design system you now maintain the left column ships a text field today; the right one charges 778 lines
2026.08.11Pi's Durable AgentHarness: An Agent Loop That Survives kill -918 min read Three stores, one invariant Three stacked bands, one per durable store in a Pi AgentHarness session. First, entries — the conversation itself: messages, compaction summaries and branch summaries, written once, never edited or deleted, belonging to no lane. Second, registers — current mutable state: the lane leaf, the lane configuration, operation metadata and the total operation state, plus facts; a register is overwritten or deleted and keeps no write history, and the operation-state register is the program counter recovery reads. Third, the usage ledger — one append-only row per settled attempt, never edited or deleted, never in the tree. All three share one monotonic sequence number. A transaction is the only write primitive. Recovery reads the operation-state register; it does not replay a journal or infer state from what is missing. Three stores, one invariant every durable payload is an entry, a register, or a ledger row entries — the conversation messages, compaction summaries, branch summarieswrite-once · never edited · never deleted · belongs to no lane registers — current mutable state lane.leaf · lane.config · op.meta · op.state · factsoverwrite or delete · no write history · this is the program counter usage ledger — cost history one row per settled attempt · token and cost eventsappend-only · never edited · never deleted · not in the tree all three share one monotonic seq — a transaction is the only write primitive recovery reads op.state; it does not replay a journal or infer from what is missing