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
{
"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
| Key | Meaning |
|---|---|
host, port | Where the web app and the API listen |
publicUrl | The address browsers and identity providers use, for callback URLs and setup links |
database | A Postgres URL. Leave it out for SQLite in data. |
data | The data folder for SQLite and local files |
namespace | Label for this server's sandboxes in Docker. Default serve. |
model | provider/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. |
approvals | Tools that wait for the session's owner (Approvals) |
autoMode | true 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) |
signIn | Sign-in methods to add at start: [{ id, kind, label?, config }]. Kinds: oidc, github-oauth. |
mcpEnv | Environment variables that agents' MCP servers may read with ${VAR}, besides PISTIS_MCP_* ones |
plugins | Plugin 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. |
flows | A folder of flow files (*.ts, *.mjs) (Flows) |
browser | Browser tools for sessions without an agent: "auto" (default) where the sandbox has a browser, "required" (refuse to start without one) or "off" (Browser). |
desktop | true 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). |
codemode | false 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. |
users | Optional name-to-token map for scripts |
sandboxes | The 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 |
hookSecret | Turns 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, metricsHost | Serve /metrics and /healthz |
Sandboxes
| Key | Meaning |
|---|---|
sandboxes.provider | docker, kubernetes or daytona |
sandboxes.image | The sandbox image |
sandboxes.allow, sandboxes.internet | Docker network access (Network access) |
sandboxes.cpu, memory, pids | Limits per sandbox. pids is Docker only. |
sandboxes.network | Docker: the network Pistis uses. Default pistis-int. |
sandboxes.max | The most sandboxes at once |
sandboxes.warm | Spare sandboxes kept ready per server |
sandboxes.relay | Docker: { url, container, handsUrl, adminKey } of a relay service that already runs, as in the compose file |
sandboxes.kubeNamespace, runtimeClassName, nodeSelector, tolerations, egress, egressExcept | Kubernetes settings. The Helm chart sets these. |
sandboxes.apiKey, apiUrl, target, snapshot, relayPort, publicRelayUrl | Daytona settings. Put a TLS proxy in front of relayPort. |
Environment
| Variable | Meaning |
|---|---|
PISTIS_SECRET_KEY | Encrypts secrets stored in the database. Required with Postgres. One server on SQLite without it creates one in <data>/secret.key. |
PISTIS_CLUSTER_KEY | Shared by several servers on one database, when fleet.clusterKey refers to it |
PISTIS_RELAY_KEY | The admin key of the relay (the service sandboxes connect to), when it runs separately |