Instant-SWOT-Agent / docs /architecture.md
vn6295337's picture
Initial commit: Instant SWOT Agent
0c591a7
# Architecture Documentation
## System Overview
Instant SWOT Agent is an AI-powered strategic analysis system that generates comprehensive SWOT analyses for companies with automatic quality improvement through a self-correcting loop.
## High-Level Architecture
```
User Input (Company Name)
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ USER INTERFACE β”‚
β”‚ Streamlit (streamlit_app.py) β”‚
β”‚ React (frontend/) via FastAPI β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ FastAPI Backend (src/api/app.py) β”‚
β”‚ Routes: analysis.py, stocks.py β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓
Workflow Engine (LangGraph)
src/workflow/graph.py
↓
Node Orchestration
↙ ↓ ↓ ↓ β†˜
Researcher β†’ Analyzer β†’ Critic β†’ Editor
β†˜________β†— (loop until score β‰₯7 or 3 revisions)
↓
Final SWOT Analysis
```
## Directory Structure
```
src/
β”œβ”€β”€ api/ # FastAPI backend
β”‚ β”œβ”€β”€ app.py # Application factory
β”‚ β”œβ”€β”€ schemas.py # Pydantic models
β”‚ └── routes/
β”‚ β”œβ”€β”€ analysis.py # Workflow endpoints
β”‚ └── stocks.py # Stock search endpoint
β”œβ”€β”€ workflow/ # LangGraph workflow
β”‚ β”œβ”€β”€ graph.py # Workflow definition
β”‚ └── runner.py # Execution wrapper
β”œβ”€β”€ nodes/ # Workflow nodes
β”œβ”€β”€ services/ # Shared services
β”‚ β”œβ”€β”€ swot_parser.py # SWOT text parsing
β”‚ β”œβ”€β”€ confidence.py # Confidence calculation
β”‚ └── workflow_store.py # Workflow state management
β”œβ”€β”€ utils/ # Utilities
└── main.py # CLI entry point
```
## Core Components
### 1. Workflow Engine
Located in `src/workflow/graph.py`, implements the self-correcting workflow:
- **Entry**: Researcher node
- **Flow**: Researcher β†’ Analyzer β†’ Critic β†’ (conditional) Editor
- **Exit**: Score β‰₯ 7 OR revision_count β‰₯ 3
### 2. Workflow Nodes
Located in `src/nodes/`:
| Node | File | Responsibility |
|------|------|----------------|
| Researcher | `researcher.py` | Gathers data via MCP servers, summarizes with LLM |
| Analyzer | `analyzer.py` | Generates SWOT analysis draft |
| Critic | `critic.py` | Evaluates quality (1-10 score) using rubric |
| Editor | `editor.py` | Revises draft based on critique |
### 3. MCP Servers
Located in `mcp-servers/`, providing data aggregation:
| Server | Data Source | Output |
|--------|-------------|--------|
| financials-basket | SEC EDGAR | Financial statements |
| volatility-basket | Yahoo Finance, FRED | VIX, Beta, IV |
| macro-basket | FRED | GDP, rates, CPI |
| valuation-basket | Yahoo Finance, SEC | P/E, P/B, EV/EBITDA |
| news-basket | Tavily | News articles |
| sentiment-basket | Finnhub | Sentiment scores |
### 4. State Management
Defined in `src/state.py`, the workflow state flows through each node:
```python
state = {
"company_name": str,
"strategy_focus": str,
"raw_data": str,
"draft_report": str,
"critique": str,
"score": int,
"revision_count": int,
"error": str | None
}
```
## Data Flow
1. **Input**: User enters company name via Streamlit UI
2. **Research**: Researcher node queries MCP servers for financial data
3. **Analysis**: Analyzer generates initial SWOT draft
4. **Evaluation**: Critic scores draft (1-10) against rubric
5. **Improvement**: If score < 7 and revisions < 3, Editor revises
6. **Output**: Final SWOT displayed with quality metrics
## Quality Evaluation
The Critic node uses a rubric-based system:
- **Completeness** (25%): All SWOT sections populated
- **Specificity** (25%): Concrete, actionable insights with data
- **Relevance** (25%): Aligned with company context
- **Depth** (25%): Strategic sophistication
Threshold: Score β‰₯ 7/10 to pass without revision.
## Extending the System
### Adding a New Node
1. Create `src/nodes/new_node.py`:
```python
def new_node(state: dict) -> dict:
# Process state
state["new_field"] = result
return state
```
2. Register in `src/workflow/graph.py`:
```python
workflow.add_node("NewNode", RunnableLambda(new_node))
workflow.add_edge("PreviousNode", "NewNode")
```
### Adding a New MCP Server
1. Create directory `mcp-servers/new-basket/`
2. Implement server with tool registration
3. Update Researcher node to call new server
## Observability
- **LangSmith**: End-to-end workflow tracing (configure via environment variables)
- **Logging**: Python standard logging at INFO/DEBUG levels
## Error Handling
- MCP server failures: Graceful degradation, continue with available data
- LLM failures: Retry with fallback providers
- Quality failures: Maximum 3 revision attempts before accepting result