affordance

Showcase  /  Comparison

Affordance vs. Pi Durable

Both systems can run agents that survive a restart. Affordance can also replace the prompt-rendering and tokenization path inside SGLang. That second use explains why the comparison starts at a different layer.

14 November 2026. Pi Durable v1.5.2 and Affordance v0.1 beta. This is a comparison of their architecture and documented contracts; we have not run a head-to-head reliability or performance benchmark.

A durable conversation and a model interface

Pi Durable is Earendil's framework for persistent agent applications. It shares Pi's model layer, and provides conversations whose work can continue after the process stops. It is a separate harness from the regular Pi coding CLI. Cloudflare's PiHarness integration supplies storage and wake-ups in a Durable Object.

Affordance starts with a rendering problem. An application has state: a conversation, a workspace, a set of tasks, or an environment. A TSX view turns that state into the context a model reads and the actions it may call. The runtime applies the resulting events and effects, then the app renders again.

Affordance's model interface
Application state
  ↓ TSX view + token layout
Context + available actions
  ↓ model reply + handler
Updated application state
Pi Durable's conversation
Submitted input
  ↓ persisted conversation
Generation + tool tasks
  ↓ committed outcomes
Answer, follow-up, or recovery

A chat conversation is one useful form of application state. Affordance also supports interfaces whose current state is more useful to the model than a transcript of how that state came about.

The renderer can live inside the model server

In our SGLang integration, Affordance sits where the server prepares a model's prompt. The template is an Affordance app, and the output is token IDs ready for inference. The renderer retains previously rendered turns so a growing conversation can reuse them. The inference engine and its scheduling remain the server's.

This use needs no Affordance agent loop. The caller can be a chat client, an evaluation program, or a separate harness. Pi Durable operates on the application side of a model API; replacing the server's template and tokenizer path is outside its supplied abstraction.

The two could therefore occupy different layers of the same stack. In principle, Pi Durable could manage a conversation while an Affordance-backed model server renders its prompts.

The same renderer underlies the template conformance checks and apps rendered in different model formats. The integration is our fork of the server. Exact token equality is checked on the reported test corpus, rather than assumed for every possible request.

Where the systems put application policy
ConcernAffordancePi Durable
Primary objectAn app whose state renders into a model interface.A conversation with entries, documents, and tasks.
Application languageA documented TSX subset interpreted in Rust. Components and libraries compose the app.TypeScript APIs for tasks, tools, hooks, and extensions.
Model inputNative bindings can supply the rendered token IDs directly. Hosted bindings send structured messages.Requests go through pi-ai and its provider interfaces.
Available toolsActions are attached to rendered content. Layout determines which survive and can be offered.The conversation's configuration and extension registry select its tools.
Context policyThe app chooses its state projection; token style sheets budget sections. History and folding are libraries.Conversation context, request hooks, and configurable compaction.

Contracts: Affordance's ownership boundaries and Pi Durable's concepts.

For agents, state becomes context

Consider an agent reviewing a patch. Its working state might contain the current diff, failing checks, unresolved comments, and a decision. A view can give each section a token budget, show the current failures, and offer an acceptance action only when the app's conditions permit it. After a check completes, the next render reflects that result.

The app can keep the full transcript for inspection while showing the model a different working view. It can also render the transcript itself. That choice belongs to the application.

Affordance makes the projection explicit: state → context + available actions. A tool belongs to the view where it is rendered. An action hidden or partly clipped by layout is excluded from the offered actions. Dispatch uses the handlers captured with the model's request. These are engine contracts, so each application can build on them.

Pi Durable also permits custom state and request rewriting. The distinction is where the mechanism lives: in Affordance, rendering and token layout are shared primitives used by templates and whole applications. The tool-output example and history layout example show two small policies built from them.

Exact native tokens are a specific boundary. When Affordance sends messages to a hosted chat API, that provider controls the final template and tokenization. The local renderer cannot promise the provider's hidden token sequence.

Recovery guarantees need their own comparison

Both systems preserve completed work, but they define recovery around different units. Affordance reconstructs an instance from journaled inputs, optionally starting at a compatible checkpoint. Pi Durable resumes persisted task phases. Its effect protocol records intent before an external operation and records the outcome afterwards.

What happens across a restart
ConcernAffordancePi Durable
Recovery unitThe instance's journaled execution, with optional recovery checkpoints.A task's persisted phase and checkpoint, together with conversation and document state.
Recorded resultsRecorded model replies and machine results are replayed without issuing those completed effects again.Committed outcomes remain stored; scheduling continues unfinished work.
Interrupted toolsOutstanding machine calls can run again. External writes need idempotency at the executor or application boundary.An interrupted tool reruns only with a replay-safe policy. Otherwise the model receives an interruption result.
Changing codeCheckpoints require matching source, tokenizer, and configuration. Strict replay rejects prompt divergence; incompatible journal contracts are refused.Task and document definitions have versions and migration mechanisms.

See Affordance's harness contract and Pi Durable's specification. Neither runtime makes arbitrary external side effects exactly-once.

For example, a shell command appends a line to a file, then the host dies before recording success. Affordance may resubmit the outstanding command. Pi Durable's default tool policy reports that the call was interrupted instead of automatically executing it again. A tool declared safe to replay still needs to make any repeated external write safe.

Deterministic execution is shared territory too. Pi Durable's Code Mode replays sandboxed scripts with recorded tool results. Affordance applies journaled replay to its application language and instance execution. The difference is the scope of the contract.

Durability also depends on storage and presentation settings. Pi Durable 1.5 can show streamed progress before persisting it, with a default window of about one second. Completed outcomes and task transitions follow the stronger commit rules. Its 1.5 release notes explain that tradeoff. Both projects still have evolving APIs.

Where Pia fits

Pia, our Affordance version of Pi, puts an Affordance app behind Pi's familiar terminal interface. Pi retains its session and extension layers. Affordance runs the app's loop and built-in tools; extension tools can cross back to Pi through an adapter.

It is a useful place to change the model's working context or the agent's behavior in TSX. Its shipped deployment uses the chat API path, and its adapter keeps Pi's transcript and the app's conversation in step. The native token guarantee demonstrated inside SGLang therefore should not be attributed to Pia's default configuration.

The small TSX files show where application policy lives. Their line count leaves out the Rust engine, shared libraries, and frontend adapter. Affordance provides more machinery underneath that small app, with an interpreted language and a renderer as well as a runtime.

Choose the layer you need to control

Starting points for three kinds of work
WorkStarting pointWhy
A persistent agent servicePi DurableA conversation API with recovery, client observation, and deployment integrations is a direct fit. Conversation watches let clients attach to its current state.
An inference-server rendererAffordance's rendering libraryThe work concerns template semantics, tokenization, and exact prompt IDs before inference.
Experiments with agent contextAn Affordance appChange how working state becomes a token-budgeted view, how actions depend on it, and how the next model call is made.

The overlap is real when building agents. Affordance's broader scope comes from treating the model interface as something an application renders. You can use that renderer alone, or use the runtime to maintain the state behind it.

To try that abstraction, build an app in the guide. To see it below the agent layer, read the SGLang integration. The memory app and the Recursive Language Model show what can be changed above it.