Phong Trang

Data Analyst Agent: Reducing Ad-hoc Requests by 40% with LangGraph

By Phong Trang - Data Platform Product Manager - thanhphong.trang@gmail.com

Data Analyst Agent Banner

โ„น๏ธ Executive Summary

  • Role: Product Manager | Industry: Web Analytics & Data Platform
  • Key Impact:
    • 40% reduction in ad-hoc data requests within 30 days
    • Saved ~50 hours/month of analyst time for strategic work
    • 85% accuracy on automated query types (behavioral analytics, conversion metrics)
    • ROI positive from week 2 of deployment
  • Technical Stack: LangGraph Azure OpenAI Streamlit SQLAlchemy Python
  • Timeline: 5 days POC development, 1 month pilot validation

๐ŸŽฏ The Problem: Drowning in Data Requests

Our web analytics team received 30-50 ad-hoc data requests weekly from product managers, marketers, and executives. Most were variations of the same questions:

Analysts spent 60% of their time writing SQL queries and formatting results instead of generating insights. Stakeholders waited 2-3 days for answers to simple questions.

Why This Matters

The cost wasn't just about time but it also include opportunity cost. While analysts manually queried data, they couldn't:


๐Ÿ’ก The Approach: POC First, Perfect Later

Instead of building a comprehensive self-service analytics platform (6+ months), I chose a targeted proof-of-concept to validate demand and learn fast.

Why a POC?

Decision Rationale
Validate demand Test if automation truly reduces requests before large investment
Learn failure modes Discover edge cases in controlled environment
Build trust Quick wins with stakeholders before expanding scope
Constrained domain Google Analytics only which features stable schema, predictable queries

๐Ÿ—๏ธ Technical Architecture: The State Graph Workflow

The workflow represents a deliberate design philosophy: explicit control flow over black-box automation.

LangGraph State Machine

Why This Flow?

The graph structure addresses three critical requirements:

1. Viability: Not Every Question is a Data Question

Early testing revealed users asked off-topic questions like "How do I reset my password?" or "Why is the site slow?"

Solution: The check_relevance node routes non-data questions to generate_funny_response instead of failing ungracefully.

Design Decision: Separate routing for irrelevant questions prevents wasted API calls and provides better UX than generic error messages.

2. Implementation Feasibility: Error Recovery is Not Optional

LLMs generate syntactically correct but semantically wrong SQL. The first version crashed on:

Solution: The regenerate_query loop captures errors, passes them back to the LLM with context, and retries up to 3 times.

Key insight: LLMs can fix their own mistakes if you show them the error. 60% of failed queries succeeded on retry.

Error Recovery Process

LangGraph's error recovery workflow in action. When the LLM generates incorrect SQL (wrong column names or date formatting), the agent captures the database error, feeds it back to the LLM with context, and successfully auto-corrects within 3 retry attempts at 60% success rate on retry.

3. Cost Control: Prevent Infinite Loops

Without iteration limits, a malformed query could retry indefinitely, burning API credits.

Solution: The check_attempts_router enforces a maximum of 3 retries before routing to end_max_iterations.

โœ… Success Path

Question โ†’ Relevance Check โ†’ SQL Generation โ†’ Execution โ†’ Human-Readable Answer

โš ๏ธ Error Recovery Path

SQL Error โ†’ Capture Message โ†’ Regenerate with Context โ†’ Retry (max 3ร—) โ†’ Escalate if needed


๐Ÿ’ป Key Technical Decisions (Product Manager Perspective)

Decision 1: LangGraph State Machine vs. Simple LLM Chain

As a PM, I needed observability into each workflow step to diagnose failures and measure performance.

from langgraph.graph import StateGraph, END
from state.agent_state import AgentState

# Define workflow with explicit state transitions
workflow = StateGraph(AgentState)

# Add nodes (tasks)
workflow.add_node("check_relevance", check_relevance)
workflow.add_node("convert_to_sql", convert_nl_to_sql)
workflow.add_node("execute_sql", execute_sql)
workflow.add_node("regenerate_query", regenerate_query)

# Add conditional routing (decision points)
workflow.add_conditional_edges("check_relevance", relevance_router, {
    "convert_to_sql": "convert_to_sql",
    "generate_funny_response": "generate_funny_response"
})

workflow.add_conditional_edges("execute_sql", execute_sql_router, {
    "generate_human_readable_answer": "generate_human_readable_answer",
    "regenerate_query": "regenerate_query"
})

# Compile and deploy
app = workflow.compile()

Why This Matters (PM View)

Decision 2: Azure OpenAI for Enterprise Compliance

Security and compliance were non-negotiable for handling proprietary business data.

import os
from dotenv import load_dotenv
from openai import AzureOpenAI

# Azure OpenAI setup with enterprise controls
client = AzureOpenAI(
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),
    api_version="2024-02-15-preview",
    azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT")
)

def convert_nl_to_sql(state: AgentState) -> AgentState:
    """Convert natural language question to SQL query"""
    prompt = f"""Given this database schema:
{state['schema']}

Convert this question to SQL:
{state['question']}

Rules:
- Use DATE() for date comparisons
- Include query explanation as comment
- Limit results to 1000 rows max
"""
    
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.1  # Low temp for deterministic SQL
    )
    
    state["sql_query"] = response.choices[0].message.content
    return state

Why This Matters (Business Perspective)

Requirement Azure OpenAI Solution Alternative Risk
Data privacy No model training on our queries Direct OpenAI trains on enterprise data
Compliance EU data residency, GDPR compliant 6+ months compliance review for other providers
Cost ~20% premium, but approved vendor Cheaper options delay project by months

Trade-off accepted: Azure OpenAI costs ~$45/month vs. $35 for direct OpenAI, but compliance overhead of using non-approved providers would have delayed deployment by 4-6 months.


๐Ÿ“Š Results: One Month Pilot Validation

Error Recovery Process

Query Coverage: 40% Automation Rate

โœ… Handled Query Types (40%)

  • Conversion funnels: "What's our signup-to-purchase rate?"
  • Behavioral analytics: "Which pages have highest engagement?"
  • Trend analysis: "How has bounce rate changed over time?"
  • Segmentation: "Compare mobile vs. desktop users"

โŒ Not Handled (60%)

  • Complex multi-table joins with business logic
  • Queries requiring data outside GA warehouse
  • Questions needing interpretation or judgment
  • Ad-hoc data collection or instrumentation requests

Time & Cost Impact

Metric Manual Process Agent Automation Improvement
Time per query 45 minutes 2 minutes 96% faster
Queries handled (month 1) โ€” 127 queries โ€”
Hours saved โ€” ~50 hours/month $2,500 value
Accuracy rate 100% (manual) 85% correct 12% need review

ROI Breakdown

Development Investment

  • 3 days POC build + 2 days refinement = ~40 hours

Monthly Operational Cost

  • Azure OpenAI API: $45 (GPT-4, ~127 queries ร— 3 calls avg)
  • Streamlit hosting: $0 (internal server)
  • Maintenance: ~2 hours/month (prompt tuning, schema updates)

Monthly Value: 50 hours saved ร— $50/hour = $2,500

Payback Period: <1 week


๐ŸŽ“ Key Learnings: AI is Good at Nodes, Humans Design Workflows

1. Constrained Domains are AI's Sweet Spot

The agent works because Google Analytics data is:

Insight: Expanding to other data sources requires similar constraints. Ad-hoc, poorly documented databases would tank accuracy.

2. Transparency Builds Trust

Showing the generated SQL query (not just results) lets analysts:

Black-box "magic" would have faced resistance. Transparency turned skeptics into champions.

3. Error Handling is the Product

Most development time (60%) went to edge cases:

The "happy path" was 20% of the work. Production-ready means handling failure gracefully.

4. Humans Still Design the Workflow

LLMs excel at individual tasks (SQL generation, formatting results), but cannot design the workflow:

The state graph represents human expertise about how data questions should be processed. AI fills in the nodes; I designed the edges.


๐Ÿš€ What's Next: Scaling Beyond POC

Immediate (Month 2-3)

Medium-term (Q2 2026)

Long-term Considerations


๐Ÿ› ๏ธ Skills Demonstrated


๐Ÿค™๐Ÿป Let's Connect

๐Ÿ“ง thanhphong.trang@gmail.com
๐Ÿ’ผ LinkedIn Profile

Available for: Product Manager, Data Platform, AI/ML Product roles
Location: Gothenburg, Sweden


๐Ÿ“‚ Portfolio Artifacts

Code Repository Structure

/data-analyst-agent
โ”‚
โ”œโ”€โ”€ graph/
โ”‚   โ””โ”€โ”€ main_workflow.py          # LangGraph state machine definition
โ”‚
โ”œโ”€โ”€ routers/
โ”‚   โ””โ”€โ”€ main_routers.py           # Conditional routing logic
โ”‚
โ”œโ”€โ”€ state/
โ”‚   โ””โ”€โ”€ agent_state.py            # State schema for workflow
โ”‚
โ”œโ”€โ”€ tools/
โ”‚   โ”œโ”€โ”€ agent_tools.py            # Core functions (SQL gen, execution)
โ”‚   โ”œโ”€โ”€ sub_tools.py              # Utility functions
โ”‚   โ”œโ”€โ”€ schema_tools.py           # Database introspection
โ”‚   โ””โ”€โ”€ chart_tools.py            # Visualization generation
โ”‚
โ”œโ”€โ”€ database_query_agent_ui.py    # Streamlit UI
โ”œโ”€โ”€ requirements.txt              # Dependencies
โ””โ”€โ”€ .env.example                  # Configuration template

Code repository: not currently public.