# Components ## Directory Tree ``` tradingagents/ ├── __init__.py ├── default_config.py # All config keys, defaults, env var overrides ├── report_paths.py # Unified report path helpers (reports/daily/{date}/) ├── daily_digest.py # append_to_digest() — consolidates runs into daily_digest.md ├── notebook_sync.py # sync_to_notebooklm() — uploads digest to NotebookLM via nlm CLI ├── observability.py # RunLogger, _LLMCallbackHandler, structured event logging ├── agents/ │ ├── __init__.py │ ├── analysts/ │ │ ├── fundamentals_analyst.py # create_fundamentals_analyst(llm) │ │ ├── market_analyst.py # create_market_analyst(llm) │ │ ├── news_analyst.py # create_news_analyst(llm) │ │ └── social_media_analyst.py # create_social_media_analyst(llm) │ ├── managers/ │ │ ├── research_manager.py # create_research_manager(llm, memory) │ │ └── risk_manager.py # create_risk_manager(llm, memory) │ ├── researchers/ │ │ ├── bear_researcher.py # create_bear_researcher(llm, memory) │ │ └── bull_researcher.py # create_bull_researcher(llm, memory) │ ├── risk_mgmt/ │ │ ├── aggressive_debator.py # create_aggressive_debator(llm) │ │ ├── conservative_debator.py # create_conservative_debator(llm) │ │ └── neutral_debator.py # create_neutral_debator(llm) │ ├── scanners/ │ │ ├── __init__.py │ │ ├── geopolitical_scanner.py # create_geopolitical_scanner(llm) │ │ ├── market_movers_scanner.py # create_market_movers_scanner(llm) │ │ ├── sector_scanner.py # create_sector_scanner(llm) │ │ ├── smart_money_scanner.py # create_smart_money_scanner(llm) ← NEW │ │ ├── industry_deep_dive.py # create_industry_deep_dive(llm) │ │ └── macro_synthesis.py # create_macro_synthesis(llm) │ ├── trader/ │ │ └── trader.py # create_trader(llm, memory) │ └── utils/ │ ├── agent_states.py # AgentState, InvestDebateState, RiskDebateState │ ├── agent_utils.py # Tool re-exports, create_msg_delete() │ ├── core_stock_tools.py # get_stock_data, get_indicators, get_macro_regime │ ├── fundamental_data_tools.py # get_fundamentals, get_balance_sheet, etc. │ ├── json_utils.py # extract_json() │ ├── memory.py # FinancialSituationMemory │ ├── news_data_tools.py # get_news, get_global_news, get_insider_transactions │ ├── scanner_states.py # ScannerState, _last_value reducer │ ├── scanner_tools.py # Scanner @tool definitions (10 tools: 7 routed + 3 Finviz direct) │ ├── technical_indicators_tools.py │ └── tool_runner.py # run_tool_loop(), MAX_TOOL_ROUNDS, MIN_REPORT_LENGTH ├── dataflows/ │ ├── __init__.py │ ├── config.py # set_config(), get_config(), initialize_config() │ ├── interface.py # route_to_vendor, VENDOR_METHODS, FALLBACK_ALLOWED │ ├── alpha_vantage.py # Re-export facade │ ├── alpha_vantage_common.py # Exception hierarchy, rate limiter │ ├── alpha_vantage_fundamentals.py │ ├── alpha_vantage_indicator.py │ ├── alpha_vantage_news.py │ ├── alpha_vantage_scanner.py │ ├── alpha_vantage_stock.py │ ├── finnhub.py │ ├── finnhub_common.py # Exception hierarchy, rate limiter │ ├── finnhub_fundamentals.py │ ├── finnhub_indicators.py │ ├── finnhub_news.py │ ├── finnhub_scanner.py │ ├── finnhub_stock.py │ ├── macro_regime.py │ ├── peer_comparison.py │ ├── stockstats_utils.py │ ├── ttm_analysis.py │ ├── utils.py │ ├── y_finance.py # Core yfinance data functions │ ├── yfinance_news.py │ └── yfinance_scanner.py ├── graph/ │ ├── trading_graph.py # TradingAgentsGraph class │ ├── scanner_graph.py # ScannerGraph class │ ├── setup.py # GraphSetup — trading graph builder │ ├── scanner_setup.py # ScannerGraphSetup — scanner graph builder │ ├── conditional_logic.py # ConditionalLogic — debate/risk routing │ ├── propagation.py # Propagator │ ├── reflection.py # Reflector │ └── signal_processing.py # SignalProcessor ├── llm_clients/ # Multi-provider LLM factory │ └── (create_llm_client dispatch) └── pipeline/ ├── __init__.py └── macro_bridge.py # MacroBridge, data classes, pipeline orchestration cli/ └── main.py # Typer app, MessageBuffer, Rich UI, 3 commands agent_os/ ├── __init__.py ├── DESIGN.md # Visual observability design document ├── README.md # AgentOS overview and setup instructions ├── backend/ │ ├── __init__.py │ ├── main.py # FastAPI app, CORS, route mounting (port 8088) │ ├── dependencies.py # get_current_user() (V1 hardcoded), get_db_client() │ ├── store.py # In-memory run store (Dict[str, Dict]) │ ├── routes/ │ │ ├── __init__.py │ │ ├── runs.py # POST /api/run/{scan,pipeline,portfolio,auto} │ │ ├── websocket.py # WS /ws/stream/{run_id} — sole executor │ │ └── portfolios.py # GET /api/portfolios/* — CRUD + summary + latest │ └── services/ │ ├── __init__.py │ └── langgraph_engine.py # LangGraphEngine: run_scan/pipeline/portfolio/auto, event mapping └── frontend/ ├── package.json # React 18 + Vite 8 + Chakra UI + ReactFlow ├── tsconfig.json ├── vite.config.ts ├── index.html └── src/ ├── main.tsx # React entry point ├── App.tsx # ChakraProvider wrapper ├── Dashboard.tsx # 2-page layout: dashboard (graph+terminal) / portfolio ├── theme.ts # Dark theme customization ├── index.css # Global styles ├── hooks/ │ └── useAgentStream.ts # WebSocket hook, AgentEvent type, status ref └── components/ ├── AgentGraph.tsx # ReactFlow live graph with incremental nodes ├── MetricHeader.tsx # Top-3 metrics: Sharpe, regime, drawdown └── PortfolioViewer.tsx # Holdings table, trade history, snapshot view ``` ## Agent Factory Inventory (18 factories + 1 utility) | Factory | File | LLM Tier | Extra Params | |---------|------|----------|-------------| | `create_fundamentals_analyst` | `agents/analysts/fundamentals_analyst.py` | quick | — | | `create_market_analyst` | `agents/analysts/market_analyst.py` | quick | — | | `create_news_analyst` | `agents/analysts/news_analyst.py` | quick | — | | `create_social_media_analyst` | `agents/analysts/social_media_analyst.py` | quick | — | | `create_bull_researcher` | `agents/researchers/bull_researcher.py` | mid | `memory` | | `create_bear_researcher` | `agents/researchers/bear_researcher.py` | mid | `memory` | | `create_research_manager` | `agents/managers/research_manager.py` | deep | `memory` | | `create_trader` | `agents/trader/trader.py` | mid | `memory` | | `create_aggressive_debator` | `agents/risk_mgmt/aggressive_debator.py` | quick | — | | `create_conservative_debator` | `agents/risk_mgmt/conservative_debator.py` | quick | — | | `create_neutral_debator` | `agents/risk_mgmt/neutral_debator.py` | quick | — | | `create_risk_manager` | `agents/managers/risk_manager.py` | deep | `memory` | | `create_geopolitical_scanner` | `agents/scanners/geopolitical_scanner.py` | quick | — | | `create_market_movers_scanner` | `agents/scanners/market_movers_scanner.py` | quick | — | | `create_sector_scanner` | `agents/scanners/sector_scanner.py` | quick | — | | `create_smart_money_scanner` | `agents/scanners/smart_money_scanner.py` | quick | — | | `create_industry_deep_dive` | `agents/scanners/industry_deep_dive.py` | mid | — | | `create_macro_synthesis` | `agents/scanners/macro_synthesis.py` | deep | — | | `create_msg_delete` | `agents/utils/agent_utils.py` | — | No LLM param | ## Extension Guides ### Adding a New Analyst 1. Create `tradingagents/agents/analysts/new_analyst.py` with `create_new_analyst(llm)` 2. Add tools to `tradingagents/agents/utils/` and register in `agent_utils.py` 3. Register tool node in `trading_graph.py:_create_tool_nodes()` 4. Add node and edges in `graph/setup.py:setup_graph()` 5. Add conditional routing in `graph/conditional_logic.py` 6. Add to `cli/main.py` `ANALYST_MAPPING` and `REPORT_SECTIONS` ### Adding a New Scanner 1. Create `tradingagents/agents/scanners/new_scanner.py` with `create_new_scanner(llm)` 2. Export from `agents/scanners/__init__.py` 3. Add to `scanner_graph.py` agents dict 4. Add node and edges in `graph/scanner_setup.py` 5. Add state field with `_last_value` reducer to `scanner_states.py` ### Adding a New Data Vendor 1. Create `tradingagents/dataflows/newvendor_common.py` (exception hierarchy, rate limiter) 2. Create per-domain modules (`newvendor_stock.py`, `newvendor_scanner.py`, etc.) 3. Add vendor functions to `VENDOR_METHODS` in `interface.py` 4. Add vendor to `VENDOR_LIST` in `interface.py` 5. Add exception types to the catch tuple in `route_to_vendor` 6. Add config category in `default_config.py` `data_vendors` ### Adding a New LLM Provider 1. Add client creation logic to `tradingagents/llm_clients/` 2. Add provider-specific kwargs handling in `trading_graph.py:_get_provider_kwargs()` and `scanner_graph.py:_get_provider_kwargs()` 3. Add API key to `.env.example` ### Adding a New Config Key 1. Add to `DEFAULT_CONFIG` dict in `default_config.py` with `_env()` or `_env_int()` override 2. Add to `.env.example` with documentation 3. Update `CLAUDE.md` if it's a frequently-used key ## CLI Commands | Command | Function | Description | |---------|----------|-------------| | `analyze` | `run_analysis()` | Interactive per-ticker multi-agent analysis with Rich live UI | | `scan` | `run_scan(date)` | Macro scanner (4 Phase-1 nodes + deep dive + synthesis), saves 5 report files | | `pipeline` | `run_pipeline()` | Full pipeline: scan JSON → filter by conviction → per-ticker deep dive | ## AgentOS Frontend Components | Component | File | Description | |-----------|------|-------------| | `Dashboard` | `agent_os/frontend/src/Dashboard.tsx` | 2-page layout with sidebar (dashboard/portfolio), run buttons, param panel | | `AgentGraph` | `agent_os/frontend/src/components/AgentGraph.tsx` | ReactFlow live graph — incremental node addition via useRef(Set) dedup | | `MetricHeader` | `agent_os/frontend/src/components/MetricHeader.tsx` | Top-3 metrics: Sharpe ratio, market regime+beta, drawdown+VaR | | `PortfolioViewer` | `agent_os/frontend/src/components/PortfolioViewer.tsx` | 3-tab view: holdings table, trade history, snapshot summary | | `useAgentStream` | `agent_os/frontend/src/hooks/useAgentStream.ts` | WebSocket hook with `statusRef` to avoid stale closures | ## AgentOS Backend Services | Service | File | Description | |---------|------|-------------| | `LangGraphEngine` | `agent_os/backend/services/langgraph_engine.py` | Orchestrates 4 run types, maps LangGraph v2 events to frontend events | | `runs` router | `agent_os/backend/routes/runs.py` | REST triggers: `POST /api/run/{type}` — queues runs in memory store | | `websocket` router | `agent_os/backend/routes/websocket.py` | `WS /ws/stream/{run_id}` — sole executor, streams events to frontend | | `portfolios` router | `agent_os/backend/routes/portfolios.py` | Portfolio CRUD, summary metrics, holdings/trades with field mapping | | `dependencies` | `agent_os/backend/dependencies.py` | `get_current_user()` (V1 hardcoded), `get_db_client()` | | `store` | `agent_os/backend/store.py` | In-memory `Dict[str, Dict]` run store (demo, not persisted) | ## Test Organization | Test File | Type | What It Covers | Markers | |-----------|------|---------------|---------| | `test_alpha_vantage_exceptions.py` | Mixed | AV exception hierarchy, `_make_api_request` errors | `integration` on HTTP tests | | `test_alpha_vantage_integration.py` | Unit | Full AV data layer (all mocked) | — | | `test_alpha_vantage_scanner.py` | Integration | Live AV scanner functions | `integration` | | `test_config_wiring.py` | Unit | `AgentState` fields, tool exports, debate wiring | — | | `test_debate_rounds.py` | Unit | `ConditionalLogic` routing at various round counts | — | | `test_e2e_api_integration.py` | Unit | Vendor routing layer (all mocked) | — | | `test_env_override.py` | Unit | `TRADINGAGENTS_*` env var overrides | — | | `test_finnhub_integration.py` | Unit | Full Finnhub data layer (all mocked) | — | | `test_finnhub_live_integration.py` | Integration | Live Finnhub endpoints | `integration`, `paid_tier` | | `test_industry_deep_dive.py` | Mixed | `_extract_top_sectors`, nudge mechanism, enriched output | — | | `test_json_utils.py` | Unit | `extract_json()` — markdown, think blocks, edge cases | — | | `test_macro_bridge.py` | Unit | Pipeline: parse, filter, render, save | — | | `test_macro_regime.py` | Mixed | Macro signals, regime classification, report format | `integration` on live test | | `test_nlm_live.py` | Integration | Live NLM CLI tests for NotebookLM sync | — | | `test_notebook_sync.py` | Unit | `notebook_sync.py` logic, `nlm` subprocess mocking | — | | `test_peer_comparison.py` | Mixed | Peer comparison functions | `integration` on live test | | `test_scanner_comprehensive.py` | Integration | All 5 scanner tools + CLI output naming | — | | `test_scanner_fallback.py` | Mixed | yfinance perf, AV failure mode, fallback routing | `integration` on some | | `test_scanner_graph.py` | Unit | `ScannerGraph` import/instantiation, graph compilation | — | | `test_scanner_mocked.py` | Unit | All yfinance + AV scanner functions (all mocked) | — | | `test_scanner_routing.py` | Integration | Live routing with AV config | `integration` | | `test_scanner_tools.py` | Integration | Scanner tool imports + live invocation | — | | `test_ttm_analysis.py` | Mixed | TTM metrics computation, report format | `integration` on live test | | `test_vendor_failfast.py` | Unit | ADR 011 fail-fast behavior, error chaining | — | | `test_yfinance_integration.py` | Unit | Full yfinance data layer (all mocked) | — | | `test_langgraph_engine_extraction.py` | Unit | LangGraph event mapping, model/prompt extraction, _safe_dict helper | — | Pytest markers: `integration` (live API), `paid_tier` (Finnhub paid subscription), `slow` (long-running). Defined in `conftest.py`.