Serve Many Tenants From One Environmentpublic

Last verified 25 Sep 2026

DigitalOcean Harness Runtime provides managed, hardware-isolated microVM sandboxes with built-in tools such as Chromium to run harnesses and execute arbitrary code. Rich lifecycle APIs preserve conversational history and working state across sessions, letting you pause, resume, and fork work to control costs and adapt to the nonlinear nature of agentic workflows. Scale complete agents such as Claude Code or use sandboxes independently for code execution, all through the same service. See What You Can Build for example use cases.

When your product is the agent, every customer needs the same environment and none of them should share one. This example saves a configuration once and starts a session per tenant from it, so onboarding a customer is one API call rather than a new spec, and no tenant can reach another tenant’s workspace.

It also covers the trick that makes evaluation affordable: warm an environment up once, checkpoint it, and fork the checkpoint instead of rebuilding the setup for every case.

Save the Environment Once

Start from a spec that describes the environment your product needs, with no per-tenant values in it. Save the following as product-agent.yaml:

name: product-agent
agent: opencode
size: mars-2vcpu-4gb
idle_timeout: 20m
env:
  HARNESS_INFERENCE_MODEL: openai-gpt-5.6-sol
secrets:
  HARNESS_INFERENCE_API_KEY: ${HARNESS_INFERENCE_API_KEY}
tools:
  - do.actions: [exa_web_search, exa_web_fetch]
permissions:
  default: allow
  rules:
    - tool: bash
      match: { command: "rm -rf *" }
      action: deny

Turn it into an Environment Config:

doctl harness-runtime config create --spec product-agent.yaml --name product-agent-v1

Credentials declared under secrets go to DigitalOcean Secrets Manager when the config is created and stay server-side. Sessions started from the config get them without you resupplying anything, which is what makes per-tenant provisioning a single call. That includes the model access key OpenCode uses against DigitalOcean Serverless Inference, so one key covers every tenant and the model usage for all of them lands on one DigitalOcean bill.

A config is immutable, and the version suffix in the name above is deliberate. Changing the environment means creating product-agent-v2 rather than editing v1, so a session can always be traced to the exact configuration it ran under. You cannot delete a config while sessions are still using it.

Start a Session Per Tenant

Give each session a name you can map back to a customer:

doctl harness-runtime config start-session product-agent-v1 --name tenant-acme

Each session is a separate microVM with its own workspace. To see everything one config has produced:

doctl harness-runtime config list-sessions <config-id>

Going the other direction, doctl harness-runtime show <session-name> reports the config a session started from, which is what you want when one tenant reports behavior the others do not.

Pause a session when its tenant is idle. The workspace is preserved and active compute charges stop, so an account that logs in weekly is not paying to sit in memory:

doctl harness-runtime pause tenant-acme

Fork a Warm Environment for Evaluations

Provisioning a session and letting it install dependencies and clone a repository is the slow part of an evaluation run, and it is identical for every case. Start a session from the config, let it warm up, then snapshot it:

doctl harness-runtime config start-session product-agent-v1 --name product-agent-eval
doctl harness-runtime checkpoint create product-agent-eval --label warmed

Fork the checkpoint into independent sessions, up to four at a time:

doctl harness-runtime fork product-agent-eval --from-checkpoint <checkpoint-id> --count 4

Each fork is a full session with its own sandbox, starting from the warmed state. Send a different case to each, compare results, and remove them. Repeat the fork command if you have more cases than one batch covers. To find the forks you created:

doctl harness-runtime list --parent-session-id product-agent-eval

The same mechanism covers the demo-environment case: warm up a configured workspace, checkpoint it, and fork a fresh copy per prospect.

Adapt It

To do this Change this
Vary behavior per tenant without a new config Keep the config fixed and vary the prompt. Configuration belongs in the environment; task belongs in the prompt.
Give each tenant its own credentials Create a config per tenant. Secrets are captured at config creation, so they cannot be overridden per session.
Offer tenants a choice of model HARNESS_INFERENCE_MODEL is part of the config, so each model needs its own. Name them for the model rather than the tenant, and map tenants to configs on your side.
Run your own agent instead of a listed adapter Package it as an OCI image and register it. See Use a Custom Template.
Run a framework agent Set agent: langgraph. See Run a LangGraph Agent.
Undo a bad run instead of forking Roll the session back to a checkpoint with doctl harness-runtime rollback.
Drive this from code rather than the CLI Every command here has an API equivalent. See the Harness Runtime API reference.

We can't find any results for your search.

Try using different keywords or simplifying your search terms.