← Work
Client projectRAG, Graph RAG & RetrievalAgentic Systems & OrchestrationAI Backend Engineering

Mukalaf.ai — Legal AI Platform

A bilingual tax-litigation platform for Saudi Zakat, tax and customs law. An agent drafts legal documents grounded in retrieved regulation, stopping for a human whenever it needs facts only the lawyer has.

Role
AI engineer — agent workflow, RAG and retrieval
Live
Visit the site →
Mukalaf.ai — Legal AI Platform interface
01

The problem

Zakat, tax and customs litigation is regulation-dense and high-stakes, and it runs in Arabic. Two things break naive AI here: legal Arabic defeats plain text extraction and embedding-only retrieval, and a document that reads fluently but cites the wrong article is worse than no draft at all. A generated filing has to be traceable to the regulation it rests on.

02

Architecture

01

Agent workflow — a LangGraph state machine: fetch case → extract documents → analyze → search legal references → generate document → generate PDF → review. Two of those edges are loops rather than steps: a request-info loop when the draft needs facts only the lawyer holds, and a feedback loop after review.

02

Human-in-the-loop durability — PostgreSQL-backed checkpointing means an interrupt is a real pause. The run resumes at the node it stopped on instead of replaying the workflow from the start, so a lawyer answering a question tomorrow does not re-trigger extraction and retrieval.

03

Retrieval — legal references embedded with Cohere embed-v4.0 (1536 dims) into Qdrant, then re-scored by a BAAI/bge-reranker-v2-m3 cross-encoder before anything reaches the model.

04

Document extraction — PyMuPDF for clean text, with a Gemini 2.0 Flash vision model as the fallback path for scanned filings and complex tabular layouts that defeat text extraction.

05

Provider factory — LLM and embedding backends behind one interface (OCI Cohere primary, OpenAI, Cohere, Ollama), so model choice is configuration rather than a code change.

06

Platform — FastAPI with async SQLAlchemy 2.0 over ~29 tables, two-tier RBAC (9 firm roles, 5 client roles, ~45 permissions), JWT with OTP/2FA, and Arabic-aware PDF generation via ReportLab with arabic-reshaper and python-bidi.

Mukalaf.ai — Legal AI Platform architecture
03

Key decisions

Chose

A LangGraph state machine with database-backed checkpoints

Over

A prompt chain that runs start to finish

Because

Legal drafting cannot complete in one pass — it stops to ask the lawyer for facts, and stops again for review. Checkpointing makes an interrupt durable: the run resumes at the node that paused instead of replaying extraction and retrieval, which would waste tokens and could produce a different draft the second time.

Chose

A cross-encoder reranker between retrieval and generation

Over

Feeding top-k vector hits straight to the model

Because

Embedding similarity in Arabic legal text surfaces passages that are topically close but legally wrong — a neighbouring article, a superseded provision. The reranker scores each candidate against the actual question, and being right about which article applies is the whole product.

Chose

A vision model as the fallback extraction path

Over

Text extraction alone

Because

Real filings arrive scanned, stamped, and laid out in tables. PyMuPDF handles the clean majority cheaply; routing only the documents it fails on to a VLM keeps cost proportional to difficulty instead of paying vision prices for every page.

Chose

Two-tier RBAC with permissions as data

Over

Role checks scattered through route handlers

Because

The firm and its clients see different slices of the same case, and ~45 permissions across 14 roles is past the point where inline checks stay correct. Centralising it means a new role is a data change, not an audit of every endpoint.

04

The hard part

Arabic legal retrieval. Legal Arabic is morphologically rich and heavily templated, so embeddings cluster documents that share phrasing rather than meaning — and the passages that share phrasing in this domain are precisely the ones that are easy to confuse: adjacent articles, amended provisions, and near-identical clauses from different regulations. Vector search alone returned plausible-looking references that a lawyer would reject. The fix was a two-stage retrieval path — recall from Qdrant, then precision from a cross-encoder that scores each candidate against the question rather than against the corpus — plus grounding every generated claim in a cited source so a reviewing lawyer can check the draft against the regulation rather than trusting it.

05

Results

8
Workflow nodes, two of them human-in-the-loop
~29
Database tables behind the case model
14
Roles across firm and client tiers (~45 permissions)
06

Stack

FastAPILangGraphPostgreSQLSQLAlchemy 2.0QdrantCohere embed-v4.0bge-reranker-v2-m3PyMuPDFGemini 2.0 FlashNext.js 15RedisDocker
07

Related field notes

smoke
“Innovation distinguishes between a leader and a follower.”

Need an AI system that holds up in production? Tell me what breaks today and I'll tell you what I'd build.

Call Me now !

mail

abdelmajidzaddi088@gmail.com

address

Mohammedia, Morocco

phone

+212 695 557 631