shubZk17/equity-research-agent
<p align="center"> <img src="docs/banner.png" alt="ARA-1 Banner" width="100%"/> </p>
<h1 align="center">ARA-1 โ Autonomous Research Agent</h1>
<p align="center"> <b>A retrieval-aware autonomous financial intelligence system built with LangGraph and the ReAct framework.</b> </p>
<p align="center"> <img src="https://img.shields.io/badge/Python-3.12+-3776AB?style=for-the-badge&logo=python&logoColor=white" alt="Python"/> <img src="https://img.shields.io/badge/LangGraph-ReAct-FF6F00?style=for-the-badge&logo=langchain&logoColor=white" alt="LangGraph"/> <img src="https://img.shields.io/badge/ChromaDB-Vector%20Store-4A154B?style=for-the-badge" alt="ChromaDB"/> <img src="https://img.shields.io/badge/LLM-Groq%20%7C%20OpenAI%20%7C%20Claude-10A37F?style=for-the-badge" alt="LLM"/> </p>
๐ What is ARA-1?
ARA-1 is an autonomous AI agent that performs end-to-end financial research on publicly traded companies. Give it a ticker symbol or a research question, and it will:
- ๐ Dynamically select tools to gather real-time stock data, financial metrics, company profiles, and news
- ๐ง Reason step-by-step using the ReAct (Reasoning + Acting) framework
- ๐ Store & retrieve knowledge from a persistent vector memory (ChromaDB)
- ๐ Score source reliability using a 3-tier evidence governance system
- โก Detect conflicting information and surface it transparently
- ๐๏ธ Learn from past analyses through episodic memory
ARA-1 is not a chatbot wrapper. It is a fully autonomous agent that decides what to do, when to do it, and when to stop โ all without human intervention.
๐๏ธ Architecture
ARA-1 is built on a layered modular architecture with clean separation of concerns:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ main.py ยท app.py ยท api/ โ โ Entry points
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ LangGraph StateGraph (agent/) โ โ The ReAct loop
โ reasoning_node โ tool_node โ output_node โ
โ + state ยท prompts ยท react_parser โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Tool Layer โ knowledge/ โ
โ (tools/) โ โ
โ โ ingestion/ cleanยทchunk โ
โ โข stock_price โ retrieval/ storeยทsearch โ
โ โข company_info โ memory/ episodic โ
โ โข financial_metrics โ reliability/ tiersยทstalenessโ
โ โข news โ ยทconflicts โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ analysis/ โ โ Evidence โ thesis
โ financial โ sentiment โ misalignment โ risk โ โ
โ confidence โ report โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ quality/ โ โ Observes only,
โ evaluation/ ยท observability/ ยท dashboard โ never blocks a run
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ config/ ยท utils/logger โ โ Support
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Data flows top to bottom. The graph only covers the ReAct loop โ
analysis/ runs after it completes, on the finished state.โ๏ธ How It Works โ End-to-End Workflow
flowchart TD
A["๐ง User Query"] --> B["Load Episodic Memory<br/>(prior run context)"]
B --> C["Build Initial State"]
C --> D["LangGraph: reasoning_node"]
D --> E{"LLM Decision"}
E -->|Use a Tool| F["tool_node<br/>Execute Tool"]
F --> G["Auto-Ingest Output<br/>โ Clean โ Chunk โ Embed โ Store"]
G --> D
E -->|Final Answer| H["output_node"]
D --> I["Retrieve Evidence<br/>from Vector Memory"]
I --> J["Score Reliability<br/>+ Detect Conflicts"]
J --> D
H --> K["Save Episode<br/>to Episodic Memory"]
K --> L["Save Final Analysis<br/>to Vector Memory"]
L --> M["๐ฅ๏ธ Display Results"]
style A fill:#1a1a2e,color:#e94560
style D fill:#0f3460,color:#16213e,color:#fff
style G fill:#533483,color:#fff
style H fill:#0f3460,color:#fff
style M fill:#1a1a2e,color:#e94560Step-by-Step Breakdown
๐ Local Setup & Usage
Prerequisites
- Python 3.12+
- Git
- At least one LLM API key: Groq (free), OpenAI, or Anthropic
1. Clone the Repository
git clone https://github.com/your-username/ara-agent.git
cd ara-agent2. Create a Virtual Environment
# Windows
python -m venv .venv
.venv\Scripts\activate
# macOS / Linux
python3 -m venv .venv
source .venv/bin/activate3. Install Dependencies
pip install -r requirements.txt4. Configure Environment Variables
Copy the example config and add your API keys:
cp .env.example .envEdit .env with your preferred editor:
# ============================================================
# ARA-1 Environment Configuration
# ============================================================
# --- LLM Provider (pick one) ---
# Option A: Groq (FREE โ recommended for getting started)
GROQ_API_KEY=your-groq-api-key-here
LLM_PROVIDER=groq
GROQ_MODEL=llama-3.3-70b-versatile
# Option B: OpenAI
# OPENAI_API_KEY=your-openai-api-key-here
# LLM_PROVIDER=openai
# OPENAI_MODEL=gpt-4o
# Option C: Anthropic
# ANTHROPIC_API_KEY=your-anthropic-api-key-here
# LLM_PROVIDER=claude
# ANTHROPIC_MODEL=claude-sonnet-4-20250514
# --- Agent Settings ---
MAX_ITERATIONS=10
LOG_LEVEL=INFO
# --- Phase 2: Embeddings (optional, enhances retrieval quality) ---
# OPENAI_API_KEY=your-openai-api-key-here๐ก Tip: Get a free Groq API key at console.groq.com. No credit card required.
5. Run the Agent
Interactive mode (prompts for a query):
python main.pyWith a query argument:
python main.py "Analyze Tesla stock as a long-term investment"More example queries:
python main.py "What are the financial risks of investing in AAPL?"
python main.py "Compare NVDA and AMD financial performance"
python main.py "Provide a comprehensive analysis of Microsoft (MSFT)"๐ Project Structure
ARA-1/
โ
โโโ main.py # ๐ CLI entry point & system assembly
โโโ app.py # ๐ฅ๏ธ Streamlit UI (the Hugging Face Space)
โ
โโโ agent/ # ๐ง The reasoning loop
โ โโโ state.py # AgentState โ the single source of truth
โ โโโ graph.py # LangGraph wiring: 3 nodes, 1 loop
โ โโโ nodes.py # reasoning โ tool โ output
โ โโโ prompts.py # System prompt template + builders
โ โโโ react_parser.py # LLM text โ structured action (5 fallbacks)
โ โโโ retry_handler.py # โ ๏ธ built, not wired
โ โโโ checkpoint_manager.py # โ ๏ธ built, not wired
โ
โโโ tools/ # ๐ง Where all external data enters
โ โโโ base.py # BaseTool โ subclass this to add one
โ โโโ registry.py # Register in main.py, that's the whole step
โ โโโ stock_price.py # Price, day range, 52w range, volume
โ โโโ company_info.py # Sector, industry, HQ, headcount
โ โโโ financial_metrics.py # P/E, margins, ROE, growth, leverage
โ โโโ news.py # Recent headlines
โ
โโโ knowledge/ # ๐ What the agent knows and how it recalls it
โ โโโ ingestion/ # Text in: clean โ chunk โ embed โ store
โ โโโ retrieval/ # Text out: vector store + semantic search
โ โโโ memory/ # What survives across runs (episodic.py)
โ โโโ reliability/ # Source tiers, staleness, conflict detection
โ
โโโ analysis/ # ๐ Turning evidence into a thesis
โ โโโ engine.py # Orchestrates the 6 stages below
โ โโโ financial_engine.py # 1. Score ~22 metrics against thresholds
โ โโโ sentiment_analyzer.py # 2. Lexicon-based news sentiment
โ โโโ misalignment_detector.py # 3. Does the story match the numbers?
โ โโโ risk_analyzer.py # 4. Valuation, leverage, volatility risks
โ โโโ confidence_calibrator.py # 5. How much should we trust this?
โ โโโ report_generator.py # 6. Render Markdown + PDF
โ โโโ schemas.py # Pydantic models tying it together
โ
โโโ quality/ # ๐ฌ Did it do a good job? Can we see how?
โ โโโ evaluation/ # 22 metrics + hallucination detection
โ โโโ observability/ # โ ๏ธ built, zero instrumentation call sites
โ โโโ dashboard.py # Read-only Streamlit monitor
โ
โโโ api/server.py # ๐ FastAPI wrapper (POST /analyze)
โโโ config/settings.py # โ๏ธ Frozen settings singleton, reads .env
โโโ utils/logger.py # ๐ Rich console + per-session file logging
โ
โโโ data/ # ๐พ Runtime state (gitignored)
โ โโโ chroma/ # Vector database
โ โโโ episodic/ # One JSON per past run
โ โโโ evaluations/ # Evaluation output
โโโ reports/ # ๐ Generated analysis reports
โโโ logs/ # ๐ Per-session logs
โ
โโโ CLAUDE.md # ๐งญ Architecture notes + known defects
โโโ plan.md # ๐บ๏ธ Roadmap (Phases 5โ8)
โโโ requirements.txt
โโโ .env.exampleWhere to start reading
Follow the data, in this order:
- `main.py` โ the assembly point. Everything is wired here and nowhere else.
- `agent/state.py` โ
AgentStateis what flows between every node. Read this before any node. - `agent/graph.py` โ 3 nodes and one loop. Small file, whole control flow.
- `agent/nodes.py` โ where reasoning and tool execution actually happen.
- `tools/stock_price.py` โ the simplest tool; the shape all others follow.
- `analysis/engine.py` โ the 6-stage synthesis pipeline.
One thing that surprises everyone: synthesis is not part of the graph. The graph is only the ReAct loop.main.pyruns it to completion, then hands the finished state toanalysis/engine.pyas a separate step.
๐งช Example Output
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ARA-1 - Autonomous Research Agent โ
โ Phase 2: Retrieval-Aware Financial Intelligence โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
[OK] Configuration valid
[OK] LLM Provider: groq (llama-3.3-70b-versatile)
[OK] Phase 2 systems initialized:
Vector Store: chroma (4 existing docs)
Embeddings: text-embedding-3-small
Episodic Memory: 1 prior episodes
Starting analysis...
Query: Analyze NVDA stock performance
Max iterations: 10
=== Iteration 1/10 ===
Thought: I need to gather NVDA's current stock price...
>> Action: get_stock_price({'ticker': 'NVDA'})
Ingested 1 chunk (total in store: 5)
=== Iteration 2/10 ===
Retrieved 5 evidence items in 6.3ms
Thought: Now I need financial metrics...
>> Action: get_financial_metrics({'ticker': 'NVDA'})
Ingested 1 chunk (total in store: 6)
...
โโโโโโโโโโโโโโโโโโโโโ [OK] Analysis Complete โโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ NVIDIA Corporation (NVDA) is a technology company operating โ
โ in the semiconductors industry. Current price: USD 224.65, โ
โ trailing P/E: 45.83, revenue growth: 73.20%, market cap: โ
โ $5.46T. Strong financial position with 55.60% profit margin. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Tool Usage Summary:
โโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโ
โ # โ Tool โ Input โ Status โ
โโโโโผโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโค
โ 1 โ get_stock_price โ {'ticker': 'NVDA'} โ OK โ
โ 2 โ get_financial_metrics โ {'ticker': 'NVDA'} โ OK โ
โ 3 โ get_company_info โ {'ticker': 'NVDA'} โ OK โ
โโโโโดโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโ
Memory Operations:
๐ฆ ingested:get_stock_price:NVDA:1chunks
๐ฆ ingested:get_financial_metrics:NVDA:1chunks
๐ฆ ingested:get_company_info:NVDA:1chunks๐ Adding Custom Tools
ARA-1's tool system is fully extensible. To add a new tool:
1. Create a new file in tools/:
# tools/my_custom_tool.py
from tools.base import BaseTool, ToolResult
class MyCustomTool(BaseTool):
@property
def name(self) -> str:
return "my_custom_tool"
@property
def description(self) -> str:
return "Description of what this tool does"
@property
def parameters(self) -> dict:
return {
"param1": {"type": "string", "description": "What this param is", "required": True}
}
def execute(self, **kwargs) -> ToolResult:
param1 = kwargs.get("param1", "")
# Your logic here
result = f"Result for {param1}"
return ToolResult(success=True, data=result)2. Register it in main.py:
from tools.my_custom_tool import MyCustomTool
def create_tool_registry() -> ToolRegistry:
registry = ToolRegistry()
# ... existing tools ...
registry.register(MyCustomTool()) # โ Add this line
return registryThat's it. The agent will automatically discover and use your tool when relevant.
๐ Supported LLM Providers
Recommendation: Start with Groq โ it's free, fast, and the llama-3.3-70b-versatile model works excellently with ARA-1's ReAct prompts.๐ก๏ธ Source Reliability Tiers
ARA-1 doesn't treat all information equally. Every piece of evidence is scored:
Scores also decay over time โ a stock price from last week is less reliable than one from today.
๐ Phase Progression
๐งฐ Tech Stack
๐ค Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/new-tool) - Commit your changes (
git commit -m 'Add SEC filing tool') - Push to the branch (
git push origin feature/new-tool) - Open a Pull Request
๐ License
This project is for educational and research purposes.
<p align="center"> <b>Built with โค๏ธ by Shubham</b><br/> <i>ARA Agent-- Any feedback is appreciated.</i> </p>
