Pistis

Configuration

Every key in pistis.json and the environment variables Pistis reads.

pistis serve --config pistis.json reads one file. ${VAR} anywhere in it is filled from the environment, so the file holds no secrets. A missing variable or an unknown key stops the start and names it.

Example

pistis.json
{
  "host": "0.0.0.0",
  "port": 7777,
  "publicUrl": "https://pistis.example.com",
  "database": "${DATABASE_URL}",
  "model": "anthropic/<model-id>",
  "approvals": ["publish"],
  "signIn": [{ "id": "corp", "kind": "oidc", "label": "Corp SSO",
               "config": { "issuer": "https://login.example.com", "clientId": "pistis", "clientSecret": "${OIDC_SECRET}" } }],
  "sandboxes": { "provider": "daytona", "apiKey": "${DAYTONA_API_KEY}", "relayPort": 8080,
                 "publicRelayUrl": "wss://relay.example.com" },
  "metricsPort": 9464
}

Keys

KeyMeaning
host, portWhere the web app and the API listen
publicUrlThe address browsers and identity providers use, for callback URLs and setup links
databaseA Postgres URL. Leave it out for SQLite in data.
dataThe data folder for SQLite and local files
namespaceLabel for this server's sandboxes in Docker. Default serve.
modelprovider/model-id new sessions start on (or PISTIS_MODEL). The provider's key comes from its usual environment variable or the Models page. Leave it out for the first model with a key.
approvalsTools that wait for the session's owner (Approvals)
autoModetrue lets people send a message in Auto mode: its waiting steps run at once, approved by the sender. Default false.
mcp{ servers: [...] }: MCP servers for sessions without an agent (MCP servers)
signInSign-in methods to add at start: [{ id, kind, label?, config }]. Kinds: oidc, github-oauth.
mcpEnvEnvironment variables that agents' MCP servers may read with ${VAR}, besides PISTIS_MCP_* ones
pluginsPlugin packages to load (Plugins)
authorizer{ kind, config }: a policy from a plugin. It can only take permissions away (Policies).
secrets{ kind, config }: where secrets live. Default { "kind": "sealed" }: Pistis's own database, encrypted under PISTIS_SECRET_KEY; { "kind": "vault" } is HashiCorp Vault, and a plugin can offer another (Secret stores). A store that can't be reached stops the start.
flowsA folder of flow files (*.ts, *.mjs) (Flows)
browserBrowser tools for sessions without an agent: "auto" (default) where the sandbox has a browser, "required" (refuse to start without one) or "off" (Browser).
desktoptrue gives sessions a virtual display and computer tools; Docker sandboxes then use pistis/desktop:dev unless you set image (A whole desktop). Default false.
screen{ "returnAfter": "2m" }: when someone took over a session's screen and left without handing back, control returns to the agent this long after they were last there. At least 5s; default 2m (Take over).
codemodefalse turns off the agent's codemode tool for new sessions. Default true.
repo{ url, token? }: one repository every session works on, at /workspace/repo. A session that names a repository of its own is refused. Leave it out to use connected code hosts.
usersOptional name-to-token map for scripts
sandboxesThe sandbox provider and its settings (below)
lifecycle{ pauseAfter, stopAfter, deleteAfter } for idle sandboxes. Defaults 2m, 30m, 7d.
fleet{ shards, brainId, url, clusterKey } to run several servers on one database. Never change shards after the first start.
workers{ relayUrl }: the public wss:// address your own machines connect to
hookSecretTurns on signed webhooks at POST /hooks/:key
slack{ botToken, apiUrl? }: connects Slack. The Slack app acts for linked people, and Pistis sends Slack notifications with the bot token.
metricsPort, metricsHostServe /metrics and /healthz

Sandboxes

KeyMeaning
sandboxes.providerdocker, kubernetes or daytona
sandboxes.imageThe sandbox image
sandboxes.allow, sandboxes.internetDocker network access (Network access)
sandboxes.cpu, memory, pidsLimits per sandbox. pids is Docker only.
sandboxes.networkDocker: the network Pistis uses. Default pistis-int.
sandboxes.maxThe most sandboxes at once
sandboxes.warmSpare sandboxes kept ready per server
sandboxes.relayDocker: { url, container, handsUrl, adminKey } of a relay service that already runs, as in the compose file
sandboxes.kubeNamespace, runtimeClassName, nodeSelector, tolerations, egress, egressExceptKubernetes settings. The Helm chart sets these.
sandboxes.apiKey, apiUrl, target, snapshot, relayPort, publicRelayUrlDaytona settings. Put a TLS proxy in front of relayPort.

Environment

VariableMeaning
PISTIS_SECRET_KEYEncrypts secrets stored in the database. Required with Postgres. One server on SQLite without it creates one in <data>/secret.key.
PISTIS_CLUSTER_KEYShared by several servers on one database, when fleet.clusterKey refers to it
PISTIS_RELAY_KEYThe admin key of the relay (the service sandboxes connect to), when it runs separately

On this page