How We Are Building a PDF-to-Slack Review Loop

This project is gratifying because it is being built to transform laborious, manual processes into something smooth.
It began with an issue that is surprisingly common. Imagine having important deadlines buried in long PDF papers. You have to locate them, each file had to be opened, pages had to be scrolled through, the pertinent dates need to be manually extracted, verified for accuracy, and then entered into the team's scheduling system. This can obviously take a lot of time, because of how repetitive it is, and is simple to do incorrectly.
The objective is to use Loop Engineering to eliminate the time-consuming steps and allow the job to proceed organically rather than to completely redo the procedure.
We needed to create a system that seemed incredibly straightforward from the outside:
- Intake: A PDF arrives in our workspace.
- Extraction: The system parses the document, extracting key dates and context.
- Notification: A summary notification lands in a Slack channel.
- Human-in-the-loop: A reviewer clicks a link to open a clean dashboard, reviews the source page side-by-side with the extracted dates, edits or approves them, and saves the verified data.
Under the hood, though, there are a lot of moving parts.
So here is how we are building it.
The Architecture of the Loop
The pipeline is designed to be resilient, cost-effective, and auditable.
Take a close look at this high-level representation of how data flows from file ingestion to human approval:
[ PDF File ]
│
▼
┌──────────────┐ Text-Selectable?
│ Parser-First │───────────────────────► [ Structured JSON ] ──┐
│ Extraction │ │
└──────────────┘ │
│ No (Scanned/Images) │
▼ ▼
┌──────────────┐ ┌─────────────┐
│ OCR Layer │ │ Data Clean │
│ (Doc AI / │───────────────────────────────────────►│ & Dedupe │
│ LlamaParse) │ └─────────────┘
└──────────────┘ │
▼
┌─────────────┐
│ Cloudflare │
│ R2 + D1 │
└─────────────┘
│
┌─────────────────────┴─────────────────────┐
▼ ▼
┌────────────────────┐ ┌───────────────────┐
│ Slack Alert │ │ Web Review UI │
│ (Compact Summary) │ │ (Side-by-Side UI) │
└────────────────────┘ └───────────────────┘
1. Ingestion: Parser-First Extraction with OCR Fallback
Parsing documents is a balance between speed, accuracy, and cost. Running heavy OCR APIs on every document is expensive and slow. That's why the extraction engine uses a parser-first strategy.
If a PDF is text-selectable, we use lightweight Python libraries to extract raw text coordinates and lines. It classifies common deadline labels using string parsing and regular expressions, normalizes date formats, and maps the layout coordinates.
If the text content is sparse or nonexistent (e.g. scanned letter PDFs or photo uploads), the pipeline routes the file to the OCR fallback layer.
Once extracted, each candidate date is structured into a standard payload:
{
"property": "Martin Valley",
"deadline": "Closing Deadline",
"due_date": "2007-12-17",
"source_page": 4,
"source_file": "Critical Dates Letter.pdf",
"confidence": "medium",
"status": "needs_review"
}
2. The OCR Providers: Google Document AI & LlamaParse
For the OCR layer, I built an adapter pattern so the application is not tightly coupled to a single vendor.
Currently, the system supports two powerful OCR engines:
- Google Document AI: Serving as the primary production-grade OCR path. Document AI is exceptionally robust for enterprise documents. It provides precise token coordinates, structural layout recognition (paragraphs, tables, blocks), and page-level provenance.
- LlamaParse (LlamaIndex): Wired in as the primary fallback and comparison provider. LlamaParse is built with agentic document-grounding in mind. It excels at parsing documents with complex spatial relationships and returning clean markdown representation with region-level bounding boxes.
Here is a quick look at how the two providers stack up for this use case:
| Feature | Google Document AI (Primary) | LlamaParse (Fallback) |
| :--- | :--- | :--- |
| Strengths | Enterprise reliability, layout structure, hierarchical tokens | Excellent table formats, markdown-centric extraction, visual grounding |
| Data Format | Hierarchical JSON (Document proto) | Markdown + Spatial bounding boxes |
| Ideal For | High-volume official files, complex legal forms | Unstructured documents, quick comparisons |
| Cost Strategy | Pay-per-page (predictable scaling) | Flexible tiers (ideal fallback budget) |
3. Slack as the Front Door
We didn't want reviewers to live inside a custom dashboard all day. Instead, Slack acts as the interface’s entry point.
When a PDF finishes processing, the Python service formats a clean, compact block message and posts it to a dedicated #critical-dates Slack channel.
Critical Dates Review Ready 🔔
Processed file: Critical Dates Letter.pdf
10 critical dates found | Review status: Needs review
Property Deadline Due Status
Martin Valley Closing Deadline Dec 17 Needs review
Martin Valley Earnest Money Nov 2 Pending review
Martin Valley Title Objection Nov 23 Needs review
👉 Open review dashboard:
https://example.com/review/doc_123
By keeping the Slack alert focused, reviewers get instant context: they see which file was processed, the key dates found, and can decide if it requires immediate action without being overwhelmed by data clutter.
4. The Human-in-the-Loop Dashboard
Document AI can be highly accurate, but it is never 100% perfect. A system that pretends to be magical without giving humans a way to verify and correct its mistakes is a recipe for silent errors.
The review page is where the magic meets reality. The user interface splits the screen:
- Left Pane: An interactive PDF viewer highlighting the source document.
- Right Pane: A clean table containing the extracted dates, deadline labels, status badges, and inline editing fields.
Clicking on a specific date row in the right panel automatically scrolls the PDF viewer to the correct page and highlights the region where the date was found. Reviewers can approve a row, change a status badge (e.g. from needs_review to approved), or edit incorrect OCR typos in place.
5. Storage and VPS Architecture
The service runs on a simple VPS. Python makes it simple to bundle libraries like pdfplumber, google-cloud-documentai, and various SDKs under one unified daemon process.
For data durability, I went with Cloudflare’s developer platform:
- Cloudflare R2: For object storage. We upload the original raw PDFs and store the full raw OCR JSON responses for historical auditing.
- Cloudflare D1: A serverless SQL database where we store documents, extracted critical-date metadata, document provenance, and the audit logs of user modifications.
This serverless-edge combination means the VPS remains thin and stateless. If the server crashes or needs to scale, all critical state, PDFs, and SQL tables reside safely in Cloudflare's durable network.
6. Noise Reduction and Cleanup
Raw OCR data is incredibly noisy. If a document includes a repeated running header like "November 5, 2007" or footer page markings, naive extraction will pull that date on every single page and mark it as a deadline event.
To address this, I built a post-processing cleanup pass:
- Header/Footer Filtering: The system builds a spatial histogram of dates. If a specific date appears at the exact same vertical coordinates across multiple pages, it is flagged as a header/footer element and ignored.
- Deduplication: Identical events (same label, date, and page) are merged.
- Pill-Based Classification: Dates with recognizable deadline terms ("Closing", "Earnest Money", "Title Review") are given priority, while ambiguous dates are marked as low-confidence and routed to the
needs_reviewlist.
The Next Step: OneDrive & Microsoft Graph Webhooks
Right now, the system triggers when a file is manually uploaded. The next phase is connecting it directly to our file directories via Microsoft Graph.
By subscribing to Graph change notifications (webhooks) and running delta queries on a shared OneDrive folder, we can completely automate ingestion:
- A user drops a new file or updates an existing document in OneDrive.
- Microsoft Graph sends a webhook notification to our VPS.
- The VPS fetches the file differential, processes the PDF, stores the rows, and posts to Slack.
- If a file is moved to a
/Cancelledfolder, the pipeline automatically archives the dates in Cloudflare D1.
This turns the app from a simple developer script into a fully integrated business workflow.
Wrap Up: Why This Was Fun
Automation is most satisfying when it is grounded in reality. This project wasn't about building a fully autonomous, black-box AI system. It was about using Document AI to do the tedious heavy-lifting of raw extraction, combined with a human-in-the-loop interface that leaves the reviewer in complete control.
With Python, Cloudflare's edge storage, Document AI/LlamaParse, and a bit of Slack UI formatting, we are building an elegant, auditable loop that makes date management painless.
Let's keep building.