Multi-agent AI wealth management assistant that delivers persona-adapted financial insights through a real-time conversational interface with an integrated portfolio dashboard and AI-powered advisory tools.
Python FastAPI LangGraph Anthropic Claude API SQLAlchemy Pydantic React Vite Tailwind CSS Recharts WebSocket PostgreSQL yfinance Docker
- Multi-agent orchestration — LangGraph StateGraph routes queries through specialized agents (Portfolio Analyzer, Market Researcher, Client Communicator) based on LLM intent classification
- 4 client personas — Conservative Retiree, Aggressive Growth, Young Professional, Institutional — same data, different communication style and detail level
- Real-time streaming — WebSocket-based chat with live token streaming and agent status indicators showing which agent is currently working
- AI-powered tools — One-click Rebalancing, Tax-Loss Harvesting, Stress Testing, and Full Report generation with structured data cards and "Ask AI" deep-dive analysis
- Portfolio dashboard — Metric cards, allocation donut chart, performance line chart, sector exposure breakdown, and holdings table with live prices and unrealized P&L
- Dynamic follow-up suggestions — Context-aware prompts generated by the LLM after each response, displayed above the chat input
- Live market data — Real-time prices and analytics fetched from yfinance with 1-hour TTL cache
- Chat management — Clear chat history with 5-second undo/restore capability
- Resizable panels — Drag-adjustable sidebar and dashboard widths
┌─────────────────────────────────────────────────────────┐
│ React Frontend │
│ Chat UI │ AI Tools │ Dashboard │ Persona Selector│
└──────────────────────┬──────────────────────────────────┘
│ WebSocket (streaming) + REST
┌──────────────────────▼──────────────────────────────────┐
│ FastAPI Backend │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ LangGraph Orchestrator │ │
│ │ │ │
│ │ route_query (intent classification) │ │
│ │ ├─ "portfolio" → Portfolio Agent → Comms │ │
│ │ ├─ "market" → Portfolio → Market → Comms │ │
│ │ └─ "full_review"→ Portfolio → Market → Comms │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────┐ ┌─────────────┐ ┌───────────────┐ │
│ │ analytics/ │ │ Claude API │ │ yfinance │ │
│ │ (pure math) │ │ (LLM) │ │ (market data) │ │
│ └──────────────┘ └─────────────┘ └───────────────┘ │
│ │
│ PostgreSQL / SQLite │
└─────────────────────────────────────────────────────────┘
Every user query is classified by an LLM router, then routed through the appropriate agent pipeline:
User Query → Intent Classifier (Claude, max_tokens=20)
│
├── "portfolio" → Portfolio Analyzer → Comms Agent → Stream Response
├── "market" → Portfolio Analyzer → Market Researcher → Comms Agent → Stream Response
└── "full_review" → Portfolio Analyzer → Market Researcher → Comms Agent → Stream Response
- Portfolio Analyzer — Loads holdings from DB, fetches live prices, computes returns, allocation, risk metrics, rebalancing trades, and tax-loss candidates
- Market Researcher — Fetches ticker news, macro indicators (Treasury yields, S&P 500), and sector performance across 10 sector ETFs
- Client Communicator — LLM-only agent (no tools) that takes prior agent outputs + persona context and streams a persona-adapted response
- Orchestrator — Routes only. No business logic. Classifies intent and selects the agent path.
analytics/is pure math — no LLM calls, fully deterministic and testable- Agents call analytics functions as LangGraph tools
- Comms agent has no tools — LLM-only, adapts tone based on persona
- State flows one direction: Query → Orchestrator → Agent(s) → Comms → Response
| Layer | Technology | Purpose |
|---|---|---|
| Agent Orchestration | LangGraph (StateGraph) | Multi-agent pipeline with conditional routing |
| LLM | Anthropic Claude (claude-sonnet-4-20250514) | Intent classification, portfolio analysis, response generation |
| Backend Framework | FastAPI | Async REST API + WebSocket endpoints |
| ORM | SQLAlchemy 2.0 | Database models and queries |
| Validation | Pydantic v2 | Request/response schemas at all API boundaries |
| Frontend | React 18 + Vite | SPA with hot module replacement |
| Styling | Tailwind CSS | Utility-first CSS, no separate stylesheets |
| Charts | Recharts | Allocation donut, performance line, sector bars |
| Database | PostgreSQL (SQLite dev fallback) | Client data, portfolios, holdings, chat history |
| Market Data | yfinance | Live prices, news, sector performance |
| Containerization | Docker + docker-compose | Full-stack deployment |
- Python 3.11+
- Node.js 18+
- An Anthropic API key
# Clone
git clone https://github.com/vikranth1000/WealthAgent.git
cd WealthAgent
# Backend
cd backend
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
# Create .env
echo "ANTHROPIC_API_KEY=your-key-here" > .env
# Start backend (auto-seeds database on first run)
uvicorn main:app --reload --port 8000
# Frontend (new terminal)
cd frontend
npm install
npm run devOpen http://localhost:5173 — the frontend proxies API and WebSocket requests to port 8000.
docker-compose up --buildThis starts three services: backend (port 8000), frontend (port 5173), and PostgreSQL (port 5432).
cd backend
PYTHONPATH=. pytest tests/ -v64 tests covering all analytics modules, agents, and API endpoints.
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/health |
Health check |
GET |
/api/clients |
List all clients |
GET |
/api/clients/{id} |
Single client details |
GET |
/api/clients/{id}/portfolio |
Portfolio with holdings |
GET |
/api/clients/{id}/analysis |
Full analytics (value, returns, allocation, risk metrics) |
GET |
/api/clients/{id}/rebalancing |
Rebalancing trades, drift, current vs target allocation |
GET |
/api/clients/{id}/tax-loss |
Tax-loss harvesting candidates + estimated savings |
GET |
/api/clients/{id}/performance-history |
Weekly portfolio value timeseries |
GET |
/api/clients/{id}/holdings-detail |
Holdings with live prices, market value, unrealized P&L |
GET |
/api/clients/{id}/chat-history |
Persisted chat messages |
DELETE |
/api/clients/{id}/chat-history |
Clear chat history |
POST |
/api/chat |
Non-streaming chat fallback |
| Endpoint | Protocol |
|---|---|
ws://host/ws/chat/{client_id} |
Send: { message, persona } — Receive: agent_start → chunk (streamed tokens) → done (with report + suggestions) |
Four one-click advisory tools accessible from the toolbar above the chat:
| Tool | Data Source | Description |
|---|---|---|
| Rebalance | /api/clients/{id}/rebalancing |
Shows current vs target allocation with drift percentages and a generated trades table (BUY/SELL with share counts and dollar amounts) |
| Tax Harvest | /api/clients/{id}/tax-loss |
Identifies holdings with unrealized losses below threshold, shows total harvestable loss and estimated tax savings at 37% rate |
| Stress Test | Frontend-computed | Applies historical scenario multipliers (2008 Crisis, Rate Shock, Stagflation, Tech Crash) to current allocation — shows portfolio impact in % and $ |
| Full Report | Chat (WebSocket) | Triggers a comprehensive portfolio review through the full agent pipeline |
Each tool card includes a "Get AI Analysis" button that sends a contextual prompt to the chat for deeper LLM-powered insights.
| Persona | Style | Detail Level |
|---|---|---|
| Conservative Retiree | Warm, reassuring, plain language | Low jargon, focuses on income stability and capital preservation |
| Aggressive Growth | Direct, data-heavy, action-oriented | High jargon, emphasizes alpha, momentum, and growth opportunities |
| Young Professional | Friendly, educational, encouraging | Medium jargon, explains concepts, focuses on long-term wealth building |
| Institutional | Formal, precise, compliance-aware | Maximum data density, risk-adjusted metrics, regulatory considerations |
All personas receive identical analytical data — only the communication style changes.
WealthAgent/
├── backend/
│ ├── main.py # FastAPI entry, lifespan handler, CORS
│ ├── config.py # Settings from env vars
│ ├── agents/
│ │ ├── orchestrator.py # LangGraph StateGraph + intent classifier
│ │ ├── portfolio_agent.py # Portfolio analysis (calls analytics/)
│ │ ├── market_agent.py # Market research (yfinance + news)
│ │ ├── comms_agent.py # Persona-adapted LLM streaming + suggestions
│ │ └── state.py # WealthAgentState TypedDict
│ ├── analytics/ # Pure math — no LLM calls
│ │ ├── portfolio.py # Total value, returns, allocation, sectors
│ │ ├── metrics.py # Sharpe, Sortino, max drawdown, volatility
│ │ ├── rebalancing.py # Drift calculation + trade generation
│ │ └── tax_loss.py # Harvesting candidates
│ ├── data/
│ │ ├── models.py # SQLAlchemy ORM (Client, Portfolio, Holding, ChatMessage)
│ │ ├── database.py # Async engine + session factory
│ │ └── seed.py # 4 demo clients with realistic holdings
│ ├── api/
│ │ ├── routes.py # REST endpoints
│ │ ├── websocket.py # WebSocket streaming endpoint
│ │ └── schemas.py # Pydantic v2 request/response models
│ ├── personas/
│ │ ├── definitions.py # PersonaConfig dataclasses
│ │ └── templates.py # System prompts + prompt templates
│ └── tests/ # 64 tests (pytest + pytest-asyncio)
├── frontend/src/
│ ├── App.jsx # Root layout with resizable panels
│ ├── components/
│ │ ├── Chat/
│ │ │ ├── ChatWindow.jsx # Main chat container + clear/undo
│ │ │ ├── MessageBubble.jsx # Markdown rendering + error styling
│ │ │ ├── ChatInput.jsx # Input bar with stop button
│ │ │ ├── SuggestedPrompts.jsx# Static + dynamic follow-up prompts
│ │ │ └── AgentIndicator.jsx # Live agent status with step progress
│ │ ├── Dashboard/
│ │ │ ├── MetricCards.jsx # Key portfolio metrics
│ │ │ ├── AllocationChart.jsx # Donut chart with legend
│ │ │ ├── PerformanceChart.jsx# Line chart with formatted Y-axis
│ │ │ ├── SectorChart.jsx # Sector exposure bars
│ │ │ └── HoldingsTable.jsx # Holdings with price, value, P&L
│ │ ├── Actions/
│ │ │ ├── ActionToolbar.jsx # 4 AI tool buttons
│ │ │ ├── ActionPanel.jsx # Overlay container + data fetching
│ │ │ ├── RebalancingCard.jsx # Allocation bars + trades table
│ │ │ ├── TaxLossCard.jsx # Candidates + savings callout
│ │ │ └── StressTestCard.jsx # Scenario impact bars
│ │ └── Layout/
│ │ ├── Sidebar.jsx # Client list with live portfolio values
│ │ ├── Header.jsx # Top bar with persona info
│ │ └── RightPanel.jsx # Dashboard container
│ ├── hooks/
│ │ ├── useWebSocket.js # WebSocket management + chat state
│ │ ├── usePortfolio.js # Portfolio data fetching
│ │ └── useClients.js # Client list with enriched data
│ └── services/
│ └── api.js # REST API client
├── docker-compose.yml # 3-service stack (backend, frontend, db)
├── PRD.md # Full product requirements document
└── CLAUDE.md # AI assistant instructions
| Variable | Required | Description |
|---|---|---|
ANTHROPIC_API_KEY |
Yes | Anthropic API key for Claude |
DATABASE_URL |
No | PostgreSQL connection URL (defaults to SQLite ./wealthagent.db) |
NEWS_API_KEY |
No | News API key for enhanced market research |
LOG_LEVEL |
No | Logging level (default: INFO) |
The database is seeded with 4 demo clients on first startup:
| Client | Persona | Holdings | Profile |
|---|---|---|---|
| Margaret Chen | Conservative Retiree | 8 (VTI, BND, VZ, JNJ, PG, O, SCHD, VTIP) | Income-focused, capital preservation |
| Alex Rodriguez | Aggressive Growth | 9 (QQQ, ARKK, TSLA, NVDA, AMD, SOXX, MSTR, COIN, SQ) | High-growth tech and crypto exposure |
| Priya Sharma | Young Professional | 5 (VOO, VTI, VXUS, BND, VNQ) | Balanced index fund approach |
| Meridian Capital | Institutional | 9 (SPY, AGG, EFA, VWO, GLD, VNQ, TLT, LQD, TIPS) | Diversified multi-asset institutional |
This project is for educational and portfolio demonstration purposes.