← All labsLab 02 / Python / LangGraph / SQLite

Enquiry Review Agent

Persist an enquiry draft, pause for a decision, resume after restart, and prevent duplicate local outputs.

A reviewed workflow

The graph drafts an acknowledgement, persists its state in SQLite, pauses for a human decision, and creates a local outbox record only after approval. Rejection creates no outbox item. It never sends email or changes a customer record.

Install and start

Download and extract the archive. Run from the extracted root with Python 3.12:

python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r labs/requirements-test.txt
python -m labs.enquiry_review.agent start --job example-1 --fixture

The printed draft is waiting for review. The process can now exit; its checkpoint remains in SQLite.

Resume in a new process

python -m labs.enquiry_review.agent resume   --job example-1 --decision approve --fixture

Use a new job ID and --decision reject to inspect rejection. Repeating approval for an already completed job returns the saved result without creating another output. A conflicting existing file fails rather than being overwritten.

Understand the action boundary

The approval interrupt occurs before the local write. The outbox uses a stable hashed job name and atomic file creation. This is a narrow demonstration of restart and idempotency, not a production messaging connector. A real integration needs its own identity checks, permitted operations, and transaction semantics.

Verification

Tests exercise approval, rejection, invalid decisions, duplicate jobs, conflicting output, and an actual start/resume across separate Python processes. Fixture mode is model-free. Live Ollama drafting is supported by omitting --fixture after starting Ollama, but was not part of initial verification.

python -m unittest discover -s labs/tests -v

Read the working details

The archive includes the graph, shared local-model helper, pinned test dependencies, tests, and operating instructions. The source keeps generation, review, and final output as distinct nodes so their responsibilities can be inspected.