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 | 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.
localStorage.Authorization: Bearer <key>. SSE and
window.open calls pass the key as a ?token= query parameter instead.Job scoped to the tenant, runs the pipeline
in a background thread, and streams progress events back via SSE.reports/{tenant_id}/ with metadata and a log file.
Usage (tokens, cost, elapsed time) is recorded in .data/tenants.db.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).
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 |
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.
Each user is a tenant with an isolated data namespace:
Authorization header. Tokens are
secrets.token_urlsafe(32) stored in SQLite.reports/{tenant_id}/. Each tenant only sees their
own reports.jobs dict is filtered by tenant_id.reports/*.md files are moved
into the default admin tenant's directory. A .data/.migrated sentinel prevents
re-running.Stripe integration exists for subscription checkout and management but can be
disabled via STRIPE_CHECKOUT_ENABLED=false in .env. When disabled:
/stripe/checkout) returns a 400 error./api/request-upgrade.Admins can manually assign plans via the admin panel or CLI
(python tenants.py set-plan user@example.com pro).
.
├── 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
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.
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.
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.
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.
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.
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.
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.
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
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
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.
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.
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.