📚 Docs / Agent Knowledge Base — answering questions about this app

Agent Knowledge Base — answering questions about this app

This is the fast-answer reference for humans and AI agents. Each entry gives a concise answer plus the doc to read for depth. If an answer here conflicts with the root README.md, trust this document (and the docs it references) — the root README is the non-technical user guide; these docs are the source-verified technical reference.

Q&A

What is this app?

A local-first legal research desktop application ("Lawyer Assistant") for legal documents. The UI, prompts and OCR are English, and retrieval is language-agnostic (the BGE-M3 embedding model handles many languages, so non-English source text can still be searched). It searches a legal corpus with BGE-M3 embeddings + ChromaDB + BM25 + a cross-encoder reranker, answers questions with a local Ollama LLM (RAG with citations), and runs a compliance playbook scan that flags risky clauses in documents. It is an Electron app with a React frontend and a Python FastAPI backend. → ARCHITECTURE.md.

What are the three "modes" of chat?

rag (default; retrieve + answer), retrieval_only (search only, no LLM), direct (LLM only, no retrieval). → BACKEND.md §2.

What AI "agents" does the app have?

What does the agent do with my query?

Rules enforced by prompts: the exact user query is passed to search_documents without rephrasing, results are verified with verify_relevance, and the final answer is written from retrieved chunks with file/page citations — or it says honestly that documents don't contain the answer. → BACKEND.md §4b.

What is human-in-the-loop approval?

Before the agent executes a tool, the LangGraph graph pauses with interrupt(). The UI shows an ApprovalBar; the user approves or rejects; /api/chat/resume resumes the thread with Command(resume=response). Reject makes the agent answer without tools. Thread state persists in data/conversations.db (AsyncSqliteSaver). → BACKEND.md §4b, §3.

How does retrieval work?

Query → BGE-M3 embedding → dense search (ChromaDB, top 50) + sparse (BM25, top 50) → hybrid merge → BGE-Reranker-v2-M3 cross-encoder re-scores → top 5 results with scores, file/page/section metadata. → BACKEND.md §5.

How does document ingestion work?

Files are saved into the active project folder (a workspace must be selected first — uploads land directly in that folder), parsed with Docling (OCR for scanned PDFs), chunked by the structure-aware chunker (480-token chunks, sections never split), embedded with BGE-M3, stored in ChromaDB, and indexed for BM25. → DATA_FLOW.md, BACKEND.md §5.

How does the compliance scan work?

Document chunks → classify clause type (embedding classifier) → check each playbook rule → emit flags (severity high/medium/low, rule id, page, reason, clause text) → persist to SQLite → UI lets you resolve / dismiss / escalate. Playbooks are JSON files in backend/legal_retrieval/playbook/playbooks/. → BACKEND.md §6.

How do attachments work?

Attach up to 5 files (or a folder of up to 50 docs) → each is uploaded to /api/upload (saved into the active project folder — a workspace must be selected first) → the paths ride along on the chat request → the router ingests (ingest_file) and/or scans (scan_document) them; if you attach files without typing, it runs a default batch-scan prompt. → BACKEND.md §2, FRONTEND.md §2.

What does "select a folder" do? (Workspace)

The "Work in a folder" button opens a native Electron directory dialog and the picked folder becomes the active workspace — and a workspace is now required: chat, upload and scan all refuse to run without one (there is no default data/ folder anymore). Raw uploads land directly in that folder, and the ChromaDB/BM25 indexes, processed temp files and per-project history all live under <folder>/workspace/ (workspace/chroma_db, workspace/bm25_index, workspace/processed, workspace/history.json), replacing the static project data/ paths. POST /api/workspace sets it, GET reads it, DELETE resets it, and POST /api/workspace/ingest (or its SSE variant /api/workspace/ingest/stream) indexes every supported document in the folder. A background folder-watcher auto-ingests new files dropped into the project. The override is runtime-only (resets on restart). The frontend passes workspace file absolute paths on send (no re-upload). → BACKEND.md §2 (Workspace), config.py workspace section.

What ports does the app use?

8765 backend (FastAPI), 5173 Vite dev server, 11434 Ollama. Electron kills stale 8765/5173 processes at startup. → ARCHITECTURE.md §2.

Where is data stored?

How does streaming work?

The backend streams Server-Sent Events (event: <type>\ndata: <json>): tokens, thinking (chain-of-thought), statuses, the plan, tool calls/results, node_start/node_complete, sources, interrupted/resumed, done, error. The frontend parses SSE lines and appends to Zustand streaming state. Workspace ingest streams its own event set (ingest_start, ingest_progress, ingest_done, ingest_cancelled, ingest_error). → BACKEND.md §3, FRONTEND.md §2, §6.

What is the Pipeline Editor?

A ReactFlow canvas visualizing the pipeline as nodes (intent, planner, dense, sparse, rerank, ingest, scan, answer). Nodes can be removed (auto-bypass rewires the flow), re-enabled via palette toggles, and the whole layout is auto-saved, resettable, and exportable/importable as JSON. Since the /api/pipeline/config endpoint, the layout also reconfigures the Python backend at runtime (rerank on/off from the rerank node, search mode + fusion weights from the dense/sparse nodes, top_k overrides). The config is runtime-only and resets on restart. → PIPELINE_EDITOR.md, PIPELINE_JSON.md §10.

Why is the UI light by default? / How does theming work?

The app defaults to a light "parchment" theme; html.light + CSS variables drive all colors, and a bridge remaps Tailwind utility classes so text never matches the background in either theme. → FRONTEND.md §7.

How do I run the app?

npm run dev at the root (runs Electron, which boots the FastAPI backend and Vite itself). Non-technical users: double-click launch.bat / launch.sh to open the launcher, which installs everything and starts the app. For production, npm run build then npm run package:win|mac|linux (electron-builder). Electron auto-creates/uses .venv for the backend. → ARCHITECTURE.md §3.

Why is the first query slow?

Models are preloaded at backend startup (warmup thread), so after startup the first query is fast; without warmup the first call pays model-loading cost. CLI (backend/scripts/query.py) also loads models on first use.

What are the tests/benchmarks?backend/tests/ has phase-based suites (boot, types, chunking, embeddings, vector

store, retrieval, integration e2e); backend/benchmark/ has component tests and golden eval harnesses; CLI law.py benchmark runs them. → backend/tests/, backend/benchmark/ source.


How to answer accurately (for agents)

  1. Scope check: is the question about the desktop app (Electron/React/ FastAPI) or the legacy CLI (law.py)? Point to docs/ for the former; the CLI is not user-facing anymore.
  2. Prefer code over memory: verify specifics against backend/main.py, backend/legal_retrieval/*.py, frontend/src/** when the question is technical.
  3. Pipeline Editor = runtime config: since POST /api/pipeline/config, the editor's layout does reconfigure retrieval at runtime (rerank on/off, search mode + fusion weights, top_k) — it is not visual-only. Say so accurately (see PIPELINE_JSON.md §10).
  4. Cite the doc: end answers with the relevant doc filename so the questioner can go deeper.

Questions, answered

Short, self-contained answers about this guide.

Where is the ground truth for the app?

The knowledge base maps each topic to its source file — API endpoints in backend/main.py, retrieval config in config.py, frontend events in chatStore.ts, pipeline layout format in pipelineStorage.ts.

What are the known documentation traps?

The root README is legacy (old CLI/flask), two routers exist (intent-based vs legacy ReAct), and both streaming and non-streaming chat endpoints exist — the knowledge base flags each so agents answer from the current architecture.

How should agents verify facts?

Answer from docs/ first, then verify technical claims against the code with search, quote file + line when unsure, and say so when a fact can't be verified.