# The Harness Outside the Sandbox

Agents do not need a computer to think. nanocode runs the agent loop and its session in a process the host already has, such as a Worker, a Function, or a browser tab, and attaches a machine only for the calls that need one.

**Most of an agent's turn is spent waiting on a model, and today a sandbox bills for every second of it.** We built nanocode so that the harness lives outside the sandbox, and a machine joins only when a tool needs one.

## TL;DR

* **First text in about a second:** a new session on Cloudflare streamed its first text 1,093 ms after the prompt, with no machine to boot.
* **80x fewer tokens:** one 20-file task took GPT-6 Luna 814,466 input tokens and 21 model calls with tool calls. In Code Mode it took 10,129 tokens and 2 calls.
* **Python without a container:** a warm matplotlib chart in a Durable Object took 335 ms.
* **Machines are optional:** a browser tab attached as a hand ran a command from a laptop brain in 4 ms.
* **Two transactions:** any number of paid requests settle in 2 chain transactions.

Every number was measured on 2026-11-09, and each one is explained below. None of them needed a sandbox.

## Why Now?

Claude Code, Codex, [OpenCode](https://opencode.ai), and [Pi](https://github.com/earendil-works/pi) started as programs on a laptop. Each keeps its session in one long-lived process and runs its tools beside it. To move them to the cloud, products start a sandbox per session and run the CLI inside it.

We think that is the wrong default, and we are not alone. Vercel's [durable-harness](https://vercel.com/blog/making-every-harness-durable) says that "not every agent task executed through a harness needs a sandbox." Anthropic's [Scaling Managed Agents](https://www.anthropic.com/research/managed-agents) decouples the brain from the hands and from the session log.

|              | Harness in a Sandbox                               | Harness Outside                                   |
| ------------ | -------------------------------------------------- | ------------------------------------------------- |
| Machine time | The whole turn, mostly spent waiting for the model | Only the calls that need a machine                |
| Credentials  | Beside the code the model writes                   | In the host, which the model's code never reaches |
| Session      | In memory, lost when the sandbox stops             | A journal that any process reopens                |
| First word   | After a machine boots                              | After a model call                                |

## How It Works

```mermaid
flowchart LR
  host[Host process] --> loop[Harness loop in WebAssembly]
  loop -->|every write| journal[(SQL journal)]
  loop -->|requests without keys| egress[Host egress]
  egress --> provider[Model provider]
  loop --> tools{Tools}
  tools --> fns[Host functions]
  tools --> bash[Shell over journaled files]
  tools --> hands[Hands: laptop, server, tab]
```

* **The loop runs in any process:** the Claude and Codex harnesses compile from one Rust SDK to native code and to one WebAssembly module of 12.1 MB, 4.0 MB gzipped.
* **The session is a journal:** every turn, model step, and tool result is a write to a SQL database that the host supplies.
* **The host holds the keys:** the module builds requests without credentials, and the host's egress adds them on the way out.

## How Fast?

With no machine to start, the first word waits only on the model. On the [Cloudflare demo](https://nanocode.xyz/cloudflare/) with Claude Haiku 5.5, the time from a prompt to the first text was:

```mermaid
xychart-beta horizontal
  title "Prompt to first text, median ms"
  x-axis ["New session, cold", "New session, warmed", "Second turn"]
  y-axis "ms" 0 --> 3000
  bar [2640, 1093, 945]
```

A cold start is an object, an open runtime, and a path to the model. None of them is a machine, so each can start before the prompt. The demo warms all three at a visitor's first pointer move or key press.

## Code Mode

In Code Mode the model writes a program that calls the tools, and only what the program returns enters its context. On one 20-file task GPT-6 Luna used 814,466 input tokens with tool calls and 10,129 in Code Mode. [Code Mode Is Necessary](/experiments/code-mode-is-necessary) has the full runs.

A Function has no /bin, so the cell runs JavaScript on QuickJS, which needs no eval and runs in Workers. The shell is bash over a virtual filesystem whose files are rows of the journal.

## Hands

A laptop, a server, or a tab can be a hand. A turn holds a hand only for the calls that name it, and a command from a laptop brain ran in a tab hand in 4 ms. [Making Every Machine Feel as One](/experiments/hands) covers the rest.

## Python in Workers

A Durable Object has no processes and may not compile WebAssembly at run time. **nanocode runs CPython there anyway.** The build runs Pyodide once, records all 515 compiled modules (26.6 MiB), and snapshots an interpreter that has already imported numpy and matplotlib and drawn a figure.

```mermaid
xychart-beta horizontal
  title "Time in python3, ms, 2026-11-09"
  x-axis ["First run in a cold isolate", "print, warm", "matplotlib chart, warm"]
  y-axis "ms" 0 --> 8000
  bar [7181, 161, 335]
```

We want to be clear about the cold start: the first run in a new isolate takes 7.2 s. After that, one interpreter serves every Python object in the isolate, and each run moves only the files that changed.

## Paying Its Way

An agent that works alone has to pay for what it uses. Over the [Machine Payments Protocol](https://mpp.dev), a paid endpoint answers 402 with a challenge, the agent signs a payment, and the repeated request returns the result with a receipt.

| Step                                          | Chain transactions |
| --------------------------------------------- | -----------------: |
| Open a session with a deposit                 |                  1 |
| Each paid request, a voucher signed off chain |                  0 |
| Settle and close                              |                  1 |

A visitor's Tempo Wallet approves a key that may spend at most 2 MACH and expires in a day, and the chain enforces both. A short demo turn on Claude Haiku 5.5 cost about $0.0001.

## Try It Today

Open the [Cloudflare demo](https://nanocode.xyz/cloudflare/), ask for a chart, and watch Python run in a Durable Object. We think the harness belongs where the data and the keys already are. If you are building agents on Workers, Functions, or in the browser, we would love to hear from you on [GitHub](https://github.com/nanocodexyz).

- [Code Mode](/docs/guides/code-mode): Run JavaScript cells against registered tools.

- [Remote Hands](/docs/guides/remote-hands): Brains, hands, tokens, and the SSH recipe.

- [Cloudflare Workers](/docs/guides/workers): Sessions and Python in Durable Objects.

- [MPP Payments](/docs/guides/mpp-payments): Pay for model and MCP requests per call.
