Managoat is the hosted Fountain. Fountain is the open-source engine, and its name is on the CLI, the API, the SDK and this manual. Everything here applies to Managoat unless a page says it is for a self-hosted server.

About sandboxes

This page explains what a sandbox is, why Fountain does not let you create one, and what changes when you move to a different provider. For the executable contract a backend must meet, read the sandbox contract. To choose and configure one, read Self-host Fountain. For the endpoints, read the Sandboxes section of the API reference.

What a sandbox is

A sandbox is the isolated machine that a conversation runs in. Several conversations can run on one sandbox at the same time, each with its own transcript.

You never create one on its own. Fountain provisions a sandbox when a conversation starts. Fountain reclaims it when every conversation on it goes quiet, or when it runs too long. You can name one, with sandbox_id, to put a second conversation on it. GET /api/sandboxes lists them, and fountain sandbox does the same from the CLI.

That is deliberate. A sandbox you could create on its own would be a resource you could leak. The machine that nobody remembered to stop is what makes agent infrastructure expensive.

Two modes

An agent chooses a default, and a launch can name the other.

With ephemeral, the default, each conversation gets a sandbox of its own. When the conversation ends, the sandbox ends. This is the mode for a one-shot task, for a fan-out, and for input you do not trust.

With persistent, the agent has one machine of its own. Each conversation with the same environment and vault lands on it. Notes, clones and installed tools accrue across conversations. What a bad turn leaves behind also accrues, because all of them use the one disk. The machine survives a conversation that ends. Nothing stops it while it runs. When you delete the agent, Fountain destroys the machine. A reset (DELETE /api/sandboxes/:id) also destroys the machine, and keeps the conversations. The next prompt builds a clean one.

The machine belongs to one identity. Three changes move that identity. You move the agent to a different environment. You delete the environment. You delete the vault. Fountain retires the machine for each of them, and keeps the conversations, so the next prompt builds a machine on the identity that exists now. Fountain refuses each change with 409 sandbox_mid_turn while a conversation on that machine runs a turn. Let the turn end, or stop it, then send the request again.

When a home parks, Fountain can take a checkpoint of its disk. The operator turns this on with CHECKPOINT_CREATION_ENABLED, and only a provider with checkpoints (Sprites) does it. The checkpoint belongs to that one machine. It can roll the machine back to its last park. It cannot rebuild a machine that the provider lost. GET /api/sandboxes/:id shows the checkpoint as checkpoint.

Why the lifecycle belongs to the conversations on it

Tie the machine to the runs on it, and three problems solve themselves.

Reclamation gets an owner. When every conversation on a machine is idle, the machine is idle, and no separate record can go wrong.

Cost gets a shape that a user recognises. "This conversation cost something" reads clearly, and "you have 14 sandboxes" does not. Two conversations that each run for an hour on one machine spend two turn hours, on a machine that was busy for one.

Memory gets somewhere to live. The runtime keeps its session on the sandbox's disk. To suspend and wake the machine is therefore the same act as to pause and resume the conversations on it. Read About conversations.

A prompt to any conversation on a parked machine wakes it. The wake serves that conversation only. The other conversations on the machine start again on their own next prompt, and that prompt lands on the machine that is already awake. The idle clock counts the activity of every conversation on the machine, so one active conversation keeps the machine up for all of them.

One seam, four backends

Each backend plugs into the same seam, Fountain.Sandbox. The contract is executable, and not merely described. The behaviour specifies callbacks, capabilities and an error taxonomy. A conformance suite that each adapter must pass covers four things. It covers replay-from-start attach, total write_stdin, exactly one terminal frame for each command, and allow: [] as deny-all.

Provider What it is Suspend
Sprites The first backend, and the instance default. Parks on its own, scales to zero, keeps the disk.
E2B Hosted. An explicit pause, with a snapshot of filesystem and memory.
Daytona Hosted, and you can self-host it. An explicit stop, keeps the disk, archives a long park.
Self-hosted runner fountain runner on a machine the user owns. Stops the processes. The directory stays.

Capabilities are honest, and that has consequences

An adapter advertises what it can truly do, from :suspend, :network_policy, :attach, :tty, :checkpoint and :public_url. The lifecycle then degrades to match, and it pretends nothing.

A provider without :suspend destroys on idle. It does not fake a park. A resume with a fresh disk would lose the agent's memory without a sound, which is worse than an honest teardown.

So the idle timeout does not mean the same thing everywhere. On Sprites it costs nothing. On a provider with no suspend it costs the memory the agent works from. Read Change sandbox lifetimes.

Three more consequences matter.

A runner gives you no isolation. It runs in trusted mode on a machine the user owns, with no egress policy. It is a way to use hardware you already have. It is not a security boundary.

Only Sprites gives you a TTY.

A sandbox never moves. A parked disk stays where Fountain wrote it, so a wake never crosses providers. Change the instance default and only new sandboxes follow it.

Anything an agent serves can be public

A provider that gives a sandbox its own HTTP endpoint advertises :public_url. Fountain sets the URL in the sandbox as SANDBOX_URL, so an agent can answer when you ask where it runs.

On Sprites that endpoint asks for a platform credential by default. Fountain opens it, because an agent that serves a page serves it to a person, and that person holds no such credential.

So anyone with the URL can reach what an agent serves. Set config :fountain, :sprites_public_urls, false to keep the default instead. A sandbox then keeps its URL, and only a token holder can open it.

Not a container you can hand us

Fountain builds no image and stores no image. A provider applies your environment as a recipe at provision time. Two conversations from the same environment install their packages one by one, on their own machines.

That costs provision time. It buys you no registry, no build pipeline, and no garbage-collection problem.

Where to go next