How it works What it is not Where it sits Quick start Guide GitHub Hub

Hosting control plane

Deploy a capability agent, get an isolated process.

HESTIA runs AIMarket capability providers on the operator’s machines. You POST a deploy request; it starts the agent as an isolated process, puts it behind a stable URL with a signed invoke edge, and announces it to the Hub only when you ask.

$ uv run --project . python -m hestia
AGENTSone isolated process each
ISOLATIONthe edge is the only way in
HUBreached only by announce
DRAG TO ORBIT · SCROLL TO ZOOM
SIM
IDLE
206
Tests
91%
Branch coverage
Ed25519
Response signature
5
Doc languages
cap-drop
Container defaults

Request → admission → process → edge → receipt

How a deploy works

Six steps from an HTTP request to a signed response. None of them fire on their own: nothing starts because a build went green.

01

Deploy request

POST /v1/tenants with a bearer token. Body: slug, capability spec, source — either an inline handler or a pinned image digest — and the owner public key. An empty HESTIA_DEPLOY_TOKEN refuses every write, including one that supplies a token.

02

Admission

Inline handler source is screened by AST before it runs: no os, subprocess, eval, open, getattr, no dunder names, no str.format attribute walks. A pinned image must match an allow-listed sha256 digest. THEMIS can refuse the capability here.

03

Start

Stub runtime: a subprocess in its own 0700 directory with operator secrets stripped from its environment. Docker runtime: cap-drop ALL, read-only rootfs, no-new-privileges, a pids limit, an internal network and a digest-pinned image.

04

Invoke edge

The agent listens at /t/{slug} for invoke and health. The same call is also on the hearth at /ai-market/v2/invoke, routed by capability_id — that door is the AIMarket SKU bus too (deploy, status, list, stop; deploy and stop need the operator token). The /t/{slug} edge forwards the method, body and query string, and passes Content-Type and Accept — never Authorization. Request bodies are capped by counted bytes, so a chunked body cannot walk past the limit.

05

Receipt

Every response carries an Ed25519 signature over the result, the capability id and the SHA-256 of the input. The provider public key is published at /.well-known/ai-market.json, so a caller can verify without asking the host.

06

Announce — optional

The Hub catalogue changes only after an explicit announce. Until then the agent is running and reachable at its own URL, and listed nowhere. /v1/hearth reports what this host is running; that is a roster, not a catalogue.

What HESTIA is not

Factory writes the source. THEMIS admits at publish time. Hub is the catalogue. ARGUS is the client. HESTIA is only the host the agent runs on — and it is easier to use once you know what it refuses to be.

Not a catalogue

A hestia URL is not a Hub listing. /v1/hearth returns the agents this one host is running. Nothing about it is a marketplace index.

roster, not index

Not a build system

Nothing starts because a pipeline finished. A deploy is an authenticated HTTP request that a person or an agent makes on purpose.

explicit deploy

Not a sandbox

AST screening is admission control, not confinement: an admitted handler still executes in the agent process. The stub runtime cannot cap CPU or memory. For enforced limits run HESTIA_RUNTIME=docker.

stated, not implied

Not multi-node

Production ledger is Postgres. HESTIA_REPLICAS greater than 1 is refused: a shared ledger is not a farm, and there is no sticky runtime-owner. Agents still run on this host.

fails closed

One layer of the stack

Where HESTIA sits

Each box below is a separate service with its own failure mode. Collapsing them is the usual source of confusion about where an agent actually lives.

Factorywrites the source
THEMISadmits at publish
HESTIAruns the process
Hublists it
ARGUScalls it

Quick start

Python 3.11 or newer. The control plane listens on :9480 and the operator console is at /ui/. Set HESTIA_DEPLOY_TOKEN first: with it empty every write is refused, which is the intended default rather than an error.

cd hestia
export HESTIA_DEPLOY_TOKEN=$(python3 -c 'import secrets; print(secrets.token_urlsafe(24))')
uv sync --extra dev --project .
uv run --project . python -m hestia          # control plane on :9480

# deploy an agent, then call it through the edge
curl -sS localhost:9480/v1/tenants \
  -H "Authorization: Bearer $HESTIA_DEPLOY_TOKEN" \
  -H 'Content-Type: application/json' -d @tenant.json
curl -sS localhost:9480/t/demo-echo/invoke \
  -H 'Content-Type: application/json' -d '{"text":"ping"}'
# -> {"ok":true,"result":{...},"provider_pubkey":"...","signature":"..."}