Running the runtime
What an orchestrator probes to decide the container is alive, what the runtime puts in the environment for your code, and how the same contract behaves under a local run.
Health and liveness
The workspace splits liveness from health:
| Route | Behaviour |
|---|---|
GET /live |
Instant 200 { status: "ok" }. No probes, no awaits: the platform liveness signal. |
GET /health |
Runs every subsystem probe in parallel. 200 { status: "ok", checks } or 503 { status: "degraded", checks }. |
The deep /health reports the subsystems your workspace depends on. Each
check is { "status": "ok" }, or { "status": "error", "detail": "…" } with
the reason it failed:
{
"status": "ok",
"checks": {
"database": { "status": "ok" },
"redis": { "status": "ok" },
},
}A single failing subsystem degrades the whole response to 503. The
platform uses /live for the liveness probe so a slow subsystem never gets
the container recycled by mistake.
Both routes belong to the deployed workspace image. stackbone dev serves a
lighter GET /api/health instead, which answers { "status": "ok" } as soon
as the emulator is up.
Runtime environment
The runtime injects these into the container as a behavioural contract. You read them, you never set them:
| Variable | What it is |
|---|---|
STACKBONE_INSTALLATION_ID |
the install this container serves |
STACKBONE_API_URL |
the control-plane URL the SDK talks to |
DATABASE_URL |
the per-install Postgres connection (the agents' + workflows' data plane) |
WORKFLOW_REDIS_URL |
the per-install Redis backing durable workflow runs |
MODEL_PROVIDER_API_KEY / MODEL_PROVIDER_BASE_URL |
the model gateway credentials an agent reads |
STACKBONE_SECRET_KEY |
the per-agent key every stored secret is encrypted with |
STACKBONE_S3_* |
endpoint, keys, bucket and region of the object store client.storage writes to |
STACKBONE_S3_FORCE_PATH_STYLE sits in that last group and decides how the
bucket is addressed. It defaults to true, which puts the bucket in the path
(https://host/bucket/key). Set it to false for a backend that only answers
to the bucket-as-subdomain form, such as AWS S3 or Railway Buckets.
Most code never reads these: the ambient stackbone client
(stackbone.database, .secrets, .config, …) wires them for you.
The image binds 8080, or PORT when the host sets one, so a platform that
assigns the port needs no extra configuration. A PORT that is not a usable
port number fails the boot instead of falling back, since binding 8080 anyway
would leave the platform health-checking a port nothing listens on. See
What you set on the deployed container.
The runtime also serves
GET /api/contract, the Stackbone Agent Protocol handshake that advertises the agent-facingstackbone.*capabilities (database, storage, rag, secrets, …). That is the SDK capability handshake; it is distinct from the HTTP endpoints above that you drive (chat, workflows, runs, hooks).
Local development
stackbone dev brings up the same contract on http://127.0.0.1:4242: the
chat endpoints and the workflow start/chat routes, all agents running
in-process behind one server. The local stack is Postgres + Redis + MinIO.
There is nothing to install or sign by hand, and the emulator accepts any
non-empty bearer key.
See Local development for the local loop and Getting started to scaffold a workspace.