A production-grade multi-agent investment research platform built with LangGraph and OpenAI. Input a ticker, get a structured buy/hold/sell investment memo generated by 9 specialized AI agents running in parallel against live market data — with a human-in-the-loop compliance gate before final synthesis.
🟢 Live Demo → financeagent-langgraph-production.up.railway.app
Enter any equity or crypto ticker. The system automatically detects the asset class, deploys a team of specialist agents in parallel, and produces a structured investment memo covering macro regime, fundamentals, bull/bear theses, valuation, risk, and sentiment — all from live data.
The pipeline pauses before final synthesis for mandatory human review, then generates the final recommendation on approval.
Equity (AAPL, MSFT, TSLA...) — fundamentals, valuation, bull/bear thesis, risk, sentiment, macro context
Crypto (BTC-USD, ETH-USD, SOL-USD...) — on-chain metrics, sentiment, risk, macro context
Step 1 — Analyze:
curl -X POST http://localhost:8000/analyze \
-H "Content-Type: application/json" \
-d '{"ticker": "AAPL", "timeframe": "3mo", "thread_id": "aapl-run-1"}'{
"status": "pending_approval",
"ticker": "AAPL",
"asset_class": "equity",
"intermediate": {
"macro": {"regime_label": "Risk-On Tightening", "fed_funds_rate": 3.64, "cpi_yoy": 3.32},
"fundamentals": {"PE_ratio": 33.54, "EPS": 8.26, "revenue_growth": 0.166},
"bull_thesis": {"confidence": "High", "key_catalysts": ["AI product cycle", "Services growth"]},
"bear_thesis": {"confidence": "Medium", "key_risks": ["Valuation stretched", "China exposure"]},
"valuation": {"valuation_label": "Overvalued"},
"risk": {"volatility": 25.29, "beta": 1.065},
"sentiment": {"sentiment_label": "bullish", "sentiment_score": 0.75}
}
}Step 2 — Approve:
curl -X POST http://localhost:8000/approve/aapl-run-1{
"status": "complete",
"supervisor_report": {
"recommendation": "Hold",
"confidence": "High",
"summary": "Apple presents a compelling AI-driven growth story...",
"bull_case": "Strong services momentum and AI product cycle...",
"bear_case": "Valuation at 33x earnings leaves limited margin of safety...",
"macro_context": "Risk-On Tightening regime supports growth equities but elevated rates pressure multiples...",
"key_metrics": ["P/E: 33.54", "Beta: 1.065", "Volatility: 25.29%", "CPI: 3.32%", "Regime: Risk-On Tightening"],
"analyst_agreement": "Disagreed — pipeline recommends Hold, analysts recommend Buy"
}
}POST /analyze (ticker, timeframe, thread_id)
│
▼
┌─────────────────┐
│ DataFetchAgent │ yfinance + CoinGecko + FRED
│ │ auto-detects asset class from quoteType
└────────┬────────┘
│
▼
┌─────────────────────┐
│ MacroRegimeAgent │ FRED → Fed funds rate, CPI, yield curve, unemployment
│ (always runs) │ classifies macro regime → injects context downstream
└──────────┬──────────┘
│
┌─────┴──────┐
▼ ▼
EQUITY CRYPTO
┌──────────┐ ┌──────────┐
│Fundament.│ │OnChain │ ┐
│Sentiment │ │Sentiment │ │ parallel
│Risk │ │Risk │ ┘
└────┬─────┘ └────┬─────┘
│ (equity only)
┌────▼─────┐
│Bull │ ┐
│Bear │ │ parallel
│Valuation │ ┘
└────┬─────┘
│
▼ ⏸ interrupt_before
┌─────────────────────┐
│ SupervisorAgent │ GPT-4.1-mini — synthesizes all agent outputs
│ (Portfolio Mgr) │ → final buy/hold/sell memo
└─────────────────────┘
│
POST /approve/{thread_id}
│
▼
Investment Memo
| Source | Used For | Asset Class |
|---|---|---|
| yfinance | Price history, fundamentals, news, analyst consensus | Equity |
| CoinGecko | Market cap, volume, developer activity, community score | Crypto |
| FRED API | Fed funds rate, CPI, yield curve spread, unemployment | Both |
Asset class is detected automatically from yfinance quoteType — no user input required.
Benchmarked across 5 S&P 500 tickers using per-agent instrumented timing (benchmark.py). Production-traced via LangSmith across 65 runs.
| Metric | Value |
|---|---|
| Avg end-to-end latency | 17.60s |
| p50 latency | 16.4s |
| p99 latency | 25.3s |
| Cost p50 | $0.00180 per run |
| Cost p99 | $0.00197 per run |
Per-agent averages:
| Agent | Avg Latency |
|---|---|
| Data Fetch | 3.36s |
| Macro Regime | 0.80s |
| Fundamentals / Sentiment / Risk (parallel) | 1.42s wall clock |
| Bull / Bear / Valuation (parallel) | 2.63s wall clock |
| Supervisor | 8.93s |
SupervisorAgent accounts for 51% of total latency — the irreducible sequential bottleneck by design.
| Layer | Technology |
|---|---|
| Agent orchestration | LangGraph (StateGraph, SqliteSaver) |
| LLM — analysis agents | GPT-4.1-nano (7 agents) |
| LLM — supervisor | GPT-4.1-mini (1 agent) |
| Market data | yfinance |
| Crypto data | CoinGecko API |
| Macro data | FRED API (fredapi) |
| Structured outputs | Pydantic v2 |
| API framework | FastAPI |
| Observability | LangSmith + Python logging |
| Deployment | Docker + Railway |
| Package manager | uv |
src/
├── states/
│ └── financestate.py # FinanceState TypedDict + all Pydantic output models
├── nodes/
│ ├── data_fetch.py # DataFetchAgent — yfinance, CoinGecko, FRED
│ ├── macro_regime_agent.py # MacroRegimeAgent — FRED macro classification
│ ├── fundamentals_agent.py # FundamentalsAgent — P/E, EPS, revenue growth, D/E
│ ├── sentiment_agent.py # SentimentAgent — equity headlines + crypto CoinGecko signals
│ ├── risk_agent.py # RiskDataAgent — volatility (std × √252), beta, risk flags
│ ├── bull_analyst.py # BullAnalyst — upside thesis, catalysts
│ ├── bear_analyst.py # BearAnalyst — downside thesis, risks
│ ├── valuation_analyst.py # ValuationAnalyst — P/E vs sector, intrinsic value
│ ├── onchain_analyst.py # OnChainAnalyst — CoinGecko metrics for crypto
│ └── supervisor_agent.py # SupervisorAgent — final synthesis, buy/hold/sell
├── graphs/
│ └── graph_builder.py # GraphBuilder — parallel graph + conditional routing
├── llms/
│ └── llm_client.py # Tiered LLM client — nano (fast) + mini (smart)
└── exceptions.py # Custom exception hierarchy
app.py # FastAPI — /analyze + /approve/{thread_id} + lifespan checkpointer
frontend/
└── index.html # Investment research desk UI
measure_agreement.py # Analyst consensus agreement measurement
benchmark.py # Per-agent Gantt-style latency benchmark
Dockerfile
git clone https://github.com/aakarsh31/FinanceAgent-LangGraph.git
cd FinanceAgent-LangGraph
uv sync
cp .env.example .envAdd to .env:
OPENAI_API_KEY=...
LANGCHAIN_API_KEY=...
FRED_API_KEY=... # free at fred.stlouisfed.org
uvicorn app:app --reloadSupervisor pattern over shared state — each specialist agent has a distinct role and writes one output to state. The SupervisorAgent reads all outputs and makes the final call — it never touches raw data directly, mirroring how a portfolio manager reads analyst memos rather than Bloomberg terminals.
MacroRegimeAgent always runs — macro context isn't an asset class to analyze, it's the backdrop for every analysis. Fed funds rate, CPI, and yield curve shape color every bull/bear thesis downstream.
Automatic asset class detection — quoteType from yfinance determines routing. Removes user error and makes the API contract cleaner.
Tiered LLM cost optimization — GPT-4.1-nano for 7 analysis agents (fast, cheap), GPT-4.1-mini reserved for SupervisorAgent where synthesis quality matters. Keeps cost under $0.002 per full run.
HITL at the right layer — interrupt fires before SupervisorAgent, not before a report formatting step. The human reviews all analyst outputs and approves the PM's synthesis — architecturally accurate to how investment firms operate.
SqliteSaver over InMemorySaver — HITL requires persisting suspended state between two separate HTTP requests. InMemorySaver cannot survive across requests in a multi-process server.
Volatility computed deterministically — std × √252 in pandas. LLM never touches numerical calculations.