-
Notifications
You must be signed in to change notification settings - Fork 0
FAQ
Mailroom is a multi-agent pipeline that ingests legal documents, classifies them, routes them to specialist agents for structured extraction, compiles the results into a matter record, and archives everything with a full audit trail.
Five types in v1:
- Contracts (MSAs, NDAs, employment agreements, etc.)
- Corporate Records (bylaws, resolutions, board minutes, cap tables)
- Due Diligence (checklists, disclosure schedules, diligence memos)
- Correspondence (demand letters, legal notices, memos)
- Compliance Filings (SEC filings, state registrations, regulatory docs)
Adding a new type takes 5 steps — see Development.
LangGraph provides:
- A defined, explicit state machine — agents don't freely negotiate what happens next
- Postgres-backed checkpointing for crash/resume
- Conditional edges for confidence-based routing
- Human-in-the-loop via
interrupt()for review scenarios
Yes. Set DEFAULT_PROVIDER=ollama in .env, or configure per-agent in config/taxonomy.yaml. See Local Model Cutover.
The pipeline degrades gracefully:
- LangGraph checkpointer falls back to MemorySaver
- Catalog writes are best-effort (pipeline continues without them)
- Audit log entries are best-effort
- The manifest JSON sidecar (archived with each file) is always written — filesystem-based durability
The system runs without it. The observability/langfuse_setup.py module has a noop client that handles all calls gracefully. The audit log is independent of Langfuse.
Watcher uses os.rename() to atomically move files from /pipeline/inbox/ to /pipeline/processing/<worker_id>/. os.rename is atomic on the same filesystem, so no two workers can claim the same file. No external locking needed.
Every state transition writes an AuditLogEntry to the audit_log table. Each entry is SHA-256 hashed with its predecessor's hash, forming a tamper-evident chain. The chain can be verified via the /audit/{doc_id} endpoint. Audit entries are also written by the Boss on escalation.
The Boss has two roles:
- In-graph: adjudicates conflicts when extraction data contradicts existing matter records
- Ops-monitor: separate process that sweeps the catalog for stuck documents, error spikes, and review backlogs
Both share the same system-prompt "voice" but are triggered differently and see different data.
Matters are auto-created when you upload a document with a new matter_id. You don't need to create matters explicitly. The catalog records the matter on first document ingestion.
The file_extensions in config/taxonomy.yaml include .pdf and .docx. The current pipeline reads text via file_path.read_text(). For production PDF/DOCX support, you'd add a text extraction step (e.g., pypdf, python-docx) in the ingest_node before classification.
v1 targets pilot scale: dozens of documents/day per matter. The threaded watcher and single-process design is sufficient. For higher volumes, Redis-based queuing and multiple workers are planned as deferred work.
During processing: data/pipeline/ (inbox, processing, classified, review, failed)
After processing: data/archive/<matter_id>/<doc_type>/
Manifests: data/manifests/<doc_id>.json
MAILROOM_BASE_DIR controls the root (./data by default).
Three ways:
-
Langfuse UI (
http://localhost:3000) — live traces of every LLM call -
/ops/statusendpoint — pipeline-wide metrics (stuck docs, review backlog, error rates) - Ops monitor — automated Boss sweeps with alerts
For pilot scale (dozens of documents/day) with human oversight: yes. For enterprise production with multi-tenant isolation, RBAC, and high-availability: this is the foundation but needs the deferred work in the roadmap (Redis queues, richer web UI, full RBAC, etc.).
Mailroom — Multi-Agent Legal Document Processing Pipeline. Built with LangGraph, OpenRouter, and Postgres.