Local, privacy-preserving multi-agent legal document intelligence.
Upload any contract, NDA, or service agreement. A team of five AI agents dissects it, flags risk clauses, benchmarks rates against market standards, translates legalese into plain English, and returns a structured risk report entirely on your machine. Your document never reaches an external API.
Lawyers charge $300-500/hr for contract review. Most people sign agreements they don't fully understand. LexVault replaces that expensive, slow step with a local AI pipeline that runs in 2-5 minutes. Because it runs on Ollama, there is no cloud dependency, no data sharing, and no subscription.
┌─────────────────────────────────────────────────────────────────┐
│ Angular Frontend │
│ Upload page - WebSocket progress view - Tabbed report view │
└───────────────────────────┬─────────────────────────────────────┘
│ HTTP & WebSocket
┌─────────────────────────────────────────────────────────────────┐
│ FastAPI Backend │
│ 1. POST /upload 2. Background task 3. WS /ws/{job_id} │
│ 4. GET /report/{job_id} │
└───────────────────────────┬─────────────────────────────────────┘
│ Agno agent framework
┌─────────────────────────────────────────────────────────────────┐
│ 5-Agent Pipeline │
│ [1] Extractor │
│ [2] Risk Scorer │
│ [3] Benchmarker │
│ (if BRAVE_API_KEY set) │
│ MCP: @modelcontextprotocol/server-brave-search │
│ Live web search for market benchmark data │
│ [4] Translator │
│ [5] Reporter │
│ report.json │
└───────────────────────────┬─────────────────────────────────────┘
│ Ollama API (local)
┌─────────────────────────────────────────────────────────────────┐
│ Ollama (qwen2.5:7b) │
│ Runs entirely on your hardware │
└─────────────────────────────────────────────────────────────────┘
Each agent is a focused, single responsibility unit backed by qwen2.5:7b running locally via Ollama. Steps 2 and 3 run in parallel to reduce total wall clock time.
Input: Raw contract text
Output: ExtractedClauses (Pydantic model)
Parses the document and identifies every clause by category: payment, termination, intellectual property, liability, exclusivity, confidentiality, governing law, dispute resolution, auto-renewal, indemnification, non-compete, force majeure, and others. Also extracts the contract type, party names, effective date, and duration.
Input: ExtractedClauses
Output: RiskAnalysis (scored clauses, 1–10 risk scale)
Reviews every clause with the perspective of a senior contracts lawyer acting on behalf of the signer. Flags one-sided termination rights, broad IP assignment, uncapped liability, short auto-renewal windows, unilateral amendment rights, and other common red flags. Produces a risk score (1–10) per clause, a risk level (low / medium / high / critical), red flags, and specific negotiation leverage for each.
Input: ExtractedClauses
Output: BenchmarkResultList
MCP: @modelcontextprotocol/server-brave-search (optional — requires BRAVE_API_KEY)
Compares key contract terms against industry market standards. Classifies each term as above_market (unfavorable), at_market (standard), below_market (favorable), or unusual. Covers payment schedules, termination notice periods, non-compete scope and duration, liability caps, IP assignment, auto-renewal windows, and warranty periods.
When BRAVE_API_KEY is set, the agent is given a live Brave Search tool via MCP and actively searches for current benchmarks (e.g. "standard net-30 payment clause freelance 2025"). Without a key it falls back to the model's training knowledge, still useful, but data may be less current.
Input: High-risk scored clauses (risk score ≥ 5)
Output: TranslatedClauseList
Rewrites each flagged clause in plain English at an 8th-grade reading level. For each clause, produces: what it actually says, what it means specifically for the person signing, and a realistic example scenario showing it in action.
Input: All outputs from Steps 1-4
Output: FinalReport (written to reports/{job_id}/report.json)
Synthesises everything into a structured final report with an executive summary, weighted overall risk score, top 3 risks, all clause analyses, benchmark comparisons, plain English translations, specific negotiation recommendations, and a sign recommendation: sign, negotiate, or walk away.
| Layer | Technology | Purpose |
|---|---|---|
| Local inference | Ollama (qwen2.5:7b) |
Runs all models locally, no API key |
| Agent framework | Agno 2.x | Multi-agent orchestration and structured output |
| MCP server | @modelcontextprotocol/server-brave-search |
Live web search for Benchmarker (optional) |
| MCP client | mcp Python SDK |
Bridges Agno agents to MCP stdio servers |
| Backend API | FastAPI & Uvicorn | REST upload, WebSocket progress streaming |
| Document parsing | PyMuPDF, python-docx | PDF and DOCX text extraction |
| Data validation | Pydantic v2 | Typed schemas for every agent's I/O |
| Frontend | Angular 17 (standalone) | Upload UI, live progress, report viewer |
| Styling | SCSS + Angular Animations | Dark theme, animated progress steps, SVG gauge |
The original design spec was called for llama3.1:70b (~40 GB) for heavy reasoning tasks. But, since I'm running the project on 16 GB MacBook that is not viable. qwen2.5:7b uses ~4.5 GB in Q4 quantization, outperforms llama3.1:8b on legal and instruction-following benchmarks, and runs at acceptable speed on Apple Silicon unified memory. All five agents share the same model.
P.S. Please feel free to use your own choice of LLM Model(See your PC Specs).
LexVault/
── backend/
── main.py # FastAPI app — upload, WebSocket, report endpoints
── requirements.txt
── .env.example
── agents/
── extractor.py # Agent 1 — clause extraction
── risk_scorer.py # Agent 2 — legal risk scoring
── benchmarker.py # Agent 3 — market benchmarking
── translator.py # Agent 4 — plain English translation
── reporter.py # Agent 5 — final report synthesis
── team/
── orchestrator.py # Async pipeline — runs agents in sequence/parallel
── parsers/
── document_parser.py # PDF + DOCX text extraction
── schemas/
── clauses.py # Pydantic models for clause data
── report.py # Pydantic model for final report
── uploads/ # Uploaded contracts (created at runtime)
── reports/ # Generated reports (created at runtime)
── frontend/
── angular.json
── package.json
── src/
── app/
── pages/
── home/ # Drag-and-drop upload page
── analysis/ # Real-time WebSocket progress view
── report/ # Tabbed report viewer with risk gauge
── services/
── analysis.service.ts # HTTP + WebSocket client
── models/
── report.model.ts # TypeScript interfaces
- macOS (tested) / Linux / Windows with WSL
- Python 3.11+
- Node.js 18–22 (avoid odd numbered versions for production)
- Ollama installed and running — ollama.com
- ~6 GB free disk for the model
ollama pull qwen2.5:7bThis downloads ~4.5 GB once. Ollama must be running in the background (ollama serve) before starting the backend.
cd backend
# Create and activate virtual environment
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Copy environment config
cp .env.example .env
# Optional: add your Brave Search API key to enable live market data for the Benchmarker
# Free tier (2,000 queries/month): https://brave.com/search/api/
# Edit .env and set: BRAVE_API_KEY=your_key_here
# Start the API server
uvicorn main:app --reload --port 8000The backend runs at http://localhost:8000.
Open a second terminal:
cd frontend
npm install
npm startThe app opens at http://localhost:4200.
- Open
http://localhost:4200 - Drag and drop a PDF or DOCX contract onto the upload zone (or click to browse)
- Click Analyse Contract
- Watch the 5-agent pipeline run in real time on the progress screen
- View the full risk report when complete:
- Clause Analysis — every clause scored and annotated, sorted by risk
- Benchmarks — how your terms compare to market standard
- Plain English — what each flagged clause actually means for you
- Recommendations — specific actions to take before signing
| Method | Endpoint | Description |
|---|---|---|
POST |
/upload |
Upload a PDF or DOCX file. Returns { job_id, filename } |
WS |
/ws/{job_id} |
WebSocket stream of progress events |
GET |
/report/{job_id} |
Retrieve the completed FinalReport JSON |
GET |
/health |
Health check |
{
"contract_type": "Freelance Service Agreement",
"parties": { "party_a": "Acme Corp", "party_b": "Jane Smith" },
"executive_summary": "...",
"overall_risk_score": 7.4, // 1.0–10.0
"risk_level": "high", // low | medium | high | critical
"top_3_risks": ["...", "...", "..."],
"scored_clauses": [...],
"benchmark_results": [...],
"translated_clauses": [...],
"recommendations": ["..."],
"sign_recommendation": "negotiate" // sign | negotiate | walk away
}- All inference runs on Ollama, which is entirely local
- Uploaded files are saved to
backend/uploads/on your own disk - No data is sent to any external API
- No telemetry, no analytics, no cloud calls
- To delete all data: remove
backend/uploads/andbackend/reports/
- Not legal advice. LexVault is an AI tool, not a lawyer. Use it to understand a contract before engaging a legal professional for high-stakes decisions.
- Model size trade-off.
qwen2.5:7bis capable but may miss subtle edge cases that a larger model (70b) would catch. Results are better on standard contract types (NDAs, service agreements, employment contracts) than on highly bespoke agreements. - Structured output reliability. Local models can occasionally produce output that does not conform to the expected schema. The pipeline will surface an error if this happens — re-running usually resolves it.
- Context length. Very long contracts (>50 pages) may exceed the model's context window. The extractor processes the full text in one pass; extremely long documents may be truncated by Ollama.
- ollama rm qwen2.5:7b removes the model file
- rm -rf ~/.ollama/ removes everything