A production-ready multi-agent system that researches technical topics and generates structured analysis reports using LangGraph and Claude/Gemini.
- π Intelligent Research: Searches multiple sources (web, documentation, papers)
- π§ Critical Analysis: Synthesizes findings, identifies gaps, validates completeness
- π Professional Reports: Generates executive summaries with citations (Markdown + PDF)
- π Feedback Loops: Iteratively improves research based on analysis
- π Full Observability: Session-based logging for debugging
- Python 3.11+ (required for TypedDict features)
- API Keys:
- Tavily API (free tier: Get key)
- AWS Bedrock access (for Claude) OR Google AI Studio (for Gemini)
- Clone the repository
git clone <repository_url>
cd multi-agent-research- Install dependencies
python -m venv venv
# Windows
.\venv\Scripts\activate
# Linux/Mac
source venv/bin/activate
pip install -r requirements.txt- Configure environment
Create a .env file in the project root:
# LLM Configuration
RESEARCH_MODEL=anthropic.claude-3-5-sonnet-20240620-v1:0
ANALYSIS_MODEL=anthropic.claude-3-5-sonnet-20240620-v1:0
REPORT_MODEL=anthropic.claude-3-5-sonnet-20240620-v1:0
# API Keys
TAVILY_API_KEY=tvly-xxxxx
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=...
AWS_DEFAULT_REGION=us-east-1
# Workflow Settings (optional)
MAX_ITERATIONS=5
CONFIDENCE_THRESHOLD=0.8
MAX_SOURCES=10Alternative: Use Gemini instead of Claude
RESEARCH_MODEL=gemini-2.0-flash
GOOGLE_API_KEY=AIza...python main.py --topic "LangChain vs LlamaIndex"Control exactly how deep the research goes (default is 5 loops):
python main.py --topic "Kubernetes autoscaling" --max-iterations 3python main.py \
--topic "Quantum Computing" \
--max-iterations 2 \
--verbose--topic TEXT Research topic (required)
--max-iterations INTEGER Max research-analysis loops (default: 5)
--verbose Enable detailed logging outputs
Command:
python main.py --topic "LangChain vs LlamaIndex"Console Output:
2026-01-25T14:32:10Z [info ] Session started topic='LangChain vs LlamaIndex'
2026-01-25T14:32:12Z [info ] Research Agent: Searching web... query='LangChain vs LlamaIndex'
2026-01-25T14:32:15Z [info ] Validated sources count=7 avg_credibility=0.82
2026-01-25T14:32:18Z [info ] Analysis Agent: Analyzing... confidence=0.65
2026-01-25T14:32:18Z [warn ] Gaps identified gaps=['LlamaIndex architecture details']
2026-01-25T14:32:22Z [info ] Research Agent: Digging deeper... query='LlamaIndex architecture'
2026-01-25T14:32:25Z [info ] Analysis Agent: Confidence 0.91 β
2026-01-25T14:32:28Z [info ] Report Agent: Generating report...
2026-01-25T14:32:31Z [info ] Report saved path='outputs/report_LangChain vs LlamaIndex_20260125.pdf'
Real-time observability logs:
The system records detailed event traces in the logs/ directory. Each run creates a timestamped session folder containing JSON snapshots of every agent action, tool call, and state update.
Generated Reports:
- π PDF: report_LangChain vs LlamaIndex.pdf
- π Markdown: report_LangChain vs LlamaIndex.md
multi-agent-research/
βββ main.py # Entry point
βββ config/
β βββ settings.py # Configuration management
βββ src/
β βββ agents/
β β βββ research.py # Research Agent (search, fetch, validate)
β β βββ analysis.py # Analysis Agent (synthesis, gap detection)
β β βββ report.py # Report Agent (formatting, PDF generation)
β βββ tools/
β β βββ search.py # Tavily web search integration
β β βββ fetch.py # Document fetching (httpx + BeautifulSoup)
β β βββ validate.py # Source validation (heuristics + LLM)
β βββ graph/
β β βββ workflow.py # LangGraph orchestration
β β βββ state.py # TypedDict state definition
β βββ utils/
β βββ llm_factory.py # LLM provider abstraction
β βββ logger.py # Structured logging (structlog)
β βββ pdf_export.py # PDF generation (fpdf2)
βββ logs/ # Session logs (auto-generated)
βββ outputs/ # Generated reports
βββ requirements.txt
βββ .env.example # Template for .env
βββ README.md
Real-time Logs Location: logs/session_YYYYMMDD_HHMMSS/
Each run creates a dedicated session directory containing granular JSON snapshots for every step of the workflow. This allows for post-mortem debugging and "time-travel" analysis of the agent's state.
Log Structure:
logs/session_20260125_143210/
βββ 001_researchagent_start.json # Metadata & timestamps
βββ 002_researchagent_tool_web_search.json # Exact API query & raw results
βββ 006_analysisagent_state_analysis_result.json # What the LLM "thought"
βββ 008_reportagent_complete.json # Final status
To debug a failed run:
- Find the session directory in
logs/ - Check
*error.jsonfor stack traces - Review
*llm_response.jsonto see what the LLM received/returned
# Easy (high-quality sources)
python main.py --topic "Docker containers vs VMs"
# Medium (requires iteration)
python main.py --topic "React hooks best practices"
# Hard (limited sources)
python main.py --topic "Emerging trends in quantum computing"Development (Free Tier):
RESEARCH_MODEL=gemini-2.0-flash
GOOGLE_API_KEY=...Production (High Quality):
RESEARCH_MODEL=gemini-2.0-flash # Fast, cheap
ANALYSIS_MODEL=anthropic.claude-3-5-sonnet-20240620-v1:0 # Best reasoning
REPORT_MODEL=anthropic.claude-3-5-sonnet-20240620-v1:0 # Best writing| Setting | Default | Description |
|---|---|---|
MAX_ITERATIONS |
5 | Max research-analysis loops |
CONFIDENCE_THRESHOLD |
0.8 | Minimum confidence to stop |
MAX_SOURCES |
10 | Max sources to analyze |
0. Verify Connectivity Before running the full system, validate your API keys:
python test_connections.pyIf this fails, check your .env file first.
1. "Tavily API key invalid"
# Verify your key works
curl -X POST https://api.tavily.com/search \
-H "Content-Type: application/json" \
-d '{"api_key": "tvly-xxx", "query": "test"}'2. "AWS credentials not found"
# Check AWS CLI configuration
aws configure list
# Or set directly in .env
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...3. "Rate limit exceeded (Gemini)"
- Solution: Switch to Claude (Bedrock) using
.envor wait a minute for quota reset.
4. "PDF generation failed"
- Cause: Long URLs breaking layout
- Solution: Handled in
pdf_export.pywith automatic truncation/wrapping.
Typical run (10 sources, 2 iterations):
- Time: 30-60 seconds
- Cost:
- All-Claude: ~$0.20
- All-Gemini: ~$0.004
- Hybrid (Gemini research + Claude analysis): ~$0.08
See technical-decisions.md for:
- Scalability considerations
- Multi-provider fallback strategy
- State persistence (PostgreSQL)
- Monitoring (OpenTelemetry + Grafana)
- Object-Oriented Design Principles (LLD)
MIT


