Beyond Markets — Architecture

Multi-agent financial analysis system powered by Claude. A user submits a natural-language request (e.g. "Analyse AAPL") and a pipeline of specialised AI agents gathers data, analyses it, critiques the analysis, and writes a final report.

┌─────────────────────────────────────────────────────────────────────┐
│                        Web UI (Starlette)                           │
│  web.py · localhost:8000                                            │
│                                                                     │
│  ┌──────────┐  ┌────────────┐  ┌──────────┐  ┌─────────────────┐   │
│  │ Auth     │  │ POST /run  │  │ Reports  │  │ Articles        │   │
│  │ register │  │ start job  │  │ per-     │  │ list / download │   │
│  │ login    │  │ SSE /events│  │ tenant   │  │ (shared)        │   │
│  └──────────┘  └─────┬──────┘  └──────────┘  └─────────────────┘   │
│        │              │                                             │
│  ┌─────────────────────────────────────────────────────────────┐    │
│  │ Bearer token auth · per-tenant data isolation               │    │
│  │ tenants.py → .data/tenants.db (SQLite)                      │    │
│  └─────────────────────────────────────────────────────────────┘    │
│                                                                     │
└────────┼──────────────┼─────────────────────────────────────────────┘
         │              │
                       │
┌─────────────────────────────────────────────────────────────────────┐
│                     Orchestrator                                    │
│  agents/orchestrator.py                                             │
│                                                                     │
│  Phase 0 ─ Planning                                                 │
│  ┌──────────────────────────────────────────────────────────┐       │
│  │  PlannerAgent                                            │       │
│  │  Decomposes user request → mode, targets, agent tasks    │       │
│  └──────────────────────────────────────────────────────────┘       │
│       │                                                             │
│                                                                    │
│  Phase 1 ─ Parallel Data Gathering (ThreadPoolExecutor, 4 workers)  │
│  ┌─────────────┐ ┌─────────────┐ ┌────────┐ ┌──────────────────┐    │
│  │ NewsAgent   │ │ MarketData  │ │ Macro  │ │ GeopoliticalRisk │    │
│  │             │ │ Agent       │ │ Agent  │ │ Agent            │    │
│  │ Haiku 4.5   │ │ Haiku 4.5   │ │Haiku4.5│ │ Haiku 4.5        │    │
│  └──────┬──────┘ └──────┬──────┘ └───┬────┘ └────────┬─────────┘    │
│         │               │            │               │              │
│                                                                 │
│  Phase 2 ─ Sequential Analysis (each sees all prior outputs)        │
│  ┌─────────────────┐ ┌────────────────┐ ┌───────────────────────┐   │
│  │ EquityAnalyst   │ │ SwingTrading   │ │ MacroLiquidity        │   │
│  │ Sonnet 4.6        │ │ Analyst        │ │ Analyst               │   │
│  │                 │ │ Sonnet 4.6       │ │ Sonnet 4.6              │   │
│  └────────┬────────┘ └───────┬────────┘ └───────────┬───────────┘   │
│           │                  │                      │               │
│                                                                  │
│  ┌─────────────────┐                                                │
│  │ ScenarioAgent   │                                                │
│  │ (Sonnet 4.6)      │                                                │
│  └────────┬────────┘                                                │
│                                                                    │
│  Phase 3 ─ Review                                                   │
│  ┌──────────────────────────────────────────────────────────┐       │
│  │  CriticAgent (Opus 4.7)                                  │       │
│  │  Reviews all outputs for gaps, contradictions, risks     │       │
│  └──────────────────────────────────────────────────────────┘       │
│           │                                                         │
│                                                                    │
│  Phase 4 ─ Report                                                   │
│  ┌──────────────────────────────────────────────────────────┐       │
│  │  ReportWriterAgent (Sonnet 4.6, 16k max tokens)            │       │
│  │  Synthesises everything into final markdown report       │       │
│  └──────────────────────────────────────────────────────────┘       │
│           │                                                         │
│                                                                    │
│       reports/{tenant_id}/*.md + .meta.json + .log                  │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                       AgentRunner                                   │
│  agents/runner.py                                                   │
│                                                                     │
│  - Loads a skill markdown file (agents/skills/*.md) as system prompt│
│  - Wires tool definitions from tool modules                         │
│  - Runs a Claude API tool-use loop (up to 12 rounds)                │
│  - Retry with exponential backoff on tool failures (3 attempts)     │
│  - Retry on transient API errors (5xx, 3 attempts)                  │
│  - Prompt caching on system prompt, tools, and context blocks       │
│  - Tracks token usage (input / output / cache read / cache write)   │
└──────────────────────────┬──────────────────────────────────────────┘
                           │
                           
┌─────────────────────────────────────────────────────────────────────┐
│                       Tool Modules                                  │
│                                                                     │
│  ┌───────────────────┐  ┌────────────────────┐  ┌────────────────┐  │
│  │ data_ingestion_   │  │ data_ingestion_    │  │ data_ingestion_│  │
│  │ fmp.py            │  │ fred.py            │  │ imf.py         │  │
│  │                   │  │                    │  │                │  │
│  │ Financial         │  │ Federal Reserve    │  │ IMF DataMapper │  │
│  │ Modeling Prep     │  │ Economic Data      │  │ ECB Statistics │  │
│  │ (27 tools)        │  │ (15 tools)         │  │ BIS Statistics │  │
│  │ via httpx         │  │ via httpx          │  │ via sdmx1      │  │
│  └───────────────────┘  └────────────────────┘  └────────────────┘  │
│                                                                     │
│  ┌───────────────────┐  ┌────────────────────┐  ┌────────────────┐  │
│  │ data_ingestion_   │  │ data_ingestion_    │  │ data_ingestion_│  │
│  │ newsapi.py        │  │ gdelt.py           │  │ newsdata.py    │  │
│  │                   │  │                    │  │                │  │
│  │ NewsAPI.org       │  │ GDELT DOC 2.0     │  │ NewsData.io    │  │
│  │ (10 tools)        │  │ (4 tools)          │  │ (4 tools)      │  │
│  │ via httpx         │  │ via httpx          │  │ via httpx      │  │
│  │ [disabled]        │  │ [no key needed]    │  │                │  │
│  └───────────────────┘  └────────────────────┘  └────────────────┘  │
│                                                                     │
│  ┌───────────────────┐  ┌────────────────────┐  ┌────────────────┐  │
│  │ data_ingestion_   │  │ data_ingestion_    │  │ data_ingestion_│  │
│  │ alphavantage.py   │  │ sec.py             │  │ openfigi.py    │  │
│  │                   │  │                    │  │                │  │
│  │ Alpha Vantage     │  │ SEC EDGAR          │  │ OpenFIGI       │  │
│  │ Forex, Commodities│  │ Company facts,     │  │ FIGI identifier│  │
│  │ Crypto, Econ data │  │ filings, concepts, │  │ mapping &      │  │
│  │ (4 tools)         │  │ full-text search   │  │ search         │  │
│  │ via httpx         │  │ (4 tools, no key)  │  │ (2 tools)      │  │
│  └───────────────────┘  └────────────────────┘  └────────────────┘  │
│                                                                     │
│  ┌───────────────────┐  ┌────────────────────┐  ┌────────────────┐  │
│  │ data_ingestion_   │  │ macro_             │  │ cache.py       │  │
│  │ articles.py       │  │ liquidity.py       │  │                │  │
│  │                   │  │                    │  │ SQLite-backed  │  │
│  │ Local markdown    │  │ Composite          │  │ TTL cache      │  │
│  │ articles +        │  │ macro-liquidity    │  │ (per-tool TTLs,│  │
│  │ web scraping      │  │ score from         │  │  WAL mode)     │  │
│  │ (Economist,       │  │ FRED data          │  │ All tool calls │  │
│  │  Reuters,         │  │                    │  │ route through  │  │
│  │  Damodaran)       │  │                    │  │ tool_cache     │  │
│  └───────────────────┘  └────────────────────┘  └────────────────┘  │
│                                                                     │
│  ┌───────────────────────────┐  ┌─────────────────────────────────┐  │
│  │ data_ingestion_alpaca_    │  │ data_ingestion_alpaca.py        │  │
│  │ mktdata.py                │  │                                 │  │
│  │                           │  │ Alpaca Trading — bracket orders,│  │
│  │ Alpaca Market Data (agent │  │ positions, get_snapshots(),     │  │
│  │ tools): market movers,    │  │ get_bracket_context(). Used by  │  │
│  │ most-active, stock        │  │ routes/trades.py, not agents.   │  │
│  │ snapshots, Alpaca news    │  │ Thread-local per-tenant keys.   │  │
│  └───────────────────────────┘  └─────────────────────────────────┘  │
│                                                                     │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │ tools.json — per-module enabled/disabled config                │ │
│  └────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                      External APIs                                  │
│                                                                     │
│  Claude API (Anthropic)  ·  FMP API  ·  FRED API  ·  Alpha Vantage  │
│  IMF DataMapper  ·  ECB SDMX  ·  BIS SDMX  ·  GDELT (free)         │
│  NewsData.io  ·  SEC EDGAR (free)  ·  OpenFIGI  ·  NewsAPI.org*     │
│  Alpaca (paper + live trading)  ·  Polygon.io (Advanced plan)       │
│                                                                     │
│  * disabled by default in tools.json                                │
└─────────────────────────────────────────────────────────────────────┘

Agent-Tool Mapping

Agent Model Tools
planner Sonnet 4.6 (none)
news Haiku 4.5 newsapi, gdelt, newsdata, articles, fmp (news + profile), finviz (news), web_search, alpaca_mktdata (news)*
market_data Haiku 4.5 fmp (all), sec, openfigi, finviz (screener subset), 13f, uw, alpaca_mktdata (movers, most-active, snapshots)
macro Haiku 4.5 fred, imf, articles, alphavantage, newsapi_ai (news subset)
geopolitical_risk Haiku 4.5 newsapi_ai, gdelt, newsdata, articles, web_search
equity_analyst Sonnet 4.6 fmp, fred, sec, openfigi, newsapi_ai (news subset), uw
swing_trading_analyst Sonnet 4.6 fmp, fred, newsapi_ai, newsdata (search), alphavantage (commodities + forex), uw (options flow subset)
macro_liquidity_analyst Sonnet 4.6 macro_liquidity, fred (subset)
scenario Sonnet 4.6 (none)
critic Opus 4.7 (none)
report_writer_default Sonnet 4.6 (none) — equity deep-dive, 10-section format
report_writer Sonnet 4.6 (none) — market brief, macro, news digest, data pull
report_writer_vip Sonnet 4.6 (none) — VIP 4-section format (Market Briefing for Aarti)

* newsapi is disabled by default in tools.json; newsapi_ai + gdelt + newsdata serve as replacements.

uw = local Unusual Whales daily CSV snapshots in uw/. Seeded on deploy, refreshed daily by scheduler. Returns empty gracefully when files absent.

alpaca_mktdata = tools/data_ingestion_alpaca_mktdata.py. Provides market movers, most-active stocks, batch snapshots, and Alpaca news via the Alpaca Market Data REST API. Uses env-var keys (not per-tenant TLS), so no auth setup needed per agent call.

Data Flow

  1. User registers or logs in via the web UI. The server returns a Bearer API key stored in localStorage.
  2. All subsequent requests include Authorization: Bearer <key>. SSE and window.open calls pass the key as a ?token= query parameter instead.
  3. Orchestrator creates a Job scoped to the tenant, runs the pipeline in a background thread, and streams progress events back via SSE.
  4. Phase 0 — the Planner decomposes the request into a structured plan (mode, targets, per-agent tasks).
  5. Phase 1 — data-gathering agents run in parallel (up to 4 threads), each calling external APIs through tool modules. Results are cached in SQLite with per-tool TTLs. Transient failures are retried with exponential backoff (up to 3 attempts per tool call).
  6. Phase 2 — analysis agents run sequentially, each receiving the cumulative output of all previous phases as context.
  7. Phase 3 — the Critic reviews all outputs for gaps and contradictions.
  8. Phase 4 — the Report Writer produces the final markdown report.
  9. The report is saved to reports/{tenant_id}/ with metadata and a log file. Usage (tokens, cost, elapsed time) is recorded in .data/tenants.db.

Tool Configuration

Tool modules can be enabled or disabled via tools.json in the project root. Each key is a module short name matching TOOL_MODULES in agents/runner.py:

{
  "fmp":             { "enabled": true },
  "fred":            { "enabled": true },
  "imf":             { "enabled": true },
  "newsapi":         { "enabled": false },
  "newsapi_ai":      { "enabled": true },
  "gdelt":           { "enabled": true },
  "newsdata":        { "enabled": true },
  "articles":        { "enabled": true },
  "sec":             { "enabled": true },
  "alphavantage":    { "enabled": true },
  "openfigi":        { "enabled": true },
  "macro_liquidity": { "enabled": true },
  "uw":              { "enabled": true },
  "finviz":          { "enabled": true },
  "unusualwhales":   { "enabled": false }
}

Disabled modules are skipped when the runner wires tools for an agent. This allows swapping data sources without code changes (e.g. NewsAPI.org → GDELT + NewsData.io).

Scheduler

Four background daemon threads started when web.py boots:

Thread Interval Purpose
Thread 1 — Daily Reports 06:00 UTC daily Generates reports for watchlist items and periodic requests; reuses existing where valid; weekly items on Mondays
Thread 2 — Data Refresh Every 15 min Refreshes UW CSV snapshots and stale market data
Thread 3 — Trade Monitor Every 60s Polls all open DB positions; auto-closes filled bracket exit legs; reconciles positions Alpaca no longer holds
Thread 4 — Trade Propose Every 10 min (starts 10s after boot) Runs swing trading pipeline to generate new trade propositions

Trades / Swing Trading

routes/trades.py + trade_db.py + tools/data_ingestion_alpaca.py

Database: SQLite at .data/trades.db. Tables: propositions (AI trade ideas) and positions (active/closed trades).

Source of truth: Alpaca holds the authoritative position list. The positions table stores bracket context (stop/target/opened_at/proposition_id) but does not gate whether a position is displayed. Any symbol Alpaca holds that has no DB record is auto-registered on the next trades load via get_bracket_context().

Lifecycle: 1. Swing Trading Analyst generates a trade card → saved to propositions table. 2. User clicks Buy/Sell on the proposition → bracket limit order placed on Alpaca via place_bracket_order(). 3. positions record created in DB with stop/target from the proposition. 4. Trade Monitor (Thread 3) polls get_exit_fill() every 60s; closes the DB record when a bracket leg fills.

Key functions in tools/data_ingestion_alpaca.py: - get_snapshots(symbols) — batch StockSnapshotRequest SDK call; returns price, bid, ask, OHLCV, change% per symbol. - get_bracket_context(symbol, mode) — reconstructs stop/target from open SELL orders, opened_at from earliest filled BUY. - set_tenant_keys() / clear_tenant_keys() — load/clear per-tenant Alpaca keys into thread-local _tls.

/api/trades/snapshots endpoint: batch price endpoint used by the frontend to poll live prices for all open positions once per 60s.

Multi-Tenancy

Each user is a tenant with an isolated data namespace:

Billing

Stripe integration exists for subscription checkout and management but can be disabled via STRIPE_CHECKOUT_ENABLED=false in .env. When disabled:

Admins can manually assign plans via the admin panel or CLI (python tenants.py set-plan user@example.com pro).

Key Files

.
├── web.py                              # Starlette web server + HTML/JS UI + auth
├── tenants.py                          # Multi-tenancy: TenantDB (SQLite), migration
├── tools.json                          # Per-module enabled/disabled config
├── install.sh                          # macOS installer (venv, API keys, LaunchAgent)
├── uninstall.sh                        # Removes installation + LaunchAgent
├── run_server.sh                       # Kills port 8000, starts web.py
├── agents/
│   ├── orchestrator.py                 # Multi-phase pipeline controller
│   ├── runner.py                       # Single-agent Claude API loop + retry logic
│   └── skills/                         # Markdown system prompts per agent
│       ├── planner.md
│       ├── news.md
│       ├── market_data.md
│       ├── macro.md
│       ├── geopolitical_risk.md
│       ├── equity_analyst.md
│       ├── swing_trading_analyst.md
│       ├── macro_liquidity_analyst.md
│       ├── scenario.md
│       ├── critic.md
│       ├── report_writer.md            # Default writer (market_brief, macro, news_digest, data_pull)
│       ├── report_writer_default.md    # Equity deep-dive writer (10-step framework)
│       └── report_writer_vip.md        # VIP 4-section writer (Market Briefing for Aarti)
├── tools/
│   ├── cache.py                        # SQLite TTL cache (shared across tenants)
│   ├── data_ingestion_fmp.py           # Financial Modeling Prep
│   ├── data_ingestion_fred.py          # FRED (Federal Reserve)
│   ├── data_ingestion_imf.py           # IMF / ECB / BIS
│   ├── data_ingestion_newsapi.py       # NewsAPI.org (disabled by default)
│   ├── data_ingestion_newsapi_ai.py    # NewsAPI.ai / Event Registry
│   ├── data_ingestion_gdelt.py         # GDELT DOC 2.0 (free, no key)
│   ├── data_ingestion_newsdata.py      # NewsData.io
│   ├── data_ingestion_alphavantage.py  # Alpha Vantage (forex, commodities, crypto)
│   ├── data_ingestion_sec.py           # SEC EDGAR (filings, facts, free)
│   ├── data_ingestion_openfigi.py      # OpenFIGI (identifier mapping)
│   ├── data_ingestion_articles.py      # Local articles + web scraping
│   ├── data_ingestion_external_data.py # UW daily CSV snapshots (module key: "uw")
│   ├── data_ingestion_finviz.py        # FinViz Elite (screener, news, sectors)
│   ├── data_ingestion_alpaca.py        # Alpaca Trading API (orders, positions, snapshots, bracket context)
│   ├── data_ingestion_alpaca_mktdata.py# Alpaca Market Data (movers, most-active, snapshots, news; agent module key: "alpaca_mktdata")
│   └── macro_liquidity.py              # Composite liquidity scoring
├── uw/                                 # Unusual Whales daily CSV snapshots
│   ├── bot-eod-report-*.csv            # Options flow (EOD)
│   ├── chain-oi-changes-*.csv          # Open interest changes
│   ├── dp-eod-report-*.csv             # Dark pool prints
│   ├── stock-screener-*.csv            # Stock/options screener
│   └── analysis/                       # Output from generate_*.py scripts
├── uw_download.py                      # Playwright downloader for UW daily files
├── trade_db.py                         # Trade database (propositions + positions, SQLite at .data/trades.db)
├── routes/
│   └── trades.py                       # Trade routes (propositions, positions, order flow, snapshots endpoint)
├── .data/                              # Tenant database + per-tenant data
│   ├── tenants.db                      # SQLite: tenants + usage tables
│   ├── trades.db                       # SQLite: propositions + positions tables
│   └── .migrated                       # Migration sentinel
├── articles/                           # Downloaded article store (shared)
└── reports/                            # Generated reports (per-tenant)
    └── {tenant_id}/                    # Each tenant's reports + .meta.json + .log

Skills Definitions

Each agent is driven by a markdown skill file (agents/skills/*.md) loaded as the system prompt by AgentRunner. The skill defines the agent's persona, tools, workflow, and output format.

planner (Sonnet 4.6)

Role: Orchestration brain — decomposes a natural-language request into a structured JSON execution plan (mode, targets, per-agent tasks).

Tools: None (pure reasoning).

Output: A single JSON object:

{
  "mode": "equity_deep_dive | swing_trade | market_brief | macro_outlook | news_digest",
  "targets": ["AAPL"],
  "agents": { "<name>": { "activate": true, "task": "..." } }
}

Mode selection rules: - equity_deep_dive — user names specific stock(s); activates all agents. - swing_trade — user asks about trading, entries, short-term positioning; skips equity_analyst and scenario. - market_brief — broad market/sector questions; skips equity_analyst, swing_trading_analyst, scenario. - macro_outlook — economy, rates, liquidity; focuses on macro + macro_liquidity_analyst + geopolitical_risk. - news_digest — "what's happening" requests; news + geopolitical_risk only.

Always activates report_writer and critic regardless of mode.


news (Haiku 4.5)

Role: Financial news analyst — gathers, filters, and synthesises news from multiple sources.

Tools: NewsAPI* (get_finance_news_snapshot, search_news, get_company_news, get_market_news, get_macro_news, get_geopolitical_news, get_central_bank_news), GDELT (search_gdelt_news, get_gdelt_sentiment, get_gdelt_coverage_volume, get_gdelt_geo_news), NewsData.io (search_newsdata, get_newsdata_market, get_newsdata_crypto, get_newsdata_sources), FMP (get_news, get_company_profile), Articles archive (search_articles, get_recent_articles, get_article, list_articles).

* NewsAPI disabled by default; GDELT + NewsData.io serve as replacements.

Workflow: Broad snapshot first → company-specific FMP news → article archive for thematic depth → full article reads only for high-relevance pieces.

Output sections: Headlines & Key Developments, Company-Specific News, Sentiment Signals (bullish/bearish/mixed/neutral), Themes & Trends, Sources.


market_data (Haiku 4.5)

Role: Market data specialist — fetches and organises equity data from FMP, SEC EDGAR, and OpenFIGI for downstream analysis.

Tools: FMP — quotes & prices (get_stock_quote, get_batch_quotes, get_price_history, get_intraday_prices), company data (get_company_profile, get_financial_statements, get_key_metrics, get_financial_ratios), analyst & valuation (get_analyst_data, get_dcf_valuation, get_esg), insider & ownership (get_insider_trades, get_congressional_trades), filings & transcripts (get_sec_filings, get_earnings_transcript), technicals (get_technical_indicator), market-wide (get_news, get_market_movers, get_sector_performance, get_economic_indicator, get_treasury_rates, screen_stocks), bundle (get_company_research_bundle — 24 concurrent calls). SEC EDGAR (get_sec_company_facts, get_sec_submissions, get_sec_concept, search_sec_filings). OpenFIGI (map_identifiers, search_figi).

Workflow: Single-company → get_company_research_bundle; multi-company → get_batch_quotes + individual metrics; sector → get_sector_performance + screen_stocks. Always includes SMA(50) and SMA(200) for trend context.

Output: Structured tables — Quote Summary, Financial Summary (3-year), Key Metrics (TTM), Analyst Consensus, Technical Levels. Minimal interpretation; raw data for analysts.


macro (Haiku 4.5)

Role: Macroeconomist — assesses the macro regime and outlook from FRED, IMF, ECB, BIS, and Alpha Vantage data.

Tools: FRED (14 tools — get_macro_snapshot, get_yield_curve, get_inflation_dashboard, get_labor_market, get_housing_market, get_credit_conditions, get_consumer_health, get_manufacturing_trade, get_monetary_aggregates, get_financial_stress, get_real_rates, get_leading_indicators, get_fred_series, list_available_series), IMF (9 tools — global outlook, GDP, inflation, current account, unemployment, debt, fiscal balance, indicator, country listing), ECB (6 tools — rates, HICP, money supply, FX, bond yields, snapshot), BIS (7 tools — credit/GDP, debt service, property prices, total credit, policy rates, effective exchange rates, snapshot), Alpha Vantage (get_forex_daily, get_commodity_prices, get_crypto_daily, get_economic_data), Articles archive.

Workflow: get_macro_snapshot (US) → get_imf_global_outlook (global) → get_ecb_snapshot + get_bis_snapshot (Europe/global finance) → drill into specific areas per task → search articles for qualitative commentary.

Output: Macro Regime Assessment (Growth / Inflation / Policy / Credit classifications), Key Indicators table with trends, Regional Outlook (US, Euro Area, China, EM), Risks & Watchpoints, Data Quality Notes.


geopolitical_risk (Haiku 4.5)

Role: Geopolitical risk analyst — assesses how political events and international tensions affect financial markets.

Tools: NewsAPI* (get_geopolitical_news, get_central_bank_news, search_news, get_finance_news_snapshot), GDELT (search_gdelt_news, get_gdelt_sentiment, get_gdelt_coverage_volume, get_gdelt_geo_news), NewsData.io (search_newsdata, get_newsdata_market, get_newsdata_crypto, get_newsdata_sources), Articles archive (search_articles, get_article_summaries, get_article — max 2 full reads).

* NewsAPI disabled by default; GDELT + NewsData.io serve as replacements.

Performance budget: ≤ 8 tool calls total.

Workflow: Geopolitical headlines → central bank news → targeted topic searches → article summaries (prefer over full text).

Output: Geopolitical Risk Register (probability × impact × timeframe × affected assets table), Risk Detail (description, trigger signals, transmission mechanism, affected sectors, historical analogue, hedging implications), Geopolitical Sentiment (risk level, direction, key uncertainty), Central Bank Watch.


equity_analyst (Sonnet 4.6)

Role: Senior equity research analyst — synthesises all prior agent output into a rigorous investment thesis with valuation and recommendation.

Tools: FMP (quote, profile, financials, metrics, ratios, analyst data, DCF, earnings transcripts, research bundle), FRED (yield curve, credit conditions, real rates, any series), SEC EDGAR (company facts, submissions, concept time series, full-text filing search), OpenFIGI (identifier mapping, search).

Inputs: News briefing, market data, macro assessment, geopolitical risk register.

Workflow: Review all context → fetch missing data → build thesis → cross-check conclusions against data.

Output: Business Quality Assessment (moat, revenue quality, capital allocation, management), Financial Analysis (growth, margins, balance sheet, FCF, capital returns), Valuation Assessment (DCF + relative methods → blended fair value), Investment Thesis (recommendation, fair value range, conviction), Key Catalysts, Risk Factors.


swing_trading_analyst (Sonnet 4.6)

Role: Institutional-level swing trading analyst — top-down analysis for 1–3 day trades in US equities/ETFs with concrete entry/stop/target.

Tools: FMP (quotes, price history, technicals, sector performance, market movers, profiles, metrics, ratios), FRED (macro snapshot, financial stress, yield curve, real rates, leading indicators), NewsAPI* (search, market headlines), GDELT (search_gdelt_news), NewsData.io (search_newsdata), Alpha Vantage (get_commodity_prices, get_forex_daily).

* NewsAPI disabled by default; GDELT + NewsData.io serve as replacements.

Performance budget: ≤ 8 tool calls total.

Workflow (strict 9-step process): 1. Market Context — index trend, VIX, rates → Risk ON/OFF/CHOP 2. Geopolitics + News — wars, macro events, earnings 3. Sector & Industry Rotation — relative strength 4. Sentiment / Positioning — crowd positioning 5. Technical Analysis — structure, key levels, indicators, patterns 6. Trade Decision — LONG or SHORT (no hedging) 7. Execution — exact entry, stop, target, risk %, R:R 8. Invalidation — price/condition that cancels trade 9. Final Trade Summary block

Output: Ends with a clean trade card:

TRADE: LONG / SHORT
TICKER: ___
ENTRY / STOP / TARGET: $___
R:R = ___
PROBABILITY: _/5

macro_liquidity_analyst (Sonnet 4.6)

Role: Macro-liquidity regime analyst — scores liquidity conditions from FRED data, classifies the regime, and explains asset-class implications.

Tools: Macro Liquidity (get_macro_liquidity_score, get_liquidity_regime, explain_liquidity_for_asset, generate_macro_liquidity_report), FRED supplementary (get_interest_rates, get_credit_conditions, get_money_supply, get_macro_snapshot).

Performance budget: ≤ 6 tool calls total.

Workflow (strict 5-step process): 1. Liquidity Score — composite score (-3 to +3) with 4-pillar breakdown (real rates, central bank balance sheet, credit impulse, funding stress) 2. Context — yield curve shape, credit spread direction, rate stance 3. Asset Implications — per asset class (equities, bonds, commodities, crypto) 4. Regime Change Signals — components near thresholds, leading indicators 5. Summary block

Output: Ends with a clean regime card:

LIQUIDITY REGIME: ___
COMPOSITE SCORE: ___ (-3 to +3)
DIRECTION: Improving / Stable / Deteriorating
ASSET POSITIONING: Equities / Bonds / Commodities / Crypto
REGIME CHANGE RISK: Low / Medium / High

scenario (Sonnet 4.6)

Role: Scenario analyst — constructs probability-weighted bull/base/bear scenarios grounded in valuation frameworks.

Tools: None (pure reasoning from prior agent context).

Inputs: Equity analyst thesis + all Phase 1 data.

Output: Scenario Summary table (probability, target price, return, key driver), detailed Bull/Base/Bear cases (thesis, key assumptions for revenue/margins/multiples, triggers, signposts), Risk/Reward Assessment (EV vs. price, skew, tail risk, optionality).

Constraints: Probabilities sum to 100%. Base case is most probable (40–60%). Scenarios are internally consistent. Target prices grounded in DCF / multiples.


critic (Sonnet 4.6)

Role: Devil's advocate and quality controller — stress-tests the full analysis for weaknesses.

Tools: None (pure reasoning from prior agent context).

Inputs: All prior agent outputs (news, market data, macro, geopolitical risk, equity thesis, scenarios).

Output: Assumption Challenges table (assumption, challenge, severity), Data Quality Concerns (stale, missing, contradictions, sample bias), Analytical Gaps, Counter-Arguments, Bias Check (anchoring, recency, confirmation, narrative, consensus), Confidence Assessment table (data quality, analytical rigour, valuation range, scenario completeness → overall), Recommendations for Improvement.


report_writer (Sonnet 4.6)

Role: Financial report writer — synthesises all agent outputs into a single, polished, reader-friendly markdown report.

Tools: None (pure writing from prior agent context + critic feedback).

Writing style: ADHD-friendly, non-technical. Lead with the bottom line, short paragraphs (2–3 sentences), plain English, liberal bullet points, bold key takeaways, analogies for context, small tables with emoji trend/signal indicators (🟢🔴🟡⬆️⬇️➡️⚠️✅❌📊).

Templates by mode: - equity_deep_dive (1500–2500 words) — The Big Picture, What the Stock Is Doing, The Business, The Numbers That Matter, What's It Worth, What Could Go Right/Wrong, Risks to Watch, The Bigger Picture, What People Are Saying, Fine Print. - market_brief (500–1000 words) — The One-Minute Version, Markets at a Glance, Winners & Losers, The Economy Right Now, What Could Shake Things Up. - macro_outlook (1000–1800 words) — Bottom Line, Growth, Inflation & Interest Rates, Around the World, Political & Geopolitical Risks, What This Means for Investing. - news_digest (400–800 words) — The Headlines That Matter, What's Moving Prices, Worth Watching.

Incorporates critic feedback in the fine print. Report stands alone without needing raw agent outputs.