> ## Documentation Index
> Fetch the complete documentation index at: https://docs.causeloop.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Platform Architecture

> How the Causeloop frontend, API, AI layer, connectors, database, and realtime channel fit together.

Causeloop is a multi-tenant SaaS platform. This page describes the major components, how a request flows through them, and how tenant data stays isolated at every layer.

***

## High-level components

```mermaid theme={null}
flowchart TD
    Browser["Browser\n(Next.js — app.causeloop.ai)"]
    WorkOS["WorkOS AuthKit\n(Identity Provider)"]
    API["Backend API\n(FastAPI — api.causeloop.ai)"]
    AI["LLM Router\n(Anthropic Claude +\nOpenAI GPT-4o +\nMock fallback)"]
    DB["PostgreSQL\n(RLS tenant isolation)"]
    WS["WS Gateway\n(/v1/stream)"]
    Connectors["Connectors / Ingestion\n(70+ integrations)"]
    Kafka["Event Bus\n(Kafka — async)"]

    Browser -->|"1. WorkOS access token"| WorkOS
    Browser -->|"2. POST /auth/exchange"| API
    API -->|"3. Verify JWKS (RS256)"| WorkOS
    API -->|"4. Issue HS256 Bearer JWT"| Browser
    Browser -->|"5. All API calls (Bearer)"| API
    Browser -->|"WebSocket (?token=)"| WS
    API --> DB
    API --> AI
    API --> Kafka
    Connectors -->|"Webhook / poll"| API
    Kafka --> WS
    WS -->|"push {type, data}"| Browser
```

***

## Component descriptions

### Frontend — Next.js (app.causeloop.ai)

The product UI is a Next.js application authenticated via WorkOS AuthKit. After exchanging the WorkOS access token for a platform JWT, the frontend communicates exclusively with the backend API and a WebSocket for realtime updates.

**Key routes:**

| Route group                   | Purpose                                                        |
| ----------------------------- | -------------------------------------------------------------- |
| `/sign-in`                    | Sign-in page (WorkOS AuthKit — email/password or Google OAuth) |
| `/(onboarding)/onboarding`    | Post-signup onboarding wizard                                  |
| `/(platform)/dashboard`       | Main workspace dashboard                                       |
| `/(platform)/issues`          | Issue list and detail                                          |
| `/(platform)/patterns`        | Pattern list and detail                                        |
| `/(platform)/predictions`     | Risk signals and forecast                                      |
| `/(platform)/recommendations` | Ranked fix queue                                               |
| `/(platform)/integrations`    | Connector management                                           |
| `/(platform)/reports`         | Generated reports                                              |
| `/(platform)/settings`        | Workspace and member settings                                  |

### Backend API — FastAPI (api.causeloop.ai)

The backend is a FastAPI application serving all product functionality under `/v1`. It is stateless and horizontally scalable. Key responsibilities:

* Auth token issuance and verification
* The deterministic engine pipeline (below) — clustering, criticality, hazard fitting, alerting
* Business logic for issues, patterns, predictions, recommendations, clusters, and connectors
* AI orchestration (dispatching extraction/root-cause/narration jobs to the LLM Router)
* Tenant isolation via database RLS
* Async job coordination via Kafka stubs (Celery-based workers in production)
* Rate limiting (1,000 requests per minute per tenant by default)

**Stack:**

| Layer      | Technology                                                                       |
| ---------- | -------------------------------------------------------------------------------- |
| Runtime    | Python 3.11+                                                                     |
| Framework  | FastAPI 0.115+                                                                   |
| Validation | Pydantic v2                                                                      |
| Auth       | PyJWT — HS256 platform tokens, RS256 verification of upstream WorkOS/JWKS tokens |
| Middleware | Rate limiting, Idempotency-Key support                                           |
| Deployment | Docker, Railway, Render                                                          |

### LLM Router — AI providers

The LLM Router dispatches AI analysis tasks — attribute extraction, root-cause narration, recommendation drafting — to the configured provider. Pattern detection itself is **not** one of them: clustering, criticality, and hazard fitting are deterministic math (the engine pipeline below), and LLMs are never allowed to produce a score, probability, date, or dollar figure. Every LLM-derived field is labeled with an `origin`, and low-confidence extractions abstain into the review queue instead of guessing (see [Abstention & the review queue](/get-started/concepts#abstention--the-review-queue)). Providers are tried in order:

1. **Anthropic** — Claude models (`ANTHROPIC_API_KEY`)
2. **OpenAI** — GPT-4o / GPT-4o-mini (`OPENAI_API_KEY`)
3. **Mock** — Deterministic offline fallback (no keys required)

<Note>
  If both `ANTHROPIC_API_KEY` and `OPENAI_API_KEY` are absent, the API falls back to the mock provider automatically. Analysis results are plausible but not real.
</Note>

### Database — PostgreSQL with Row-Level Security

All product data lives in PostgreSQL 16. Multi-tenancy is enforced at the database layer using Row-Level Security (RLS):

* Every tenant table has a `workspace_id` column.
* Before executing any query, the API binds `app.current_workspace_id` on the session.
* RLS policies reject reads and writes that do not match the bound workspace ID.
* The application role (`causeloop_app`) does not have `BYPASSRLS`; a superuser role is kept separate for migrations only.

This means even a bug in the application layer cannot leak one tenant's data to another.

### Connectors and Ingestion

Connectors pull issues into a workspace from external tools. They operate in two modes:

* **Poll** — the backend fetches issues from the external API on a configurable schedule (`poll_interval_seconds`).
* **Webhook (inbound push)** — the external tool POSTs events to `POST /ingest/{connector_token}`, verified by HMAC signature.

Sync runs are tracked with start/end timestamps, record counts, and error details, accessible via `GET /connectors/{id}/sync-runs`.

### The engine pipeline — deterministic, one run at a time

`POST /engine/runs` is the single entry point for turning ingested issues into patterns, predictions, and financials. There is no separate "model training" step — one run executes the whole pipeline, stage by stage, and every stage's counters/durations land in the run's manifest:

```mermaid theme={null}
flowchart LR
    A["feature_forge"] --> B["graph_weave"]
    B --> C["leiden_partition"]
    C --> D["dsu_crosscheck"]
    D --> E["loop_anchor"]
    E --> F["term_namer"]
    F --> G["taxonomy_label"]
    G --> H["criticality_rollup"]
    H --> I["hazard_fit"]
    I --> J["alert_eval"]
```

| Stage                | What it does                                                                                                                                                 |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `feature_forge`      | Embeds narratives and derives structural/text features per issue.                                                                                            |
| `graph_weave`        | Builds the similarity graph — cosine, BM25, and structural edge components.                                                                                  |
| `leiden_partition`   | Community detection over the graph to propose pattern clusters.                                                                                              |
| `dsu_crosscheck`     | A deterministic disjoint-set cross-check against the Leiden result — the `stability.leiden_dsu_agreement` figure in the run manifest is this stage's output. |
| `loop_anchor`        | Reconciles clusters against prior runs and any active [pins](/get-started/concepts#pins) — pins win over the majority vote.                                  |
| `term_namer`         | Derives top-terms for each pattern from its member issues.                                                                                                   |
| `taxonomy_label`     | Assigns macro-theme / six-bone labels from the active `taxonomy` config.                                                                                     |
| `criticality_rollup` | Deterministic criticality scoring per the active `rubric` config.                                                                                            |
| `hazard_fit`         | Fits the `powerlaw_nhpp_hawkes_v1` point-process model per pattern — the source of every prediction, `T̂_R`, and crest alert.                                |
| `alert_eval`         | Evaluates alert rules (including `crest`) against the freshly fitted hazards.                                                                                |

Every run produces a **manifest** (`snapshot_hash`, `event_log_cursor`, `configs{kind→hash}`, `models{embed, extract_llm, rca_llm}`, seeds, code version) and a **stability report** (`leiden_dsu_agreement`, churn per pattern). `POST /engine/runs/{id}/replay` re-executes a prior run against the pinned manifest and returns `{identical: bool, diff_summary}` — the mechanism a CI gate uses to prove the pipeline is reproducible before every release. See [Event log & provenance](/get-started/concepts#event-log--projections) for how run outputs trace back to inputs.

### WebSocket Gateway — Realtime channel

The backend exposes a WebSocket endpoint at `/v1/stream`. Authenticated clients connect with their platform JWT as a query parameter (`?token=<jwt>`). The gateway pushes typed event envelopes to all sockets belonging to the same tenant:

```json theme={null}
{"type": "issue.updated", "data": {"id": "iss_01J...", "status": "mitigating"}}
```

Event types that reach the browser: `activity.created`, `issue.updated`, `pattern.updated`, `prediction.alert`, `recommendation.created`, and `job.updated` (for async job progress).

***

## Request and auth flow

<Steps>
  <Step title="User signs in via WorkOS AuthKit">
    The Next.js frontend delegates authentication to WorkOS AuthKit (`@workos-inc/authkit-nextjs`) — email/password or Google OAuth, hosted at `/sign-in` and `/callback`. On success, WorkOS issues a signed RS256 access token to the browser session.
  </Step>

  <Step title="Exchange for a platform token">
    The frontend calls `POST /v1/auth/exchange` with the WorkOS access token as `subject_token`. The backend verifies the token against WorkOS's JWKS endpoint (RS256), then runs admission: the identity must resolve to an existing membership, an accepted invitation, or (only when the workspace explicitly opts into domain JIT) a verified-domain match. Exchange never creates a user as a side effect otherwise — an unprovisioned identity gets a `403` and an `auth.login.denied` audit event. On admit, it issues a short-lived HS256 Bearer token bound to the resolved workspace.
  </Step>

  <Step title="API calls with Bearer token">
    All subsequent requests include the Bearer token in the `Authorization` header. Middleware resolves the token to `{user_id, workspace_id, role, scopes}` and binds the RLS session variable before any query runs.
  </Step>

  <Step title="Realtime updates via WebSocket">
    The frontend upgrades to a WebSocket connection at `/v1/stream?token=<jwt>`. The gateway verifies the token identically to the REST path, then pushes events for that tenant as they occur.
  </Step>
</Steps>

***

## Deployment topology

In production, each logical layer runs as an independent set of replicas behind a load balancer:

| Component                 | Replicas               | Notes                                                  |
| ------------------------- | ---------------------- | ------------------------------------------------------ |
| Backend API               | 2–8 (autoscale)        | Stateless; any replica handles any request             |
| WS Gateway                | 2–4                    | Per-tenant fan-out; replicas share a Redis pub/sub bus |
| Kafka consumers (workers) | 1–4 per topic group    | Pattern detection, AI jobs, notification delivery      |
| PostgreSQL                | Primary + read replica | RLS enforced on all connections                        |

For local development, `docker-compose.yml` runs the API, PostgreSQL, and Caddy (reverse proxy) as a single-box stack.

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/get-started/quickstart">
    Sign in and see your first insights in 10 minutes.
  </Card>

  <Card title="Deploy & Security" icon="shield" href="/deploy-security/overview">
    Self-hosting, environment variables, and security controls.
  </Card>
</CardGroup>
