Introduction
In ecommerce, pricing is the single most powerful lever for revenue optimization. Enterprises routinely run A/B pricing experiments—showing different price points to different customer segments—to maximize conversion and margin. However, a dangerous analytical trap lurks in these experiments: confusing correlation with causation.
A price drop of 15% might correlate with a 30% spike in sales, leading teams to conclude the price cut caused the surge. But what if a major competitor went out of stock that same week? What if a viral social media post drove traffic independently? Without rigorous causal inference, pricing decisions based on correlational data lead to margin erosion, misallocated budgets, and flawed pricing strategies. This article details how we built an enterprise-grade system using Multi-Agent LangGraph with RAG and persistent state to systematically distinguish correlation from causation in ecommerce pricing experiments.
The Challenge: Spurious Correlations in Pricing Experiments
When analyzing pricing experiments, data science teams encounter three primary confounding traps:
Temporal Confounders: Seasonality, holidays, and macroeconomic events correlate with both price changes and demand shifts. A Black Friday price cut appears causal, but demand would have surged regardless.
Competitor Interference: A competitor's simultaneous promotion or stockout creates a spurious correlation between your price change and your conversion lift.
Selection Bias: If the treatment group (customers seeing the new price) differs systematically from the control group in unobserved ways (e.g., higher intent buyers were routed to the experiment), the measured effect is biased.
Traditional dashboards and simple A/B test calculators cannot detect these confounders. They report a p-value and a lift percentage, leaving the causal question unanswered.

The Solution: Causal Inference Meets Multi-Agent RAG
Our approach combines statistical causal inference methods (Difference-in-Differences, confounder detection) with RAG-powered contextual retrieval. The key insight is that determining causation requires context—historical experiment results, competitor intelligence, and market event calendars—that lives in unstructured documents.
We orchestrate this through a LangGraph multi-agent system:
Experiment Data Agent: Extracts structured metrics (conversion rates, revenue per session) for treatment and control groups.
RAG Context Agent: Queries a vector database for historical pricing experiments, competitor activity logs, and market event calendars to identify potential confounders.
Causal Inference Agent: Applies Difference-in-Differences (DiD) logic and confounder scoring to determine whether the observed effect is likely causal or spurious.
Reporting Agent: Synthesizes the causal verdict with explainable reasoning, leveraging persistent memory to track the experiment's lifecycle.
Real-Time Use Case: Dynamic Pricing for Electronics During Holiday Season
The Scenario: An ecommerce platform runs a pricing experiment on wireless earbuds in December. The treatment group sees a 12% price reduction. Results show a 28% conversion lift. The pricing team wants to roll this out permanently.
The Problem: December is peak holiday season. Competitor X ran a massive ad campaign that week. The 28% lift might be entirely driven by seasonal demand and competitor spillover, not the price cut.
The Workflow: Our LangGraph system retrieves historical December experiments (which show similar lifts even without price cuts), identifies the competitor campaign as a confounder, applies DiD analysis against a non-electronics control category, and concludes: "The observed 28% lift is likely 70% seasonal/confounded. True causal price elasticity is approximately 8%. Recommend against permanent price cut."
Enterprise Multi-Agent LangGraph Architecture
The architecture leverages LangGraph's conditional edges and persistent memory to allow agents to iteratively investigate confounders before rendering a causal verdict.
Step-by-Step POC Implementation
Step 1: Defining State, Memory, and Causal Schema
We define the state to carry experiment metrics, retrieved context, confounder analysis, and the final causal verdict.
# backend/graph_state.py
from typing import TypedDict, List, Annotated, Literal, Optional
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver
class PricingExperimentState(TypedDict):
experiment_id: str
treatment_lift_pct: float
control_lift_pct: float
retrieved_context: List[str]
identified_confounders: List[str]
causal_verdict: Literal["CAUSAL", "SPURIOUS", "PARTIALLY_CONFOUNDED"]
true_effect_estimate: Optional[float]
final_report: str
agent_trace: Annotated[List[str], "Audit trail of causal reasoning"]
memory = MemorySaver()
Step 2: Building the Multi-Agent Causal Inference Workflow
We define agents that extract data, retrieve RAG context, perform causal analysis, and report findings.
# backend/agents.py
from .graph_state import PricingExperimentState, memory
MOCK_VECTOR_DB = {
"electronics_december": [
"Historical Experiment #2024-DEC-12: 25% conversion lift observed in electronics with NO price change. Attributed to holiday demand surge.",
"Competitor Intel: Competitor X ran 'Mega Deals' campaign Dec 10-20, driving category-wide traffic increase of 40%.",
"Market Calendar: December 15-25 is peak holiday shopping window. Baseline conversion naturally increases 20-30%."
],
"apparel_march": [
"Historical Experiment #2025-MAR-05: 12% lift with 10% price cut in apparel. No major confounders identified. Effect deemed causal."
]
}
def experiment_data_agent(state: PricingExperimentState):
"""Extracts structured experiment metrics."""
state["agent_trace"].append("Data Agent: Extracted treatment lift and control group metrics.")
return {"control_lift_pct": 22.0} # Simulated baseline seasonal lift
def rag_context_agent(state: PricingExperimentState):
"""Retrieves historical experiments and market context via RAG."""
context = MOCK_VECTOR_DB.get("electronics_december", [])
state["agent_trace"].append(f"RAG Agent: Retrieved {len(context)} contextual documents about historical experiments and market conditions.")
return {"retrieved_context": context}
def causal_inference_agent(state: PricingExperimentState):
"""Applies DiD logic and confounder detection."""
treatment_lift = state["treatment_lift_pct"]
control_lift = state["control_lift_pct"]
context = state["retrieved_context"]
# Difference-in-Differences: True effect = Treatment Lift - Control (Baseline) Lift
did_estimate = treatment_lift - control_lift
# Confounder detection from RAG context
confounders = []
for doc in context:
if "holiday" in doc.lower() or "seasonal" in doc.lower():
confounders.append("Seasonality/Holiday Demand")
if "competitor" in doc.lower():
confounders.append("Competitor Campaign Interference")
confounders = list(set(confounders))
# Causal verdict logic
if len(confounders) >= 2:
verdict = "PARTIALLY_CONFOUNDED"
elif did_estimate < 5.0:
verdict = "SPURIOUS"
else:
verdict = "CAUSAL"
state["agent_trace"].append(f"Causal Agent: DiD estimate = {did_estimate}%. Confounders found: {confounders}. Verdict: {verdict}")
return {
"identified_confounders": confounders,
"causal_verdict": verdict,
"true_effect_estimate": round(did_estimate, 2)
}
def reporting_agent(state: PricingExperimentState):
"""Generates the final explainable causal report."""
report = (
f"Experiment {state['experiment_id']} Causal Analysis Report\n"
f"Observed Treatment Lift: {state['treatment_lift_pct']}%\n"
f"Baseline Control Lift: {state['control_lift_pct']}%\n"
f"DiD True Effect Estimate: {state['true_effect_estimate']}%\n"
f"Identified Confounders: {', '.join(state['identified_confounders'])}\n"
f"Causal Verdict: {state['causal_verdict']}\n"
)
state["agent_trace"].append("Reporting Agent: Final causal report generated.")
return {"final_report": report}
# Build the Graph
workflow = StateGraph(PricingExperimentState)
workflow.add_node("data", experiment_data_agent)
workflow.add_node("rag", rag_context_agent)
workflow.add_node("causal", causal_inference_agent)
workflow.add_node("report", reporting_agent)
workflow.set_entry_point("data")
workflow.add_edge("data", "rag")
workflow.add_edge("rag", "causal")
workflow.add_edge("causal", "report")
workflow.add_edge("report", END)
app = workflow.compile(checkpointer=memory)
Step 3: The FastAPI Backend
# backend/main.py
from fastapi import FastAPI
from pydantic import BaseModel
from .agents import app
app_api = FastAPI(title="Causal Pricing Experiment Analyzer")
class PricingRequest(BaseModel):
experiment_id: str
treatment_lift_pct: float
thread_id: str = "pricing_audit_01"
@app_api.post("/analyze-pricing-experiment")
async def analyze_pricing(req: PricingRequest):
config = {"configurable": {"thread_id": req.thread_id}}
initial_state = {
"experiment_id": req.experiment_id,
"treatment_lift_pct": req.treatment_lift_pct,
"control_lift_pct": 0.0,
"retrieved_context": [],
"identified_confounders": [],
"causal_verdict": "",
"true_effect_estimate": None,
"final_report": "",
"agent_trace": []
}
final_state = app.invoke(initial_state, config)
return {
"report": final_state["final_report"],
"verdict": final_state["causal_verdict"],
"true_effect": final_state["true_effect_estimate"],
"confounders": final_state["identified_confounders"],
"agent_trace": final_state["agent_trace"]
}
Step 4: The Streamlit Frontend
# frontend/app.py
import streamlit as st
import requests
st.set_page_config(page_title="Causal Pricing Analyzer", layout="wide")
st.title(" Ecommerce Pricing: Correlation vs. Causation Analyzer")
st.markdown("*Multi-Agent LangGraph RAG with Causal Inference*")
st.sidebar.header("Experiment Input")
exp_id = st.sidebar.text_input("Experiment ID", "EXP-DEC-2026-001")
treatment_lift = st.sidebar.slider("Observed Treatment Lift (%)", 0.0, 60.0, 28.0)
thread_id = st.sidebar.text_input("Audit Thread ID", "pricing_thread_01")
if st.sidebar.button("Analyze Causality"):
with st.spinner("Agents are retrieving context and running causal inference..."):
response = requests.post(
"http://localhost:8000/analyze-pricing-experiment",
json={"experiment_id": exp_id, "treatment_lift_pct": treatment_lift, "thread_id": thread_id}
)
if response.status_code == 200:
data = response.json()
col1, col2 = st.columns(2)
with col1:
st.subheader("Causal Verdict")
if data["verdict"] == "CAUSAL":
st.success(f" {data['verdict']}")
elif data["verdict"] == "SPURIOUS":
st.error(f" {data['verdict']}")
else:
st.warning(f" {data['verdict']}")
st.metric("True Causal Effect (DiD)", f"{data['true_effect']}%")
st.subheader("Identified Confounders")
for c in data["confounders"]:
st.info(f" {c}")
with col2:
st.subheader("Full Causal Report")
st.text(data["report"])
st.subheader("Agent Reasoning Trace")
for trace in data["agent_trace"]:
st.write(f" {trace}")
else:
st.error("Failed to connect to analysis engine.")
Conclusion
Distinguishing correlation from causation in ecommerce pricing experiments is not merely a statistical exercise—it is a business-critical capability that prevents millions in margin erosion. Traditional A/B testing tools report lifts but remain blind to confounders like seasonality, competitor actions, and selection bias.
By architecting a Multi-Agent LangGraph system with RAG, we empowered specialized agents to collaboratively investigate causality. The Data Agent extracts metrics, the RAG Agent surfaces critical historical and market context, the Causal Inference Agent applies rigorous Difference-in-Differences methodology, and the Reporting Agent delivers an explainable verdict. Persistent memory ensures every experiment's causal audit trail is preserved for compliance and future learning. This approach transforms pricing teams from reactive correlational thinkers into proactive causal strategists.

Join the conversation! Your thoughts help the community grow.