13-node LangGraph financial SQL agent with Prophet forecasting, MESA scenario simulation, semantic cache, RAG-assisted SQL generation, and automated email / Sheets delivery.
dev-module-agent takes natural-language business questions, grounds them on
a DuckDB warehouse via RAG over schema embeddings, generates and executes
SQL, forecasts with Prophet, simulates what-ifs with a MESA agent-based
model, caches semantically similar queries in Qdrant, and delivers the
results to email or Google Sheets on a schedule.
NL question
│
▼
[ 1 ] intent_classifier ← analytic / forecast / scenario / report
│
▼
[ 2 ] safety_gate ← block risky queries, PII leakage, scope check
│
▼
[ 3 ] semantic_cache_lookup ← Qdrant similarity hit?
│
├─ HIT → skip to [ 12 ]
▼
[ 4 ] schema_retriever ← RAG over schema embeddings (Qdrant)
│
▼
[ 5 ] sql_generator ← LLM writes SQL grounded on retrieved schema
│
▼
[ 6 ] sql_validator ← parse + dry-run; rewrite on failure
│
▼
[ 7 ] duckdb_executor ← run against financial.duckdb
│
▼
[ 8 ] forecast? ← if intent ∈ {forecast}, fan out to Prophet
│ │
│ └──► Prophet model (forecasting/)
│
▼
[ 9 ] simulate? ← if intent ∈ {scenario}, fan out to MESA
│ │
│ └──► MESA ABM (simulation/)
│
▼
[ 10 ] result_synthesizer ← merge SQL + forecast + scenario outputs
│
▼
[ 11 ] safety_review ← PII redaction + result-shape check
│
▼
[ 12 ] semantic_cache_write ← store (question_embedding, result) in Qdrant
│
▼
[ 13 ] delivery_dispatcher
├─ email (Gmail OAuth)
├─ Google Sheets append (Sheets API)
└─ direct response
Every node writes a checkpoint to snapshots/ so a crashed run can be
resumed at the failing node, not from scratch.
A single "RAG → SQL → run" chain falls over the moment a question requires forecasting or scenario simulation. Splitting into nodes lets the graph:
- Skip the heavy nodes (forecast / simulate) when the intent doesn't warrant them.
- Retry an individual node (e.g., regenerate SQL after a parse failure) without re-running upstream nodes.
- Branch into Prophet and MESA in parallel for compound questions like "forecast Q4 revenue and simulate the impact of a 5% price cut".
- Gate every state transition with a safety check (nodes 2 and 11).
- Cache at both ends — semantic-similarity at the front, structured result at the back — so repeated questions return instantly.
forecasting/ wraps Facebook Prophet:
- Pulls a time-series from the DuckDB warehouse using the SQL produced upstream.
- Fits a Prophet model with auto-detected seasonality.
- Generates forecasts at the requested horizon with
yhat,yhat_lower,yhat_upper. - Decomposes trend / weekly / yearly / holiday components for explainability.
- Returns a structured object the result synthesiser can graph or serialise.
simulation/ runs an agent-based model over the business question:
- Customer / segment / channel agents instantiated from the warehouse.
- Scenario lever exposed as a parameter (price change, churn shock, marketing spend shift).
- Monte-Carlo runs return distributional outcomes, not point estimates.
- The synthesiser merges the ABM output with the deterministic SQL result so the report shows both "what is" and "what could be".
qdrant_data/ persists embeddings of past questions and their results.
On every new question:
- Embed the question via the configured embedder.
- Query Qdrant for the top-K similar past questions.
- If similarity ≥ threshold AND result freshness is acceptable, return the cached result.
- Otherwise, run the full pipeline and write the new result into the cache.
This is the single largest cost saver — repeat or near-repeat questions do not re-hit the LLM or the warehouse.
safety/ runs two gates:
- Pre-execution gate (node 2) — refuse out-of-scope queries (modifying ledgers, hitting PII columns the user lacks access to), block obviously risky SQL patterns, enforce read-only roles.
- Post-execution gate (node 11) — scan the result set for PII / secret tokens; redact before delivery; clip oversized result payloads.
Both gates write to an audit log so a reviewer can trace every refusal.
delivery/ ships results via:
- Gmail (OAuth) — formatted Markdown / HTML email with attachments for forecasts and ABM plots.
- Google Sheets — appends rows to a configurable spreadsheet for dashboard consumption.
- Direct response — returns to the caller for API / chat-bot usage.
scheduler/ lets the same question be scheduled (e.g., "every Monday at
08:00 deliver this dashboard"). The scheduler uses LangGraph
checkpointing so a deferred run can resume cleanly.
git clone https://github.com/krishddd/dev-module-agent.git
cd dev-module-agent
pip install -r requirements.txt
cp .env.example .env # Google OAuth + LLM provider creds
# Seed the DuckDB warehouse (one-time)
python setup_db.py
# Bring up Qdrant + the agent
docker compose up -d
# Run a question
python -m agent.run "Show me Q3 revenue vs forecast for the EMEA segment"
# Schedule a recurring question
python -m scheduler.schedule \
--cron "0 8 * * 1" \
--question "Weekly EMEA revenue snapshot vs forecast" \
--deliver "sheets:my_dashboard"API mode:
uvicorn server.api:app --reload --port 8000
curl -X POST http://localhost:8000/ask \
-H 'Content-Type: application/json' \
-d '{"question": "Forecast Q4 revenue for EMEA with a 5% price cut"}'agent/ Tool-using agent loop
pipeline/ 13-node LangGraph pipeline definition
forecasting/ Prophet wrappers + decomposition helpers
simulation/ MESA ABM scenario simulator
scheduler/ Cron scheduler with LangGraph checkpointing
delivery/ Gmail + Google Sheets + direct delivery
safety/ Pre/post execution safety gates
core/ Shared primitives (embedding, IO, types)
database/ DuckDB connection layer + SQL helpers
server/ FastAPI control plane
config/ Agent + pipeline + delivery config
auth_google.py Google OAuth setup
setup_db.py Seed financial.duckdb from sample data
docker-compose.yml Qdrant + agent compose
financial.duckdb Warehouse (gitignored)
qdrant_data/ Semantic-cache persistence (gitignored)
snapshots/ Pipeline state checkpoints (gitignored)
training_data/ Schema / few-shot data (gitignored)
tests/ Safety + pipeline integration tests
docs/ Long-form notes
| Env var | Meaning |
|---|---|
LLM_PROVIDER |
openai / anthropic / ollama |
LLM_MODEL |
Model name for the SQL generator |
EMBEDDING_MODEL |
Model for schema + question embeddings |
DUCKDB_PATH |
Path to financial.duckdb |
QDRANT_URL |
Qdrant endpoint (default http://localhost:6333) |
QDRANT_CACHE_COLLECTION |
Collection name for the semantic cache |
CACHE_SIMILARITY_THRESHOLD |
Above this we serve from cache |
CACHE_MAX_AGE_HOURS |
Refresh stale cache entries past this age |
GOOGLE_OAUTH_CLIENT_SECRET_PATH |
Path to OAuth client secret JSON |
GOOGLE_OAUTH_TOKEN_PATH |
Path to OAuth token JSON |
SAFETY_BLOCK_DENYLIST |
Comma-separated SQL patterns to refuse |
SCHEDULER_TZ |
Cron timezone |
Personal portfolio. Tests cover the safety gates and the pipeline integration paths.
MIT