BoardPulse AI is built around a strict separation between the interface layer, the orchestration core, and the data layer. Every natural-language question travels through a deterministic five-node LangGraph graph before a single byte of SQL reaches your database. This page explains each layer and how they connect.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/FloxTBoTyy/BoardPulse-AI/llms.txt
Use this file to discover all available pages before exploring further.
Services
The full deployment runs six Docker services defined indocker-compose.yml:
| Service | Image / Framework | Default port | Role |
|---|---|---|---|
api | FastAPI (Python) | 8000 | Core backend — orchestration, SQL execution, exports |
admin | Next.js | 3001 | Administrative panel for workspace and schema configuration |
postgres | PostgreSQL 16 | 5432 | Internal config store, audit log, and demo data |
redis | Redis 7 | 6379 | Cache and job queues |
openwebui | Open WebUI | 3002 | Conversational chat interface |
ollama | Ollama | 11435 | Local LLM inference (optional, local-models profile) |
Ollama is only started when you use
docker compose --profile local-models up. All other services start without it.Conversation graph
Every query sent toPOST /api/v1/chat/query is processed by a LangGraph StateGraph defined in backend/app/graphs/chat_graph.py. The graph runs five nodes in a fixed linear sequence with no branching:
ChatState object. Here is what each node does:
load_context
Calls metadata_service.get_workspace_context() to retrieve the workspace’s approved table list, schema metadata, and dialect information. This context is passed to every subsequent node — the AI never sees tables that are not on the approved list.
draft_query
Calls model_router.draft_query() with the user’s message and the loaded context. The model router selects a backend (cloud, local, or mock) based on the preferred_provider field in the request, then uses the chosen LLM to produce a candidate SQL query and a plain-language answer draft.
validate_query
Passes the candidate SQL through sql_guard.validate_read_only_query(). This is the SQLGlot-based guardrail layer — see SQL guardrail layer below.
execute_query
Runs the validated SQL against your source database in strict read-only mode via query_service.execute_read_only_query(). Also builds CSV/XLSX exports, assembles a chart specification if the data shape supports it, and composes the final answer text.
finalize_response
Appends any warnings collected during the run (for example, if row results were capped by QUERY_MAX_ROWS) to the answer text, then returns the complete ChatResponse.
The
executed_sql field in every API response contains the exact SQL that ran — nothing is hidden. You can use this for auditing or to reproduce queries directly against your database.Model router
The model router (backend/app/services/model_router.py) decouples the graph from any specific LLM backend. Three providers are supported:
| Provider | Configuration | Use case |
|---|---|---|
mock | No API key required | Development, testing, CI |
cloud | Set OPENAI_API_KEY and OPENAI_MODEL in .env | Production with OpenAI or compatible API |
local | Set OLLAMA_MODEL and enable the local-models profile | Air-gapped or privacy-sensitive deployments |
preferred_provider field in ChatRequest, or falls back to DEFAULT_MODEL_PROVIDER from your environment. The graph logic is identical regardless of which provider runs — only the LLM call changes.
SQL guardrail layer
Before any SQL reaches your database, it passes through a validation layer built on SQLGlot. The guard (backend/app/services/sql_guard.py) enforces:
- SELECT only —
INSERT,UPDATE,DELETE,DROP,ALTER, and any other mutation statements are rejected at parse time - Table allowlist — queries referencing tables not in
DEFAULT_SOURCE_INCLUDE_TABLESare blocked, even if those tables exist in the database - Row limit — results are capped at
QUERY_MAX_ROWS(default200) to prevent runaway queries
Data flow diagram
OpenAI-compatible endpoint
Open WebUI connects to BoardPulse AI through an OpenAI-compatible endpoint at/openai/v1. This allows Open WebUI to treat BoardPulse AI as if it were an OpenAI model, with no changes to Open WebUI’s configuration beyond pointing it at http://api:8000/openai/v1. The BoardPulse AI backend handles the translation — the full LangGraph conversation graph runs on every message regardless of which interface sent it.
Related pages
SQL guardrails
Full details on what the validation layer blocks and why
Model providers
How to configure cloud, local, and mock provider settings
Connect a database
Point the system at your own PostgreSQL instance
Docker deployment
Service-by-service breakdown of the Docker Compose setup