The handbook
TroubleshootingLocal developmentDeploymentProvision a new clientStandalone deploymentUpgradesArchitecture
Operate

Architecture

A one-page mental model of how the console fits into the AcasoOS platform. The full specification lives in specs/003-management-console/ of the monorepo.

High-level

https://os.aca.so
Browser Client
  • Sidebar + TopBarConsole interface shell
  • Connection switcherMulti-tenant / Multi-env router
  • Static-export Next.jsClient-only React bundle
no BFF • no proxy
HTTPSBearer session token
zuri-os instance(s)/v1/* endpoints
Your Infrastructure
  • DataHub + AgentHubCore service layer & agent runtime
  • PostgresRLS, pgvector, Apache AGE (graph)
  • RedisCache & pub/sub events
  • LangGraph checkpointerAgent state persistence

There is no console-side backend. The browser talks directly to whatever AcasoOS URL you configure in the Connect form.

Layers

AcasoOS is structured in three layers:

  • DataHub (packages/datahub) — structured data, graphium memory, scope catalog, users, roles, audit log.
  • AgentHub (packages/agenthub) — agent runtime, chat with the AG-UI protocol, admin endpoints (tenants, keys, health, overrides), the /v1/auth/session exchange.
  • AppHub (planned) — end-user-facing apps built on AgentHub. Out of scope for v1.

The console targets DataHub and AgentHub. In dev, AgentHub mounts every DataHub router too, so a single URL serves the whole surface.

Database isolation

Every tenant-scoped table has ENABLE plus FORCE ROW LEVEL SECURITY. The application connects as the non-privileged acaso_app role (no superuser, no BYPASSRLS), so the policy fires on every query.

The auth middleware binds these Postgres session vars on every request, and RLS policies read them to decide row visibility:

  • app.current_tenant
  • app.current_user
  • app.current_scopes

Migrations and DDL run via a separate ADMIN_DATABASE_URL connecting as the acaso superuser. Application code never touches this connection at runtime.

Memory model

Graphium organises agent context as a four-level taxonomy: Family → Genus → Specimen → ContextStatement. Statements get vector embeddings with HNSW indexes for ANN search.

The structural taxonomy is mirrored into the tenant's AGE graph as :Family, :Genus, :Specimen vertices, so Cypher traversal queries see the structure. See Concepts: Context (graphium).

Cultivators write into this same memory autonomously: on each ingest event they propose Context Statements, and every committed statement is stamped with a provenance_run_id back to the run that wrote it. See Concepts: Cultivators.

Design system

The console uses Syntropic, acaso's own design system. Tokens are vendored from colors_and_type.css; the font is Sora; icons are Phosphor with outline-bold as the default weight and fill reserved for active states.

The layout is a 240–280px sidebar, 68px top header, main content in the right column, right-side sheet for detail panels. Centre modals are reserved for destructive confirmations.

State and HTTP

  • TanStack Query for all server state. Cache keys include the connection id so switching connections invalidates the cache without data leaking across them.
  • Axios for the HTTP layer with two interceptors: attach the session token; handle 401 by triggering the session-expired flow.
  • Zustand for the connection store, persisted via the persist middleware backed by sessionStorage.
  • nuqs for URL state of filters, pagination cursors, and tab selections.

What the console does not do

  • Hold long-lived keys. The exchange is one round trip; the key is wiped from memory afterwards.
  • Persist anything to localStorage. v1 uses sessionStorage only.
  • Proxy traffic. There is no console-side request router; every API call originates in the user's tab.
  • Define agents in the database. Agents are code-declared; tenant customisation goes through overrides.
PreviousOperateUpgrades