Pond — Deployment and Usage Manual
This manual tells you how to deploy Pond and how to use it.
For the system design, read docs/concepts.md.
1. System description
Pond is an engine that runs AI coding agents on a codebase. Pond has three types of process:
- Control plane — serves the
/v1HTTP API and owns the Pond database. - Orchestrator — polls the control plane for jobs. One orchestrator serves one pool.
- Worker — polls the orchestrator and runs the agents.
All connections go inward: consumer → control plane, orchestrator → control plane, worker → orchestrator. Pond does not dial out. Because of this, pools can operate behind NAT.
2. Requirements
- Python 3.11 or later, and
uv. - Docker, for Postgres and for sandboxed jobs.
- macOS or Linux. Windows can use
install.ps1(Section 4).
3. Quick local deployment — ./cast
Use ./cast for a local stack. All state goes to .pond-local/.
- Generate the keys:
./cast env - Start Postgres, the migrations, and the control plane:
./cast dev - Add a worker pool:
./cast pool - Make sure that the stack is up:
./cast status
To stop the stack: ./cast down. To also stop Postgres: ./cast down --postgres.
NOTE: If the control plane does not start, set AUTH0_DOMAIN and AUTH0_AUDIENCE
in .pond-local/env. For local use, example values are sufficient.
4. Full containerized deployment
Run ./install.sh (Windows: install.ps1).
This starts the full stack in Docker: Postgres, MinIO, the control plane,
an orchestrator, and one sandbox worker. This mode does not need Python on the host.
5. Manual deployment (production)
5.1 Control plane
- Start Postgres:
docker compose -f docker-compose.pond.yml up -d - Copy the example configuration:
cp .env.example .env - Set
POND_SOURCE_KEY,POND_SERVICE_TOKEN, and theAUTH0_*values in.env. - Install the dependencies:
uv sync - Apply the database migrations:
uv run alembic upgrade head - Start the server:
uv run uvicorn app.main:app --port 8001
CAUTION: Do not lose POND_SOURCE_KEY. Without it, Pond cannot seal or unseal
credentials, and runs that need credentials stop with an error.
5.2 Orchestrator — one for each pool
- On the control plane, get a pairing code:
pond pool pairing-code - On the pool host, redeem the code:
python3 swarm.py pair --code <code> --backend <pond-url> - Start the orchestrator:
python3 swarm.py serve --bind 127.0.0.1:8080 --state-dir ./swarm-state
WARNING: The orchestrator speaks plain HTTP. Do not bind it to a public address
without an encrypted overlay (WireGuard, Tailscale) or a TLS tunnel. A bind that
is not loopback needs the flag --insecure-no-tls.
5.3 Worker — one or more for each pool
-
Make a single-use enrollment code:
pond pool enroll-code -
Start the worker:
python3 swarm.py worker \ --orchestrator http://<orchestrator-host>:8080 \ --enroll-code <code> \ --capabilities harness.codex,sandbox.docker
The worker keeps its secret in ~/.cache/swarm/.
After the first start, the worker does not need a new code.
6. Configuration
The most important settings. For the full list, read docs/reference/configuration.md.
| Variable | Function |
|---|---|
POND_DATABASE_URL | Connection URL for Pond’s Postgres database. |
POND_SOURCE_KEY | Fernet key that seals credentials. Required. |
POND_SERVICE_TOKEN | Shared token for a trusted first-party consumer. |
POND_REQUIRE_SANDBOX | If true, Pond rejects the sandbox profile none. |
POND_BUNDLE_BUCKET | S3 bucket for source bundles. If empty, bundle delivery is off. |
AUTH0_DOMAIN, AUTH0_AUDIENCE | Authentication for the operator console. |
7. Usage
7.1 Configure the CLI
- Install the CLI:
uv tool install '.[cli]' - Set the environment:
export POND_URL=http://localhost:8001 POND_TOKEN=<service-token> - Test the connection:
pond status
7.2 Register a harness, a model, and a credential
A harness tells Pond how to start an agent. A model points to an LLM. A credential holds an API key. Pond keeps the API key away from the agent.
- Show the available harness presets:
pond harness presets - Register a harness from a preset:
pond harness from-preset <preset>Or register from a file:pond harness create -f harness.json - Register a model:
pond model create --helpshows the options. - Store an API key:
pond credential set --helpshows the options.
NOTE: A model that has a --capability value adds that capability to the
requirements of each job. The worker must advertise all required capabilities.
If it does not, jobs stay in the queue.
7.3 Submit a run
pond run submit --project <uuid> --source <git-url> \
--harness <key> --model-ref <model> --wait
The flag --wait makes the CLI poll until the run is complete.
To examine a submission without a start: pond run preflight.
7.4 Monitor a run
- Status:
pond run get <run-id> - Logs:
pond run logs <run-id> - Output files:
pond run artifacts <run-id> - All runs:
pond run list
7.5 Attach to a live agent
If the harness is attachable, you can connect a terminal UI to the agent:
pond run attach <run-id>
- If the stage has no explicit prompt, the agent starts idle. You attach and give the first instruction.
- If the stage has an explicit prompt, the agent does the first turn itself. You can attach and steer it later.
7.6 Cancel a run
pond run cancel <run-id>
8. Safety
A sandbox profile sets the isolation for a job:
none— no isolation. Only for development.untrusted-code-read— read-only checkout. The agent can only reach the model API.untrusted-code-write— writable copy of the checkout. Egress is limited to an allowlist.
WARNING: Do not use the profile none for code that you do not trust.
In production, set POND_REQUIRE_SANDBOX=true.
The agent does not receive real API keys. A broker on the worker adds the real key to each model request. Source code travels to the worker as an encrypted bundle. Only the worker that claimed the job can decrypt it.
9. Maintenance
- After each upgrade, apply the migrations:
uv run alembic upgrade head - Health check:
pond health - Worker inventory:
pond pool workers - Local performance report:
./cast bench(report goes to.pond-local/bench/) - Tests:
uv run pytestneeds a live Postgres.
CAUTION: The test suite erases data in the database that POND_DATABASE_URL
points to. Point the tests at a database that is separate from production.