This repo turns informal workshop emails into a review packet a coordinator can read before taking action.
The messages in this repo are intentionally written like real email, not like forms. A live LangGraph workflow uses an OpenAI chat model to extract the fields it can support, then a checked-in Excel catalog applies the rule-based match and writes a packet led by a plain-language summary. The workflow does not send messages, approve requests by itself, or claim production mailbox coverage.
The first artifact to open is outputs/ws-1002/reader-summary.md. It shows the path from messy source email to reviewed request, catalog decision, and human-visible follow-up note.
Inputs:
- sample
.emlmessages under fixtures/inbox - an Excel catalog under fixtures/workbook/community_workshop_catalog.xlsx
OPENAI_API_KEYfrom the local shell, secret manager, or CI secret- optional
WORKSHOP_INBOX_OPENAI_MODELwhen you want to override the validated default modelgpt-4.1-mini
Outputs:
reader-summary.md: the plain-language packet for first reviewcoordinator_note.txt: the response note a person can edit or copy into the real communication channelnormalized_request.json: extracted fields and extraction notes for technical inspectioncatalog_match.json: the selected workbook row and comparison notes
Automation helps with live field extraction, alias normalization, table matching, and packet writing. A human remains responsible for approving the final note and deciding whether the request should proceed.
This pattern fits routine inbound messages that need live interpretation, matching against trusted tabular policy or catalog data, and a reviewable output bundle before action. It works best when the safest design is:
- live extraction for messy wording
- rule-based matching against trusted workbook data
- visible review notes instead of silent auto-send behavior
The implementation is Python-based and intentionally narrow:
- runtime: Python module with a CLI proof path and an optional desktop review surface
- extraction boundary: LangGraph orchestration with structured OpenAI output and one repair pass for incomplete or contradictory fields
- matching boundary: workbook-backed rules for aliases, participant limits, notice windows, and support-level compatibility
- storage format: checked-in
.emlfixtures, checked-in.xlsxcatalog, and generated review-packet files - integration surface: optional local Mailpit API adapter that exercises a real mailbox API boundary without external mailbox credentials
This public slice does not automate a browser, authenticated enterprise inbox, or custom production workbook.
In WS-1002, the sender writes a normal-looking email about a seed-starting session at the north library branch. The note mentions a larger-print handout, aisle space for mobility devices, and quiet seating near the door, but it never fills out labeled fields.
The live extraction workflow turns that message into a structured request, infers the accessibility review path, and records why that choice was made. The workbook layer then resolves the wording to the approved topic and neighborhood, checks participant and notice rules, and selects Northside Library Room A.
The packet starts with reader-summary.md, then keeps JSON files as backing evidence for reviewers who want to inspect the extracted fields and comparison notes.
Run the fixture-backed path from a fresh clone without creating local environment files inside the repo:
python3.11 -m venv /tmp/workshop-inbox-venv
source /tmp/workshop-inbox-venv/bin/activate
python -m pip install --disable-pip-version-check -r requirements.txt
export OPENAI_API_KEY=<your-local-secret>
export WORKSHOP_INBOX_OPENAI_MODEL=gpt-4.1-mini
python -m workshop_inbox_app --sample-run --request-id WS-1002 --output-root /tmp/workshop-inbox-output
sed -n '1,120p' /tmp/workshop-inbox-output/ws-1002/reader-summary.mdOPENAI_API_KEY must come from your local shell, secret manager, or CI secret; it is not stored in this repo. WORKSHOP_INBOX_OPENAI_MODEL is optional. The public validation path used gpt-4.1-mini.
That command writes a scratch packet under /tmp/workshop-inbox-output/ws-1002/ and leaves the checkout clean. To refresh the checked-in example packet intentionally, run the same module command with --output-root outputs.
The repo also includes a bounded live route with Mailpit. This proves the application can connect to a mailbox API, read messages from that API, and process those messages through the same live extraction, workbook matching, and packet-writing pipeline. It does not claim Microsoft Graph or OAuth production coverage.
Start the local mail server, seed the public examples, run the pipeline against the API, then shut the container down:
docker compose up -d mailpit
curl -fsS http://localhost:8025/api/v1/info >/tmp/workshop-mailpit-info.json
python3.11 -m venv /tmp/workshop-inbox-mail-venv
source /tmp/workshop-inbox-mail-venv/bin/activate
python -m pip install --disable-pip-version-check -r requirements-live.txt
export OPENAI_API_KEY=<your-local-secret>
export WORKSHOP_INBOX_OPENAI_MODEL=gpt-4.1-mini
python -m workshop_inbox_app --seed-mail-api --mail-api-base-url http://localhost:8025 --clear-mail-api
python -m workshop_inbox_app --sample-run --source mail-api --mail-api-base-url http://localhost:8025 --request-id WS-1002 --output-root /tmp/workshop-inbox-mail-output
sed -n '1,120p' /tmp/workshop-inbox-mail-output/ws-1002/reader-summary.md
docker compose down -vMailpit exposes its web UI and API on port 8025 and SMTP on 1025. The seed command uses the HTTP send API with the checked-in fictional messages, so no mailbox credentials are required. Set MAIL_API_BASE_URL instead of passing --mail-api-base-url when you want the command to point at another local-compatible mail API endpoint.
- workshop_inbox_app: LangGraph extractor, workbook loader, matcher, packet writer, CLI entry point, optional GUI, and optional local mail API adapter
- fixtures: public sample inbox messages and catalog workbook
- outputs: checked-in review packet for the main sample
- docs/methodology.md: plain-language method notes followed by implementation details
- docs/validation.md: bounded validation commands and status
- tests: evergreen checks for graph repair, alias resolution, matching, and packet generation
After installing requirements.txt, run:
python -m unittest discover -s testsThe tests cover graph repair for an incomplete first pass, alias resolution, catalog matching, packet writing, a participant-count rejection path, and local Mailpit payload/envelope handling.
The CLI proof path is the stable public route. The package also contains a PySide6 desktop review surface for local inspection; install requirements-gui.txt if you want to open it.
The Mailpit route is intentionally bounded. It reads from a local Mailpit server, writes no outbound real-world messages, and uses public sample messages. requirements-live.txt is present so reviewers can install the live path explicitly; it does not add extra Python packages beyond the base app requirements.
This repo stops at a reproducible review packet. It does not:
- approve requests automatically
- send outbound messages
- support Microsoft Graph, OAuth, or a real mailbox tenant
- ingest attachments or custom workbook templates
- handle multi-reviewer assignment, retention, monitoring, or deployment hardening
Those are normal production concerns, but they depend on the actual operating environment and should be designed after the workflow contract is validated with real users.
Author: Juan Luis Herrera Cortijo
Contact: juan.luis.herrera.cortijo@gmail.com
GitHub: https://github.com/JLHerreraCortijo
Copyright: Copyright (c) 2026 Juan Luis Herrera Cortijo
License: Portfolio Review License. See LICENSE. Third-party dependencies retain their own licenses.