Open source · self-hosted · AGPL-3.0-or-later

Give your app a computer it can talk to.

Send a prompt. A sandbox wakes up with the repos, tools and credentials it needs, an agent gets to work, and the answer streams back. Build an engineering workbench around it, hide it behind your product, or make something we have not imagined yet.

Fountain is the open-source conversational API underneath. Run it on your infrastructure, keep the data in your database, hold the keys, and change anything.

Your server · your database · your keys · your agents

A product, workbench or automation sends a prompt to Fountain. Fountain assembles the reusable configuration, then wakes a sandbox containing the repository, tools, credentials and running agent.
Product agent hidden
Workbench agent visible
Automation no screen
Fountain

one conversational API

Sandbox

repo · tools · config · credentials

Running agent

fixing test_user_login.py … live

Put the agent wherever the idea needs it.

Keep it on the screen while engineers steer every move. Put it behind a file upload, a button or an API and return only the result. Let a webhook wake it up when nobody is watching.

These look like different products to the customer. Underneath, they all need the same thing: a machine that can pick up a conversation and keep working after you close your laptop.

Agent on the glass

Build the engineering workbench.

Show the thread, shell, diff and event stream. Let people steer the work while it happens.

Agent behind the interface

Ship the outcome, not the agent.

Your customer asks for a brief, a chart or a change. Your product returns it. The agent stays plumbing.

Agent off on its own

Start work from anything.

A webhook, cron job, CI run or another agent can start a conversation and follow it to the result.

The reusable pieces

Set up the machine once. Start it with a prompt.

Fountain keeps the machine, credentials, agent configuration and live work separate. Change one without rebuilding the rest, then reuse the same setup anywhere your product needs it.

Environment

The machine: repositories, packages, env vars and setup scripts.

Vault

The credentials a run is allowed to use, kept apart so rotating a token is not a machine edit.

Agent

The runtime, model, skills and tools, under one name your software can call.

Conversation

The running work: prompts, streamed output and the sandbox behind them.

Your first agent

Define the setup once. Your product sends the prompts.

1

Describe the machine once. Repositories, packages, env vars and setup scripts. The Environment is reusable across agents and runs.

setup.ts environment
import { Fountain } from "@agentshit/fountain-sdk";

const fountain = new Fountain(); // FOUNTAIN_API_KEY

const environment = await fountain.environments.create({
  name: "app",
  repositories: [{
    url: "https://github.com/acme/app",
    mount_path: "/work/app",
  }],
  setup_script: "cd /work/app && npm install",
});
2

Add credentials only when a run needs them. A Vault is an optional set of environment-variable overrides. Write its values separately, then attach it only to runs that need them.

setup.ts vault
const vault = await fountain.vaults.create({ name: "ci-bot" });

await fountain.vaults.secrets.set(
  vault.id,
  "GITHUB_TOKEN",
  process.env.GITHUB_TOKEN!
);
3

Name the agent and its tools. Pick the runtime and model, add skills and MCP tools, attach the Environment, and allow the Vault callers may opt into.

setup.ts agent
await fountain.agents.create({
  name: "reviewer",
  runtime: "claude",
  model: "anthropic/claude-sonnet-5",
  environment_id: environment.id,
  allowed_vault_ids: [vault.id],
  skills: [{ source: "obra/superpowers", ref: "v2.1.0" }],
  mcp_servers: {
    deepwiki: {
      type: "http",
      url: "https://mcp.deepwiki.com/mcp",
    },
  },
});
4

Send a prompt. Attach the Vault when this run needs its GitHub token; leave it off otherwise. Fountain streams the work as it happens and keeps the conversation ready for the next prompt.

run.ts prompt
import { Fountain } from "@agentshit/fountain-sdk";

const fountain = new Fountain(); // FOUNTAIN_API_KEY

const run = await fountain.run(
  "Fix the failing test and open a PR",
  { agent: "reviewer", vault: "ci-bot", channelId: ticket.id }
);

console.log(run.text);

Interfaces

Talk to it from whatever you are building.

Use Fountain’s API and SDK in your product. Speak OpenAI-compatible chat from existing tools. Plug into editors over ACP or build a live interface over AG-UI. Every door reaches the same agents, conversations and event stream.

Bring the runtime you want.

Choose the coding agent the sandbox runs. Every client-facing interface sees the same shape.

  • Claude Code
  • Codex
  • Gemini CLI
  • OpenCode

Use the model provider you trust.

Bring your own credentials. Your model provider bills you directly; Fountain never marks up tokens.

  • Anthropic
  • OpenAI
  • Google Gemini
  • Claude subscription

Run on the sandbox you choose.

Where the agent runs. A hosted provider, or a runner on hardware you own that dials out over WebSocket.

  • Sprites
  • E2B
  • Daytona
  • Your own machine

Tools and systems

MCP inside. Webhooks outside.

Attach any stdio or HTTP MCP server. Use built-in credential bindings to keep provider tokens out of the sandbox.

Anthropic Cloudflare Cohere Datadog DeepSeek Discord Fireworks AI Google Gemini GitHub GitLab Groq Linear Mistral AI Notion NPM Github NPM registry OpenAI OpenRouter PagerDuty Perplexity Postmark Resend SendGrid Sentry Shopify Slack Stripe Supabase Telegram Together AI Vercel xAI (Grok) + any MCP server
Browse every protocol and integration →

Own the data

The conversation stays on your server.

Prompts, events, configuration and the audit trail land in your Postgres. Logs stay on stdout. Metrics stay on a private listener. Trace and error export turn on only when you configure a destination.

Metrics

Local by default

Prometheus → Grafana

Scrape routes, database timings, provisioning, turn latency and sandbox state from the private metrics listener. The repo includes dashboards and alerts.

METRICS_PORT=9568

Traces

Off until configured

OpenTelemetry → your OTLP backend

Export request, provisioning and turn spans over OTLP. Point the standard exporter variables at Honeycomb, Grafana Tempo or another compatible collector.

OTEL_EXPORTER_OTLP_ENDPOINT=…

Errors

Off until configured

Sentry API → Sentry or GlitchTip

Send grouped crashes without cookies, IP addresses or request bodies. Unset the DSN and the SDK stays inert; nothing is buffered for later.

SENTRY_DSN=…

Health

/health reports liveness. /health/ready reports whether the instance can receive traffic.

Import the included dashboards and alert pack →

Own the stack

Start with one machine. Grow when you need to.

Begin with Docker Compose and the published release image. If the workload grows, run a clustered set of replicas against the same Postgres. The deployment shape changes; the API does not.

Or run the OCI image anywhere that can keep a Phoenix process and Postgres alive. Compare deployment requirements →

Make it yours

Fork it. Extend it. Build the thing only you would build.

Host the apps and API yourself. Keep conversations and configuration in your Postgres. Hold the encryption keys. Run sandboxes through Sprites, E2B, Daytona or machines on your own network. The engine and apps are open for you to take apart and reshape.