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.

The four primitives

This page explains what Fountain's four objects are, and why there are four of them. For the fields on each one, read the API reference. To build something with them, start with the guided tour.

The problem the four primitives divide up

To run a coding agent on a machine that is not yours, you must decide four things. Each of the four changes on its own schedule.

What the machine holds changes rarely. Python 3.12, a checkout of your repo, a setup script. You decide it once for a team, then leave it alone for months.

Which credentials the agent runs with changes constantly. A staging database URL today, a customer's API key tomorrow, a rotated token an hour from now.

How the agent behaves changes sometimes. Which model, which runtime, which skills, which MCP servers, and what its system prompt says.

What it does right now changes every few seconds.

Put all four in one object, and each credential rotation edits the machine image. Each prompt edits the credentials. Fountain divides them into four objects on purpose, and that division is the product.

Primitive Answers Changes
Environment what the machine holds rarely
Vault which credentials the run uses constantly
Agent how the agent behaves sometimes
Conversation what it does now continuously

How they compose

An Agent names an Environment. A Conversation runs an Agent. That Conversation can name a different Environment, and it can attach a Vault for that one run.

Three of the four are templates. They are rows that you write once and use many times. The fourth, the Conversation, is a run on a machine. The machine is the heavy work, and Fountain does it for you.

TEMPLATES · rows, written once Agent model, runtime, skills Environment packages, repos, secrets Vault secret overrides, per run Fountain, at launch merge env ∪ vault, vault wins split: broker or sandbox RUNS · the machine Sandbox Conversation transcript Conversation shares it env: config, placeholders GITHUB_TOKEN=__github_token__ machine: built, warm, metered, reclaimed Egress broker hosted, when the broker is on → GitHub, model APIs, yours runs as a conversation builds the machine placeholders values, per conversation HTTPS_PROXY, only exit
Three templates, one machine. Agent, Environment and Vault are rows you write once. When a Conversation starts, Fountain builds the sandbox from the Environment and runs the Agent on it. Several Conversations can share one machine. On a hosted account with the egress broker on, a bound secret goes to the broker and the sandbox gets a placeholder; the sandbox reaches the internet only through the broker, which attaches the value. On any other account, the merged secrets enter the sandbox as environment variables.

A Conversation starts. At that moment Fountain merges the Environment's secrets with the Vault's secrets. The Vault wins on a key collision. That one rule is what makes the division into four usable and not merely tidy. About vaults sets it out.

What happens next depends on the account. On a self-hosted instance, and on a hosted account without the egress broker, the merged secrets enter the sandbox as environment variables. On a hosted account with the broker on, a bound secret does not. The sandbox gets a placeholder, such as __github_token__, and the broker puts the real value on each request to the bound host. Where a secret comes from follows one secret through both paths.

Why an API for this, when you can run an agent in a sandbox by hand? Because the templates outlive the run. The machine, the secrets and the agent are rows you can list, diff, share and launch from code. Because the identity and the machine are separate, so one Environment can run as you, as a bot user, or as a customer. And because a run is a thing with an id, a status, a transcript and an event stream. A webhook, a cron job or another agent can start one and follow it.

Substitution

Each string value in an Agent config takes a ${VAR} reference. Fountain resolves it from the merged environment and vault secrets at spawn time.

Syntax Result
${VAR} The value of VAR from the merged map
$$ A literal $

Substitution is recursive, so it works inside maps and lists. It is also fail-complete. Fountain reports each absent variable at once, and not one for each attempt.

What Fountain does not have

There is no fifth primitive. Two things look like one and are not.

A team is not an object. A teammate is a Conversation bound to the reserved channel fountain:team. Read Agents as teammates.

A sandbox is not an object you create. Fountain gives you one when a Conversation starts. An ephemeral sandbox ends with its Conversation, and a persistent one stays as the Agent's own machine. You can list a sandbox, put a second Conversation on it with sandbox_id, and reset a persistent one. Read About sandboxes and the Sandboxes section of the API reference.

Where to go next