# What is Condensate (https://condensate.dev/argument/)

> A runtime and a durable layer for coding agents, on your own machines.

**Condensate is a runtime and a durable layer for coding agents.** You run it on your own machines. It runs several vendors' agents under one record and one set of rules.

- **Many engines.** The real Claude Code and Codex, with their own tools, sub-agents and plugins, run beside two engines built into Condensate: its own agent loop, and pi, a thinner loop over a provider's API that the app lists as API.
- **Durable.** Every message, tool result and approval is written down before any agent acts on it.
- **Provable.** On Condensate's own loop, each request to the model is rebuilt from the record, and its fingerprint is saved before it is sent, so a replay can be checked byte for byte.
- **One policy.** A single policy service checks tool calls from every engine.
- **Pooled.** Your Claude and Codex plans are shared across agents, and the same pool is served as an OpenAI-compatible endpoint.
- **Self-hosted.** It runs on a machine you keep on. Your code and logins stay there.

Each section below says what is built, what runs only in tests, and what is designed but not built yet.

## The layers

[Diagram: The system at a glance. Your interface talks to the runtime over HTTP. The runtime records every thread, and the engine you pick runs the model conversation on one of your accounts. Middleware connects agent tools you did not build.]

Condensate is easiest to understand as five layers, each resting on the one below.

| Layer | What it holds | What it brings |
| --- | --- | --- |
| The record | Every thread, written before anything acts on it | What durable agent frameworks offer |
| The runtime | The engines, and the logins kept away from them | What the native CLIs offer, under one policy |
| The workflow | Separate copies of the repository, diffs, stacked pull requests, reviews, a view of every agent | What agent UI wrappers offer |
| Always on | Threads that keep running on your machine, several people guiding one thread, GitHub-triggered review and fixes | What hosted agents offer, self-hosted |
| The ways in | The web app, the phone app, a completions endpoint, one MCP address, an SDK | Your own programs on the same accounts and rules |

Four things here would require a competitor to change how its product is built: the provable request, the sub-agent that starts with a warm cache, one policy across engines, and subscriptions behind a completions endpoint. The workflow and always-on layers are features others also have, and the gaps are listed below.

## The record

The runtime writes each message, tool result, approval and reply to the thread's store, and only then hands it to the engine. Every engine shares this record, and every app reads it, so the web app, the phone and the review server show the same thread.

Condensate's own loop keeps a second, lower record of its own. Each entry is chained to the one before it by a hash and written to disk before the loop continues. If the machine dies mid-write, the half-written last entry is trimmed when the record reopens. If anyone edits an entry, the chain breaks and the record is refused. Entries name the account that was used and never contain a login.

## Provable requests

[Diagram: One thread, event by event. Each event lands in the log with the next sequence number, and your message is on disk before any model reads it. Pull the plug at any point: the log is still there, and Resume continues from it.]

On Condensate's own loop, every request to the model is built the same way:

1. The loop builds the exact request it will send from the record.
2. It computes a fingerprint (a hash) of that request.
3. It writes the fingerprint to the record.
4. Then it sends the request.

Opening the same record later, in a new process, rebuilds the same request byte for byte. A replay rebuilds every request and compares fingerprints, and a resume refuses to continue if anything has drifted. The version of the code that builds requests is saved in the record too, so an upgrade can't quietly change the bytes.

That matters for the model provider's prompt cache, which is keyed on those exact bytes: a correct resume can read the cache it left behind, and a live test confirms it does. The cache still expires and belongs to one account and model, so identical bytes are needed for a cache hit but don't guarantee one.

UI wrappers never see these bytes, because the vendor's CLI builds them. Claude Code and Codex keep them in an internal format that changes between versions, and don't fingerprint them. Pi Durable designs its transcript to keep the cache valid, and has no proof that it did.

## Moving a thread

A **turn** is one message to an agent and its full reply, tool calls included.

| Situation | State |
| --- | --- |
| The same process, across turns | Built |
| A new process on the same machine | Built |
| A new process, with the fingerprint check on resume | Runs in tests |
| A new machine, with the cache still warm | Designed, not built |
| A different account | Refused on purpose, because a cache belongs to one account |

Claude Code's `--teleport` and the Codex app's handoff already move a session between machines today, without a proof.

## Sub-agents that start warm

When Condensate's own loop hands part of a task to a sub-agent, the sub-agent's record starts as an exact copy of its parent's, up to the hand-off. Because the request is rebuilt from the record, the sub-agent's first request starts with the same bytes the parent already sent, so it reads the parent's cache. If the model, account, provider, request-builder version or tools differ, the hand-off is refused instead of quietly starting cold. A live test confirms the sub-agent's first call reads from the cache.

Claude Code's sub-agents start from an empty context, and its `--fork-session` copies a session without checking the cache. Sub-agents on Claude Code and Codex don't have this property inside Condensate either; it belongs to Condensate's own loop.

## After a crash

When Condensate's own loop reopens after a crash, it looks at each tool call that was in flight. Calls that only read run again. Calls that change something are recorded as "effect unknown", and the agent decides what to do. Once a tool has started, the runtime never retries the turn on its own. Undoing a step adds a new entry that marks it undone; nothing is erased.

Pi Durable and Claude Code handle interrupted calls in a similar way, so this is parity. Pi Durable goes further: after a crash it resumes on its own. Condensate marks the interrupted turn as lost, and a person presses Resume.

## The engines

[Diagram: Four engines, and an agent Condensate only watches. Pick an engine. The model id decides the engine unless you name one.]

Claude Code runs through Anthropic's Agent SDK, Codex runs as its own app server, and pi and Condensate's own loop run inside the runtime. Claude Code and Codex bring their tools, sub-agents, sandbox and plugins with them. Condensate changes three things:

- it replaces their context trimming with its own;
- it doesn't load your personal Claude Code settings;
- it switches off Claude Code's own permission prompts and checks every tool call itself instead.

Condensate's own loop is newer and does less. It has 7 tools, MCP servers, approvals, messages sent mid-turn, and interrupts, skills, the warm sub-agent hand-off and crash repair. It doesn't yet have context trimming, plan mode, questions back to you, thinking control, switching models mid-thread, or a sandbox for shell commands. An existing Claude Code session can be imported.

## One policy layer

[Diagram: How far the policy service may go. Slide across the five tiers. Each position lights what the policy service may do, and the answer under it shows how one tool call ends. The last switch cuts the policy service off.]

The same four events reach one policy service from every engine: before a tool runs, after it runs, when you send a prompt, and when the agent stops. The service can let a call through, block it with a reason, or add a note to the agent's next turn. You choose how far it may go, from only recording to interrupting the agent, and a control group with no notes measures whether the notes help.

Each native CLI's hooks cover only that CLI, and UI wrappers start the CLIs without seeing their tool calls.

## Logins

Agents hold placeholder keys and reach the model providers through a proxy that adds the real login on the way out. The runtime refuses to start without the proxy, and refuses to start any agent that carries a real login. In the Docker install, agents run with no network of their own. One process refreshes each login, exactly once, under a lock, so two agents never race to refresh the same token.

Claude Code on the web does the same thing for its own agent in Anthropic's cloud. In the other self-hosted tools that run several engines, agents run as your own user.

## Accounts and the completions endpoint

[Diagram: What leaves the agent, and what leaves the Mac. A placeholder is all an agent ever holds. The real login exists only in the proxy, and only the host it belongs to receives it.]

Claude, Codex, OpenCode and Cerebras subscription accounts sit behind one OpenAI-compatible completions endpoint. A project lists the accounts it may spend. The runtime picks an account by weighing the usage it has left against the time until it resets.

[Diagram: One task, three accounts. Press Next to move the task. The second switch limits it to the two accounts this workspace lists, which is the rule every workspace runs under.]

If an account runs out, the request moves to the next one, but only before the first word of the answer has come back. Each call writes a usage record that holds no prompt or answer text. Switching models on a Claude Code agent is checked against a limit on what re-filling the cache would cost.

The endpoint has limits today:

- it answers only on the machine itself, with no key of its own;
- it takes text only, and can't force a tool call;
- it doesn't yet check the project's list of allowed models.

bb pools subscriptions only for its own CLI, and LiteLLM speaks the OpenAI format over API keys rather than subscriptions.

## The workflow

[Diagram: A review, then the push. Five steps of review, then four of the push. A result is pinned to the commit it read, and the push only ever adds commits on top of what GitHub has.]

Each agent gets its own copy of the repository from a pool kept ready in advance, and a copy is archived as a patch before it's ever deleted. Changes show as a diff you can comment on line by line. Stacked pull requests work with Graphite or jj. A merge needs an approval for the exact latest commit. A review puts two vendors' agents on one change, with one fixing and one checking, and can merge on approval. A check spots two agents doing the same work. A project's lead agent keeps watching work after any terminal closes. Several clients can follow and guide one thread, any thread can be forked from any point, and archiving never deletes. By default two build agents run at once.

[Demos of the Condensate app, on sample data, on the HTML page. Every account, and what it has left: Usage and reset times for each Claude, ChatGPT and API login. When one runs out, the task moves to the next and no tool runs twice. Condensate asks when an agent needs you: A waiting agent says what it wants to run, with Allow and Deny. On the iPhone the same ask shows on the lock screen. Review and CI at the exact commit: Claude builds, Codex reviews, and you approve the commit the review result belongs to. Every agent's live work, from one log: Each step is written to the thread's log first, so a crash, restart or reconnect loses nothing. Logins agents never see: By default agents hold a placeholder, and the proxy adds the real token on the way out. Spending limits: A workspace spends only the accounts and models it lists. One policy: Hooks from local agents and plugin sessions go to one place that can deny or steer. One tool gateway: Every MCP server you connect, served to your local agents as one catalog.]

## Where Condensate is behind

- **No hosted option.** Amp, Conductor Cloud, Claude Code and Codex in the cloud, Cursor and Devin run with no machine for you to look after. Condensate needs your own machine, always on.
- **No pausing.** Amp can pause a running agent and resume it later with its files and services intact.
- **No move between machines yet.** It's designed and not built. Claude Code and Codex already move sessions between machines.
- **No automatic resume.** After a crash, a person presses Resume. Pi Durable resumes on its own.
- **No exactly-once send.** A message sent twice arrives twice. T3 Code and Pi Durable de-duplicate.
- **No terminal you type into, no desktop app, no app-store phone app.** The Condensate app runs in the browser and installs on a phone as a web app.
- **No schedules beyond a daily brief, and no Slack.** Conductor, Amp, bb and Claude Code have schedules, and several have Slack.
- **Fewer engines.** bb runs about 13 CLIs, T3 Code 6, Condensate 4.
- **No live presence.** Amp and Conductor show who else is in a thread.
- **Condensate's own loop is shallower** than Claude Code, which has about 35 hook events to the loop's 4.
- **Review tools.** Devin's review spots moved code and has a rules editor.
- **Operations at scale.** Temporal and Cloudflare are far ahead on scaling out and observability.

## How it compares

| Kind of tool | How much Condensate matches | How |
| --- | --- | --- |
| UI wrappers (T3 Code, Conductor) | Most features | Builds its own copies, diffs, stacks, a view of all running agents, and forks, and goes further on review and the merge check. Missing a terminal, desktop and phone apps, and more than 2 builds at once |
| Hosted agents (Amp, bb, cloud agents) | Part | Threads that keep going, several people guiding, GitHub loops, self-hosted. Missing a cloud, pausing, schedules, Slack and presence |
| Native CLIs (Claude Code, Codex) | Inherits, with changes | Runs the real CLIs, replaces context trimming, skips personal settings, checks every tool call. Its own loop covers part of what they do |
| Durable frameworks (Pi Durable) | Level on crash repair, ahead on the cache, behind on resume | The hash chain, provable requests, warm sub-agents and a record with no logins in it are ahead. Automatic resume and exactly-once are behind |

## Implementation

- The thread record is written before the engine sees it in `packages/agents-host/src/thread.ts:2181` and `packages/agents-host/src/store.ts:1716`.
- The loop's hash-chained record, its disk writes, torn-write trimming and refusal on edit are in `packages/engine/src/loop/log.ts:60-117`; entries carry no secrets per `packages/engine/src/loop/frames.ts:11`.
- The request is rebuilt from the record in `packages/engine/src/loop/session.ts:326`; its fingerprint is written before sending at `:330`; replay compares fingerprints at `packages/engine/src/loop/session.ts:788`; resume refuses on drift in `packages/engine/src/loop/hibernate.ts:240`; the request-builder version is pinned in `packages/llm/src/wire.ts:14`.
- Production reopen is `packages/engine/src/loop/condensate.ts:344`; resume with the check runs in `packages/engine/tests/loop-log.test.ts:396`; the live cache read on resume is `packages/engine/tests/live/loop-resume-prgrm.test.ts:96`; the machine-to-machine move is designed in `docs/architecture/condensate-loop-resume.md:50`; the account check is `packages/engine/src/loop/session.ts:235`.
- The warm sub-agent hand-off is `packages/engine/src/loop/fork.ts:232`, refused with `ForkCacheMismatch` at `fork.ts:82`, wired at `condensate.ts:387`, with the live check in `packages/engine/tests/live/loop-fork-prgrm.test.ts:169`.
- Crash repair is `packages/engine/src/loop/session.ts:735`; the runtime withholds a retry once a tool starts in `packages/agents-host/src/turn-retry.ts:17`; the lost turn is `packages/agents-host/src/lost-turn.ts`.
- The engines are listed in `packages/engine/src/model/engine-id.ts:15`; Claude Code's permission hook, cost check and permission setting are in `packages/engine/src/claude/claude.ts:693`, `:732` and `:819`; Codex hooks in `packages/engine/src/codex/session.ts:196`; pi in `packages/engine/src/pi/loop.ts:727`; the loop's events in `packages/engine/src/loop/hooks.ts:85`; the import in `packages/agents-host/src/claude-import.ts`.
- One policy wire is `packages/agents-host/src/spawn-middleware.ts:49`; consent tiers and the control group are `apps/middleware/backend/src/consent.ts:41` and `:111`.
- Placeholders and the proxy are `packages/agents-host/src/seat-proxy.ts:21` and `proxy-boot.ts:67`; Docker agents with no network are `agent-launcher.ts:133`; the single refresh is `packages/broker/src/broker.ts:100`.
- The endpoint is `packages/agents-host/src/completions.ts:695`, with failover before the first token at `:481`, usage records at `:439` and its limits at `:55` and `packages/agents-host/src/main.ts:303`; the list is `account-failover.ts:265`; pacing is `account-pace.ts:88`.
- Several clients following one thread, forks and archive are `packages/agents-host/src/http.ts:1319`, `:1484` and `:1793`; the merge check is `packages/head-tools/src/prs.ts:105`; two build agents by default is enforced at `apps/gt-review/src/http/server.ts:4987`.
- Checked at commit d6fc25c00. Comparisons with other tools rest on their public docs as of October 2026.
