Building a Stock Prediction AI Agent with LangGraph: A Step-by-Step Guide#
Want to build an AI agent that can search for stock data and make predictions? LangGraph makes it surprisingly straightforward to create sophisticated AI agents with custom tools and graph-based workflows.
In this tutorial, I'll walk you through building a stock prediction agent that:
- 🔍 Searches for real stock data using Yahoo Finance
- 📊 Analyzes historical trends
- 🤖 Makes price predictions using LLM reasoning
- 🔁 Chains multiple tools together intelligently
By the end, you'll have a working agent and understand how to build your own custom AI agents for any domain.
What is LangGraph?#
LangGraph is a framework from LangChain for building stateful, multi-actor applications with LLMs. Think of it as a way to create AI agents that can:
- Use multiple tools sequentially or in parallel
- Maintain state across interactions
- Make decisions about which tools to use
- Chain complex reasoning workflows
Why LangGraph over simple LLM calls?#
| Traditional LLM Call | LangGraph Agent |
|---|---|
| Single input → output | Multi-step reasoning |
| No tool use | Multiple tool integrations |
| Stateless | Stateful conversations |
| Linear flow | Graph-based workflows |
| Limited to text | Actions in real world |
Perfect for: Financial analysis, research assistants, customer service bots, data analysis pipelines, and more.
What We're Building#
The Stock Prediction Agent Architecture#
User Input: "Predict AAPL stock price"
↓
[LangGraph Agent]
↓
Tool Selection
↓
┌───────────┬──────────────┐
↓ ↓ ↓
[Search Tool] [Predict Tool] [Analysis]
↓ ↓ ↓
Yahoo Finance ML Model GPT Reasoning
↓
Final Prediction
Key Components#
- Agent Core (
agent.py) - LangGraph workflow orchestration - Tools (
tools.py) - Stock search & prediction functions - Model (
model.py) - Prediction logic (easily extendable to ML models) - LLM - GPT-4o for reasoning and tool selection
Prerequisites#
What you need:
- Python 3.10+
- OpenAI API key
- Basic understanding of Python and APIs
- 10 minutes to follow along
No prior LangGraph experience required! This tutorial assumes you're starting from scratch.
Step 1: Project Setup#
Install Dependencies#
I use uv for fast dependency management, but pip works too:
# Using uv (recommended - much faster!) uv venv --python 3.10 uv sync # Or using traditional pip python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate pip install langgraph langchain openai yfinance python-dotenv
Project Structure#
stock-agent/
├── agent.py # LangGraph agent definition
├── tools.py # Custom tools (search, predict)
├── model.py # Prediction logic
├── .env # API keys
└── pyproject.toml # Dependencies
Configure Environment#
Create .env:
OPENAI_API_KEY=your_openai_api_key_here
Security tip: Never commit .env to git! Add it to .gitignore.
Step 2: Building Custom Tools#
Tools are functions your agent can call. Let's create two tools:
Tool 1: Stock Data Search#
File: tools.py
import yfinance as yf from langchain.tools import tool @tool def search_stock_data(symbol: str) -> dict: """ Fetch historical stock data for a given symbol. Args: symbol: Stock ticker symbol (e.g., 'AAPL', 'TSLA') Returns: Dictionary with historical prices and metadata """ try: stock = yf.Ticker(symbol) # Get last 5 days of data hist = stock.history(period="5d") if hist.empty: return {"error": f"No data found for symbol {symbol}"} return { "symbol": symbol, "current_price": round(hist['Close'].iloc[-1], 2), "5d_high": round(hist['High'].max(), 2), "5d_low": round(hist['Low'].min(), 2), "5d_avg": round(hist['Close'].mean(), 2), "5d_prices": hist['Close'].tolist() } except Exception as e: return {"error": str(e)}
What's happening here:
@tooldecorator makes this function callable by the agent- Uses
yfinanceto fetch real stock data from Yahoo Finance - Returns structured data the LLM can reason about
- Includes error handling for invalid symbols
Tool 2: Price Prediction#
from model import predict_next_price @tool def predict_stock_price(symbol: str, historical_data: list) -> dict: """ Predict next day's stock price using historical data. Args: symbol: Stock ticker symbol historical_data: List of recent closing prices Returns: Dictionary with prediction and confidence """ try: if not historical_data or len(historical_data) < 2: return {"error": "Insufficient data for prediction"} predicted_price = predict_next_price(historical_data) return { "symbol": symbol, "predicted_price": round(predicted_price, 2), "method": "5-day moving average", "confidence": "medium" # Can be enhanced with real ML model } except Exception as e: return {"error": str(e)}
Step 3: Simple Prediction Model#
For now, we'll use a simple moving average. You can replace this with LSTM, XGBoost, or any ML model!
File: model.py
def predict_next_price(prices: list[float]) -> float: """ Predict next price using simple moving average. In production, replace with: - LSTM neural network - XGBoost model - Prophet for time series - Fine-tuned transformer """ if not prices: return 0.0 # Simple 5-day moving average return sum(prices[-5:]) / min(len(prices), 5)
💡 Pro Tip: This is intentionally simple to keep the tutorial focused on LangGraph. For real trading, use proper ML models with backtesting!
Step 4: Building the LangGraph Agent#
Here's where the magic happens! LangGraph orchestrates the tools and LLM.
File: agent.py
from langgraph.prebuilt import create_react_agent from langchain_openai import ChatOpenAI from tools import search_stock_data, predict_stock_price import os from dotenv import load_dotenv load_dotenv() # Initialize LLM llm = ChatOpenAI( model="gpt-4o", temperature=0.1, # Low temperature for consistent predictions api_key=os.getenv("OPENAI_API_KEY") ) # Create agent with tools agent = create_react_agent( llm, tools=[search_stock_data, predict_stock_price], state_modifier="""You are a financial analysis agent. When asked to predict a stock price: 1. First use search_stock_data to get historical data 2. Then use predict_stock_price with that data 3. Provide a clear summary with the prediction and reasoning Always cite the data you used and explain your prediction.""" ) def run_agent(stock_symbol: str) -> dict: """ Run the agent to predict stock price. Args: stock_symbol: Stock ticker (e.g., 'AAPL') Returns: Agent's response with prediction """ query = f"Predict the next day's closing price for {stock_symbol}" result = agent.invoke({ "messages": [("user", query)] }) return result if __name__ == "__main__": # Example usage result = run_agent("AAPL") print("\n=== Agent Response ===") print(result["messages"][-1].content)
Understanding the Code#
create_react_agent:
- "ReAct" = Reasoning + Acting pattern
- Agent reasons about what to do, then acts (uses tools)
- Repeats until it has an answer
state_modifier:
- System prompt that guides agent behavior
- Tells agent which tools to use and when
- Defines output format
invoke:
- Sends user message to agent
- Agent decides which tools to call
- Returns final response
Step 5: Running Your Agent#
Basic Usage#
python agent.py
Example Output:
=== Agent Response ===
Based on my analysis of AAPL stock data:
Current Price: $172.35
5-Day Average: $171.80
5-Day Range: $169.50 - $174.20
Predicted Next-Day Price: $172.15
Reasoning: Using a 5-day moving average model, the predicted price is
slightly below current levels due to recent volatility. The stock has
been trading in a narrow range, suggesting consolidation.
Confidence: Medium
Method: 5-day moving average
Note: This is a simple prediction model. For trading decisions, consult
professional financial advice and use more sophisticated models.
Interactive Usage#
Create interactive.py:
from agent import run_agent def main(): print("🤖 Stock Prediction Agent") print("=" * 50) while True: symbol = input("\nEnter stock symbol (or 'quit'): ").strip().upper() if symbol == 'QUIT': break if not symbol: print("Please enter a valid symbol") continue print(f"\n🔍 Analyzing {symbol}...") result = run_agent(symbol) print("\n" + "="*50) print(result["messages"][-1].content) print("="*50) if __name__ == "__main__": main()
Run it:
python interactive.py
Understanding How the Agent Works#
The ReAct Pattern#
- Thought: "I need stock data to make a prediction"
- Action: Call
search_stock_data("AAPL") - Observation: Receives historical data
- Thought: "Now I can predict using this data"
- Action: Call
predict_stock_price("AAPL", prices) - Observation: Gets prediction result
- Thought: "I have everything I need"
- Answer: Provides final response to user
Tool Selection Logic#
The LLM automatically decides:
- Which tools to use (search vs predict)
- When to use them (sequence matters!)
- What arguments to pass (extracts from context)
- When to stop (after getting complete answer)
This is much more powerful than hardcoded workflows!
Extending the Agent#
Add More Tools#
@tool def get_company_news(symbol: str) -> dict: """Fetch latest news for a company.""" # Use News API or similar pass @tool def calculate_technical_indicators(prices: list) -> dict: """Calculate RSI, MACD, moving averages.""" import pandas as pd import talib # Technical analysis logic pass @tool def get_fundamental_data(symbol: str) -> dict: """Fetch P/E ratio, market cap, etc.""" stock = yf.Ticker(symbol) return stock.info
Add to agent:
agent = create_react_agent( llm, tools=[ search_stock_data, predict_stock_price, get_company_news, # New! calculate_technical_indicators, # New! get_fundamental_data # New! ] )
The agent will automatically use these tools when relevant!
Upgrade the Prediction Model#
Replace model.py with real ML:
import torch from transformers import TimeSeriesTransformerForPrediction def predict_next_price(prices: list[float]) -> float: """Use a proper ML model for prediction.""" model = load_pretrained_model() # Your trained model prediction = model.predict(prices) return prediction
Add LangSmith Tracing#
Monitor agent behavior in production:
import os os.environ["LANGSMITH_API_KEY"] = "your_key" os.environ["LANGSMITH_PROJECT"] = "stock-agent" os.environ["LANGSMITH_TRACING"] = "true" # Agent calls are now automatically logged to LangSmith!
Real-World Considerations#
⚠️ Important Disclaimers#
- Not Financial Advice: This is an educational project
- Simple Model: The moving average prediction is too basic for real trading
- No Backtesting: Real trading systems need rigorous testing
- Market Hours: Add checks for when markets are open
- Rate Limits: Yahoo Finance has usage limits
Production Enhancements#
For a real trading agent, add:
1. Error Handling
from tenacity import retry, stop_after_attempt, wait_exponential @retry(stop=stop_after_attempt(3), wait=wait_exponential()) @tool def search_stock_data(symbol: str) -> dict: # Retries on failure with exponential backoff pass
2. Caching
from functools import lru_cache @lru_cache(maxsize=100) def fetch_stock_data(symbol: str, date: str): # Cache expensive API calls pass
3. Validation
def validate_symbol(symbol: str) -> bool: """Check if symbol exists before querying.""" valid_symbols = load_symbol_list() # NYSE, NASDAQ lists return symbol.upper() in valid_symbols
4. Async Tools
from langchain.tools import AsyncTool @tool async def search_stock_data_async(symbol: str) -> dict: """Async version for better performance.""" async with aiohttp.ClientSession() as session: # Fetch data asynchronously pass
Common Use Cases Beyond Stock Prediction#
The same LangGraph pattern works for:
1. Research Assistant#
tools = [ web_search, arxiv_search, summarize_paper, extract_citations ]
2. Customer Support Bot#
tools = [ search_knowledge_base, check_order_status, create_ticket, escalate_to_human ]
3. Data Analysis Agent#
tools = [ load_dataset, run_sql_query, create_visualization, statistical_analysis ]
4. Code Review Agent#
tools = [ analyze_code_quality, check_security_issues, run_tests, suggest_improvements ]
Debugging Tips#
View Agent's Reasoning#
Add verbose logging:
import logging logging.basicConfig(level=logging.DEBUG) # Now you'll see all agent thoughts and tool calls result = run_agent("TSLA")
Check Tool Calls#
result = agent.invoke({"messages": [("user", query)]}) # Inspect all messages for msg in result["messages"]: print(f"{msg.type}: {msg.content}")
Test Tools Individually#
# Test tool without agent from tools import search_stock_data data = search_stock_data("AAPL") print(data) # Should return stock data dict
Performance Optimization#
Parallel Tool Execution#
LangGraph can run independent tools in parallel:
# Agent automatically parallelizes when possible # No code changes needed!
Reduce LLM Calls#
Use caching for repeated queries:
from langchain.cache import InMemoryCache from langchain.globals import set_llm_cache set_llm_cache(InMemoryCache())
Smaller Model for Tool Selection#
# Use cheaper model for tool routing router_llm = ChatOpenAI(model="gpt-3.5-turbo") # Use powerful model only for final answer answer_llm = ChatOpenAI(model="gpt-4o")
Next Steps#
Beginner Projects#
- Add more stocks: Handle portfolio predictions
- Historical analysis: Compare predicted vs actual prices
- Alert system: Notify when prediction confidence is high
Advanced Projects#
- Replace with LSTM: Train deep learning model for better predictions
- Multi-agent system: Separate agents for research, analysis, trading
- Backtesting framework: Test strategies on historical data
- Real-time dashboard: Visualize predictions with Streamlit
Conclusion#
You've built a working AI agent with LangGraph! Here's what you learned:
✅ Create custom tools for any functionality ✅ Build LangGraph agents that reason and act ✅ Chain multiple tools intelligently ✅ Integrate external APIs (Yahoo Finance) ✅ Structure production-ready agent code
The power of LangGraph: Once you understand this pattern, you can build agents for any domain just by swapping out the tools!
Resources#
- Source Code: GitHub - Stock Prediction Agent
- LangGraph Docs: Official Documentation
- Try it yourself: Clone and experiment!
git clone https://github.com/MinhQuanBuiSco/AI_CheatSheet.git cd AI_CheatSheet/AI_agent_langGraph # Follow setup instructions in README
Questions? The code is open source - issues and PRs welcome!
Happy building! 🚀📈