Skip to main content
The control plane is the FastAPI service that stores agent definitions and tokens and relays the serve/chat WebSockets. Prefer not to run it yourself? Use Hexgate Cloud — it’s the same service, hosted. Self-host when you need it inside your own infrastructure.

Run it

The default support-bot project is seeded on first boot with three agents — default (broad access, side-effects gated by approval_required), read_only (everything mutating denied), and support_bot (the role-aware demo that returns different answers per support / billing role).

Database — SQLite for dev, Postgres for production

make platform-api uses a local SQLite file — zero setup, ideal for dev and the test suite. For production, set DATABASE_URL to a Postgres DSN; bare postgres:// URLs are normalized to the asyncpg driver. A local Postgres is in the dev compose:
DATABASE_URL is read from the real environment or platform/api/.env. A managed Postgres (e.g. Scaleway, RDS) needs SSL in the DSN, e.g. …/hexgate?ssl=require. The SQLite DB lives at platform/api/hexgate.db; delete it and restart to wipe dev state.
Schema management. Tables are created with SQLAlchemy create_all; there is no migration runner, so a model change is applied by recreating the schema (make postgres-reset locally) rather than by an incremental migration. Plan schema upgrades as a maintenance step.

Endpoints

  • POST /v1/projects/:id/tokens — mint a dev token (returned in full once)
  • GET /v1/projects/:id/tokens — list dev tokens (masked)
  • DELETE /v1/projects/:id/tokens/:tid — revoke
  • GET /v1/projects/:id/agents — list agents with their YAMLs
  • GET /v1/projects/:id/agents/:name — read one agent
  • PUT /v1/projects/:id/agents/:name — save agent / policy / system YAMLs
  • POST /v1/agents — register a manifest (hexgate register / serve auto-register)
  • GET /v1/agents/:name — read an agent’s current policy (the hexgate serve fetch)
  • WS /v1/serve — producer socket (the hexgate serve CLI dials here)
  • WS /v1/projects/:id/chat — consumer socket (the dashboard Playground dials here)
  • POST /v1/traces — OTLP/HTTP span ingest for audit, usage and ban events. Served by the collector, not by this API: on the same origin only because the reverse proxy routes that one path to the collector’s port. See below.
The /v1/agents…, /v1/serve and /v1/traces routes are not project-scoped in the path — the project is resolved from the bearer token (carried in the WebSocket subprotocol for serve), so a fty_live_… key both authenticates and selects the project. Only the dashboard-facing routes (/projects/:id/…, chat) take an explicit project id.

The full stack

uvicorn alone gives you agents, tokens, policy and the Playground. The audit trail needs three more processes — the OTLP collector, Redpanda as the span buffer, and the span-enricher that writes ClickHouse — plus a reverse proxy rule sending /v1/traces to the collector instead of the API. Locally:
For a deployed stack, platform/docker-compose.deploy.yml runs all of it as one Compose project per environment and platform/DEPLOY.md is the runbook (ports, secrets, the proxy rule, and make platform-smoke to verify a live stage). How events move through these services is described in audit log.

Health & readiness

GET /health is a dependency-free liveness probe. GET /ready reports downstream health — once ClickHouse is up it returns "clickhouse": "ok". See audit log for the audit store and email for outbound mail configuration.

Point the SDK at your instance

The key and URL are coupled: a fty_live_… key only verifies against the platform instance that minted it.