Project record

Sales Intelligence Agent

FastAPI and LangGraph sales-intelligence API that answers structured and causal questions over a cleaned SQLAlchemy star schema plus business-note retrieval, with citations, semantic caching, async queueing, and golden-set evals.

Complete State since Aug 6, 2026 Python · FastAPI · LangGraph · SQLAlchemy · SQLite · PostgreSQL · ChromaDB · Gemini embeddings · Redis · Upstash Redis · QStash · deepseek-v4-flash · Langfuse · Golden-set evals
Ruled evidence ledger with completed marks and one separated boundary line
Editorial illustration — a ruled ledger with one separated line, used for the Sales Intelligence Agent case study, which keeps repository evidence distinct from deployment claims.

Current state. Public repository and docs describe a cited sales-intelligence API over cleaned structured data and redacted business notes; this portfolio presents the documented architecture, benchmarks, and lessons learned without claiming a live deployment or production adoption.

Context

“Why did SparkClean 1kg sales spike in Mumbai in Sep 2025?”

That is the kind of question this agent answers. It turns a messy sample FMCG sales export — 8 CSV tables across 52 weeks, 5 product categories, and 12 territories, plus 30 business-note documents — into a question-answering API. WHAT questions are answered from the structured data; WHY questions must back their causal claims with citations retrieved from the notes.

Problem

The hard part was never just wiring an LLM to a database. The system needed to separate three different contracts:

  • WHAT questions should return factual answers from the structured dataset.
  • WHY questions should return causal analysis only when citations are available.
  • WHAT_TO_DO questions should remain recommendations with PENDING_APPROVAL, never decisions presented as fact.

That contract had to survive bad source data. The cleaning pass found 10,972 mixed-format dates, 9,416 non-numeric sales-value strings, 771 9999 sentinel volumes, 734 negative-unit rows, 23 duplicate primary-sales pairs, and 12 PII redactions in the unstructured notes. Later audit work also found that the dataset’s value column is mostly synthetic: 53,849 of 58,262 valid rows match 0.75 × MRP × units exactly, with another 4,385 within ₹1 rounding.

Approach

The architecture follows the repo’s accepted decisions:

  1. Clean first, then reason. The pipeline normalizes dates and value strings, deduplicates rows, redacts PII from business notes, and preserves bad-unit rows via null-with-flag handling, keeping the audit trail inspectable.
  2. One agent, three tools. A single LangGraph loop calls query_database, search_docs, and describe_database — no multi-agent supervisor. The repo ADRs make the trade-off explicit: lower latency, less state complexity, fewer moving parts.
  3. Structured data + retrieval together. The structured side uses a SQLAlchemy star schema; the unstructured side indexes the 30 business notes in ChromaDB with Gemini embeddings so WHY answers can cite qualitative evidence.
  4. Serverless-safe async path. POST /ask enqueues via QStash, the signed webhook processes the request, and Upstash-backed Redis stores intermediate and semantic-cache state. /ask-direct remains available for synchronous runs.
  5. Validation as a product boundary. The agent uses a two-pass output flow and enforces response contracts in code: WHY needs citations, WHAT_TO_DO must stay PENDING_APPROVAL, and tool failures map to an explicit error status.

Tech stack / architecture

  • API layer: FastAPI endpoints for /ask, /ask-direct, /webhook/process, and cache invalidation.
  • Agent runtime: LangGraph single-agent tool loop with deepseek-v4-flash as the default model.
  • Structured analytics layer: SQLAlchemy over a star schema spanning facts, dimensions, promotions, and stockouts; local SQLite with PostgreSQL as the production target.
  • Retrieval layer: ChromaDB vector search over 30 cleaned business-note documents using Gemini embeddings (gemini-embedding-2, 1536 dimensions).
  • Caching: Redis semantic cache with cosine similarity threshold 0.97 and 600-second TTL.
  • Async processing: QStash queue plus signed webhook flow; Upstash Redis for serverless-compatible state.
  • Observability: optional Langfuse tracing for LLM calls, chains, and tool invocations.
  • Evaluation: 14-question golden set with policy checks, runnable in fake or live mode.

Evidence

The repo ships unusually complete public evidence:

  • README.md documents the architecture, API surface, and tech stack.
  • APPROACH.md records the data-cleaning ledger, tool design, queue flow, cache behavior, and major limitations.
  • docs/adr/README.md indexes six accepted ADRs covering the agent loop, star schema, QStash choice, semantic cache, PII redaction, and model selection.
  • docs/DATA_QUALITY.md deepens the anomaly catalogue, including the synthetic value finding and unresolved edge cases.
  • docs/LESSONS_LEARNED.md preserves the failed RQ-first plan and the serverless pivot to QStash/Upstash.

Evidence boundary

This entry is a repository-backed case study, not proof of a live system:

  • no deployed badge, live URL, or production-adoption claim;
  • no invented business metrics beyond what the repository already documents;
  • no claim that sparse promotions and stockouts coverage explains every sales movement;
  • the synthetic value column is not presented as an independent source of pricing truth.

Outcomes

The reconciliation and audit trail preserve 38,630,596 validated units across 52 weeks: problematic rows are kept annotated, not deleted. The eval harness turned model choice into a measurement: the 14-question golden set kept deepseek-v4-flash over kimi-k2.6 on both pass rate and wall time. The hardening pass expanded verification from 70 to 98 passing tests and added benchmark, ADR, and data-quality docs.

Read this as an in-development, public-safe architecture case study — evidence-backed, but not proof of a live customer deployment, production adoption, or business ownership.

Next

If the public evidence set expands later, the strongest follow-up angles are already clear from the repo: selective cache invalidation, richer promo/stockout evidence for causal answers, and further benchmark/eval work. Until then, the most honest value is the current one: a fully inspectable record of how the system was built, where the data lied, and which engineering decisions held up under measurement.