# zleap-ai/sag architecture

> Architecture diagram of the GitHub repository zleap-ai/sag, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/zleap-ai/sag
- Repository: https://github.com/zleap-ai/sag

## Overview

1. **Overall shape**
   - SAG is a TypeScript monorepo with three runtime surfaces: a Fastify HTTP API, a stdio MCP server, and a React/Vite WebUI.
   - The backend is organized as layered services over a PostgreSQL data model, with AI provider calls abstracted behind small client modules.

2. **Primary user-facing flow**
   - The WebUI is the main entry point for creating projects, uploading documents, chatting, and inspecting traces/graphs.
   - UI actions call the HTTP API, which routes into service modules; the same services are reused by the MCP server so external agents and the UI see the same project state.

3. **Document ingestion pipeline**
   - Uploaded Markdown/TXT documents go through `ingestion-service`.
   - The pipeline performs chunking, event extraction, entity extraction, and embedding generation.
   - Results are stored in PostgreSQL through repository modules, creating the project’s searchable knowledge base.

4. **SAG retrieval pipeline**
   - Search is centered on the SAG structure: `chunk -> event`, `chunk -> entities`, and `event <-> entities`.
   - `search-service` orchestrates retrieval, using project-scoped data and multi-hop expansion over stored relations rather than relying on vector search alone.
   - The returned result includes citations and, when requested, an execution trace for debugging.

5. **Two search modes**
   - Fast mode uses entity/full-text matching, multi-hop expansion, and reranking without an LLM query-analysis step.
   - Standard mode adds LLM-based query entity extraction before retrieval and reranking.
   - This is an important architectural boundary because the search path can be either low-latency or higher-precision.

6. **AI provider abstraction**
   - `embedding-client`, `llm-client`, and `rerank-client` isolate all model-provider interactions.
   - The system supports OpenAI-compatible endpoints and has local deterministic fallback behavior when keys are absent.
   - This separation keeps retrieval logic independent from any single provider.

7. **Database as the core system of record**
   - PostgreSQL is the persistence layer for projects, documents, chunks, events, entities, embeddings, conversations, settings, and search-related metadata.
   - `pgvector` is used for embeddings, and migrations also add full-text search and schema constraints.
   - Repository modules form the boundary between SQL and application services.

8. **Project isolation**
   - Most functionality is project-scoped: documents, conversations, graphs, MCP config, and search all bind to a project/source ID.
   - That means the architecture is multi-tenant at the logical level, even though it runs as a single local service.

9. **Knowledge graph and exploration**
   - `graph-service` exposes the event/entity relationship structure for visualization in the WebUI.
   - The graph is not a separate graph database; it is derived from the relational/embedded document model in PostgreSQL.
   - The UI graph component consumes this project graph to support expand, inspect, and detail workflows.

10. **MCP integration**
   - The `mcp` subsystem turns SAG into an MCP server for external agents.
   - It exposes tool operations such as ingest, search, explain search, and fetch event details.
   - The MCP server reuses the same backend services, so agent access and WebUI access share the same retrieval and storage logic.

11. **Observability and inspection**
   - The repo includes explicit observability support for logger output and raw model-call logs.
   - These logs are surfaced in the workbench so users can inspect LLM/embedding/rerank inputs and outputs alongside search traces.
   - This is part of the product architecture, not just dev logging.

12. **Configuration and environment**
   - `src/config/env.ts` centralizes runtime configuration from `.env`.
   - Important config dimensions are database connectivity, HTTP ports, search mode defaults, and model provider endpoints/keys.
   - The repository ships Docker Compose and migration scripts, indicating that local deployment depends on bringing up PostgreSQL plus schema initialization.

13. **Codebase boundaries**
   - `services/` contains business workflows.
   - `ingestion/` contains document processing primitives.
   - `ai/` contains external model adapters.
   - `db/` contains schema, pools, migrations, and repositories.
   - `api/` and `mcp/` are the two transport layers.
   - `web/` is a separate frontend application that consumes the API.

14. **What an architecture diagram should emphasize**
   - Show the WebUI, HTTP API, and MCP server as separate entry points into the same backend services.
   - Show PostgreSQL/pgvector as the central persistence and retrieval store.
   - Show ingestion as a write pipeline into chunks/events/entities/embeddings.
   - Show search as a read pipeline that combines SQL expansion, vector/full-text retrieval, and reranking.
   - Show AI providers as external dependencies behind adapter clients.

Main entry points: [`src/api/server.ts`](https://github.com/zleap-ai/sag/blob/main/src/api/server.ts) (HTTP API), [`src/config/env.ts`](https://github.com/zleap-ai/sag/blob/main/src/config/env.ts) (Env config), [`src/services/ingestion-service.ts`](https://github.com/zleap-ai/sag/blob/main/src/services/ingestion-service.ts) (Ingestion service), [`src/services/search-service.ts`](https://github.com/zleap-ai/sag/blob/main/src/services/search-service.ts) (Search service)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["WebUI"]
  node_web_app["App shell<br/>react-ui<br/>[App.tsx]"]
  node_web_graph["Graph view<br/>react-component"]
  node_web_api["API client<br/>frontend-client<br/>[api.ts]"]
end

subgraph group_entrypoints["Runtime entrypoints"]
  node_http_api["HTTP API<br/>fastify-server<br/>[server.ts]"]
  node_mcp_server["MCP server<br/>stdio-mcp<br/>[server.ts]"]
end

subgraph group_services["Backend services"]
  node_webui_service["UI service<br/>app-service<br/>[webui-service.ts]"]
  node_ingest_service["Ingestion service<br/>pipeline-service"]
  node_search_service["Search service<br/>retrieval-service<br/>[search-service.ts]"]
  node_graph_service["Graph service<br/>graph-service<br/>[graph-service.ts]"]
  node_mcp_agent["MCP tools<br/>tool-service"]
end

subgraph group_pipeline["Ingestion pipeline"]
  node_chunker["Chunking<br/>ingestion-stage<br/>[markdown.ts]"]
  node_extractor["Extraction<br/>ingestion-stage<br/>[extractor.ts]"]
end

subgraph group_ai["AI adapters"]
  node_embed_client["Embeddings<br/>ai-client"]
  node_llm_client["LLM client<br/>ai-client<br/>[llm-client.ts]"]
  node_rerank_client["Rerank client<br/>ai-client<br/>[rerank-client.ts]"]
end

subgraph group_data["Persistence"]
  node_db_repo["Repositories<br/>[repositories.ts]"]
  node_db_pool["DB pool<br/>postgres-pool<br/>[pool.ts]"]
  node_db_vector["Vector SQL<br/>pgvector-support<br/>[vector.ts]"]
  node_env_cfg["Env config<br/>runtime-config<br/>[env.ts]"]
end

subgraph group_ops["Observability"]
  node_logger["Logger<br/>observability<br/>[logger.ts]"]
  node_model_log["Model logs<br/>observability<br/>[model-call-log.ts]"]
end

node_web_app -->|"uses"| node_web_api
node_web_app -->|"renders"| node_web_graph
node_web_api -->|"calls"| node_http_api
node_http_api -->|"routes to"| node_webui_service
node_http_api -->|"ingest"| node_ingest_service
node_http_api -->|"search"| node_search_service
node_http_api -->|"graph"| node_graph_service
node_mcp_server -->|"tools"| node_mcp_agent
node_mcp_agent -->|"ingest"| node_ingest_service
node_mcp_agent -->|"search"| node_search_service
node_mcp_agent -->|"inspect"| node_graph_service
node_ingest_service -->|"chunks"| node_chunker
node_ingest_service -->|"extracts"| node_extractor
node_ingest_service -->|"embeds"| node_embed_client
node_ingest_service -->|"stores"| node_db_repo
node_search_service -->|"reads"| node_db_repo
node_search_service -->|"standard mode"| node_llm_client
node_search_service -->|"reranks"| node_rerank_client
node_search_service -->|"matches"| node_embed_client
node_graph_service -->|"builds from"| node_db_repo
node_db_repo -->|"executes on"| node_db_pool
node_db_repo -->|"vector ops"| node_db_vector
node_env_cfg -->|"configures"| node_http_api
node_env_cfg -->|"configures"| node_mcp_server
node_env_cfg -->|"connects"| node_db_pool
node_env_cfg -->|"providers"| node_embed_client
node_env_cfg -->|"providers"| node_llm_client
node_env_cfg -->|"providers"| node_rerank_client
node_embed_client -->|"logs"| node_model_log
node_llm_client -->|"logs"| node_model_log
node_rerank_client -->|"logs"| node_model_log
node_logger -->|"observes"| node_http_api
node_logger -->|"observes"| node_mcp_server

click node_web_app "https://github.com/zleap-ai/sag/blob/main/web/src/App.tsx"
click node_web_graph "https://github.com/zleap-ai/sag/blob/main/web/src/components/ProjectGraphFlow.tsx"
click node_web_api "https://github.com/zleap-ai/sag/blob/main/web/src/lib/api.ts"
click node_http_api "https://github.com/zleap-ai/sag/blob/main/src/api/server.ts"
click node_mcp_server "https://github.com/zleap-ai/sag/blob/main/src/mcp/server.ts"
click node_webui_service "https://github.com/zleap-ai/sag/blob/main/src/services/webui-service.ts"
click node_ingest_service "https://github.com/zleap-ai/sag/blob/main/src/services/ingestion-service.ts"
click node_search_service "https://github.com/zleap-ai/sag/blob/main/src/services/search-service.ts"
click node_graph_service "https://github.com/zleap-ai/sag/blob/main/src/services/graph-service.ts"
click node_mcp_agent "https://github.com/zleap-ai/sag/blob/main/src/services/mcp-agent-service.ts"
click node_chunker "https://github.com/zleap-ai/sag/blob/main/src/ingestion/chunking/markdown.ts"
click node_extractor "https://github.com/zleap-ai/sag/blob/main/src/ingestion/extract/extractor.ts"
click node_embed_client "https://github.com/zleap-ai/sag/blob/main/src/ai/embedding-client.ts"
click node_llm_client "https://github.com/zleap-ai/sag/blob/main/src/ai/llm-client.ts"
click node_rerank_client "https://github.com/zleap-ai/sag/blob/main/src/ai/rerank-client.ts"
click node_db_repo "https://github.com/zleap-ai/sag/blob/main/src/db/repositories.ts"
click node_db_pool "https://github.com/zleap-ai/sag/blob/main/src/db/pool.ts"
click node_db_vector "https://github.com/zleap-ai/sag/blob/main/src/db/vector.ts"
click node_env_cfg "https://github.com/zleap-ai/sag/blob/main/src/config/env.ts"
click node_logger "https://github.com/zleap-ai/sag/blob/main/src/observability/logger.ts"
click node_model_log "https://github.com/zleap-ai/sag/blob/main/src/observability/model-call-log.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_web_app,node_web_graph,node_web_api,node_logger,node_model_log toneBlue
class node_http_api,node_mcp_server toneAmber
class node_webui_service,node_ingest_service,node_search_service,node_graph_service,node_mcp_agent toneMint
class node_chunker,node_extractor toneRose
class node_embed_client,node_llm_client,node_rerank_client toneIndigo
class node_db_repo,node_db_pool,node_db_vector,node_env_cfg toneTeal
```

## Components

### WebUI

React/Vite client for projects, uploads, chat, traces, and graph exploration.

- [App shell](https://github.com/zleap-ai/sag/blob/main/web/src/App.tsx): react-ui · Main WebUI entry for project workflows and inspection. · `web/src/App.tsx`
- [Graph view](https://github.com/zleap-ai/sag/blob/main/web/src/components/ProjectGraphFlow.tsx): react-component · Project graph visualization and expand/inspect interactions. · `web/src/components/ProjectGraphFlow.tsx`
- [API client](https://github.com/zleap-ai/sag/blob/main/web/src/lib/api.ts): frontend-client · Browser-side transport for calling the backend API. · `web/src/lib/api.ts`

### Runtime entrypoints

HTTP and MCP surfaces that enter the shared backend services.

- [HTTP API](https://github.com/zleap-ai/sag/blob/main/src/api/server.ts): fastify-server · Fastify surface for UI-driven project, ingestion, and search operations. · `src/api/server.ts`
- [MCP server](https://github.com/zleap-ai/sag/blob/main/src/mcp/server.ts): stdio-mcp · StdIO MCP entrypoint for external agents and tools. · `src/mcp/server.ts`

### Backend services

Project-scoped application workflows for ingestion, search, graphing, settings, and MCP support.

- [UI service](https://github.com/zleap-ai/sag/blob/main/src/services/webui-service.ts): app-service · Backend workflow facade for WebUI project actions and shared state. · `src/services/webui-service.ts`
- [Ingestion service](https://github.com/zleap-ai/sag/blob/main/src/services/ingestion-service.ts): pipeline-service · Coordinates document ingest from parsing through storage. · `src/services/ingestion-service.ts`
- [Search service](https://github.com/zleap-ai/sag/blob/main/src/services/search-service.ts): retrieval-service · Orchestrates fast and standard SAG retrieval, expansion, reranking, and citations. · `src/services/search-service.ts`
- [Graph service](https://github.com/zleap-ai/sag/blob/main/src/services/graph-service.ts): graph-service · Builds project-scoped event/entity graphs for visualization. · `src/services/graph-service.ts`
- [MCP tools](https://github.com/zleap-ai/sag/blob/main/src/services/mcp-agent-service.ts): tool-service · Exposes ingest, search, explain, and detail tools over MCP. · `src/services/mcp-agent-service.ts`

### Ingestion pipeline

Document processing stages that turn uploaded text into searchable knowledge.

- [Chunking](https://github.com/zleap-ai/sag/blob/main/src/ingestion/chunking/markdown.ts): ingestion-stage · Splits markdown/TXT content into searchable chunks. · `src/ingestion/chunking/markdown.ts`
- [Extraction](https://github.com/zleap-ai/sag/blob/main/src/ingestion/extract/extractor.ts): ingestion-stage · Extracts events and entities from chunks. · `src/ingestion/extract/extractor.ts`

### AI adapters

Provider-facing clients for embeddings, LLM calls, and reranking with local fallback behavior.

- [Embeddings](https://github.com/zleap-ai/sag/blob/main/src/ai/embedding-client.ts): ai-client · Embedding adapter with provider and local fallback behavior. · `src/ai/embedding-client.ts`
- [LLM client](https://github.com/zleap-ai/sag/blob/main/src/ai/llm-client.ts): ai-client · Query analysis and model-call adapter for provider-backed or local execution. · `src/ai/llm-client.ts`
- [Rerank client](https://github.com/zleap-ai/sag/blob/main/src/ai/rerank-client.ts): ai-client · Reranking adapter used after initial retrieval. · `src/ai/rerank-client.ts`

### Persistence

PostgreSQL boundary, vector support, repositories, migrations, and runtime config.

- [Repositories](https://github.com/zleap-ai/sag/blob/main/src/db/repositories.ts): sql-repositories · Project-scoped SQL boundary for documents, chunks, events, entities, conversations, and settings. · `src/db/repositories.ts`
- [DB pool](https://github.com/zleap-ai/sag/blob/main/src/db/pool.ts): postgres-pool · PostgreSQL connection and vector support boundary. · `src/db/pool.ts`
- [Vector SQL](https://github.com/zleap-ai/sag/blob/main/src/db/vector.ts): pgvector-support · Embedding/vector helpers and retrieval primitives. · `src/db/vector.ts`
- [Env config](https://github.com/zleap-ai/sag/blob/main/src/config/env.ts): runtime-config · Centralized runtime configuration for ports, DB, search mode, and provider endpoints. · `src/config/env.ts`

### Observability

Logging and model-call inspection surfaced through the workbench.

- [Logger](https://github.com/zleap-ai/sag/blob/main/src/observability/logger.ts): observability · Structured application logging. · `src/observability/logger.ts`
- [Model logs](https://github.com/zleap-ai/sag/blob/main/src/observability/model-call-log.ts): observability · Raw model-call logging for inspection in the workbench. · `src/observability/model-call-log.ts`

## Connections

- App shell → API client: uses · UI actions call the browser API layer.
- App shell → Graph view: renders · The app includes the project graph exploration view.
- API client → HTTP API: calls · Frontend requests enter through the HTTP API.
- HTTP API → UI service: routes to · HTTP handlers delegate shared project workflows.
- HTTP API → Ingestion service: ingest · API-triggered uploads enter the ingest pipeline.
- HTTP API → Search service: search · API search requests use the shared retrieval service.
- HTTP API → Graph service: graph · Graph inspection is served from the project graph service.
- MCP server → MCP tools: tools · MCP requests are translated into tool operations.
- MCP tools → Ingestion service: ingest · Agent tools reuse the same ingestion workflow.
- MCP tools → Search service: search · Agent search uses the shared retrieval pipeline.
- MCP tools → Graph service: inspect · Agent graph/detail tools reuse project graph access.
- Ingestion service → Chunking: chunks · Documents are split into chunks before extraction.
- Ingestion service → Extraction: extracts · Ingestion derives events and entities from chunks.
- Ingestion service → Embeddings: embeds · Chunks and related content receive embeddings.
- Ingestion service → Repositories: stores · Processed knowledge is persisted through repositories.
- Search service → Repositories: reads · Search starts from project-scoped relational data.
- Search service → LLM client: standard mode · Standard search extracts query entities before retrieval.
- Search service → Rerank client: reranks · Retrieved candidates are reranked before response.
- Search service → Embeddings: matches · Vector similarity supports retrieval when available.
- Graph service → Repositories: builds from · Graph views are derived from stored events and entities.
- Repositories → DB pool: executes on · Repositories run SQL against PostgreSQL.
- Repositories → Vector SQL: vector ops · Embedding and similarity helpers support retrieval.
- Env config → HTTP API: configures · Environment settings control runtime ports and defaults.
- Env config → MCP server: configures · Environment settings control MCP behavior and endpoints.
- Env config → DB pool: connects · Database connection details come from env configuration.
- Env config → Embeddings: providers · Model provider endpoints and keys configure AI adapters.
- Env config → LLM client: providers · Model provider endpoints and keys configure AI adapters.
- Env config → Rerank client: providers · Model provider endpoints and keys configure AI adapters.
- Embeddings → Model logs: logs · Embedding requests and responses are captured for inspection.
- LLM client → Model logs: logs · LLM prompts and outputs are captured for inspection.
- Rerank client → Model logs: logs · Rerank inputs and outputs are captured for inspection.
- Logger → HTTP API: observes · Server activity is emitted through structured logs.
- Logger → MCP server: observes · MCP activity is emitted through structured logs.
