FinSight Agent is a full-stack investor research workflow:
- React frontend sends a finance question to FastAPI.
- FastAPI validates and guards the question, optionally exposes the plan, and coordinates specialist research agents.
- Amazon Bedrock powers a multi-agent pipeline: Amazon Nova Pro plans the run and synthesizes the final report, while Amazon Nova Lite writes specialist analysis sections.
- Market data, price history, and recent headlines are prefetched before agent execution.
- The backend returns normalized JSON for the UI or deterministic PDF bytes for download.
This repository is intentionally structured so new contributors can extend it without having to load the entire codebase into context first.
Current request flow:
Frontend -> /analyze/plan (optional) or /analyze -> guardrails -> analysis_service -> planner -> data_prefetcher -> selected specialist agents (parallel) -> report agent -> JSON response
/analyze/pdf can either run the same full pipeline from a question or render a cached report object directly into PDF bytes.
Separation of concerns:
backend/app/main.py: API wiring onlybackend/app/schemas/: request and response contractsbackend/app/agents/: planner, orchestrator, report synthesis, and specialist agent definitionsbackend/app/tools/: external data collectionbackend/app/services/: request-level coordination, integrations, guardrails, and output generationfrontend/: React UI scaffold and API clientbackend/app/config.py: environment-driven settings, loadsbackend/.env
POST /analyze/planor the internal planner chooses entities, specialist agents, and report style.backend/app/tools/data_prefetcher.pyinspects the selected agents'required_dataand fetches only the needed metrics, headlines, and price history in parallel.backend/app/agents/orchestrator.pybuilds a sharedAgentContextand runs the selected specialists in parallel withThreadPoolExecutor.backend/app/agents/report_agent.pysynthesizes the specialist outputs into a normalized report dict.backend/app/services/pdf_service.pyrenders that report deterministically without any extra Bedrock or data-fetch calls.
Current specialist agents:
news_sentimentfundamental_analysisrisk_assessmentpeer_comparisontechnical_analysismarket_contextwealth_strategyincome_strategyfinancial_education
finsight-agent/
├── AGENTS.md
├── README.md
├── backend/
│ ├── requirements.txt
│ ├── .env.example
│ ├── tests/
│ │ ├── test_analysis_fallbacks.py
│ │ ├── test_analysis_service.py
│ │ ├── test_data_prefetcher.py
│ │ ├── test_input_guardrails.py
│ │ └── test_main_error_handling.py
│ └── app/
│ ├── main.py
│ ├── config.py
│ ├── agents/
│ │ ├── base_agent.py
│ │ ├── planner_agent.py
│ │ ├── report_agent.py
│ │ ├── orchestrator.py
│ │ ├── news_agent.py
│ │ ├── fundamentals_agent.py
│ │ ├── risk_agent.py
│ │ ├── comparison_agent.py
│ │ ├── technical_agent.py
│ │ ├── market_context_agent.py
│ │ ├── wealth_strategy_agent.py
│ │ ├── income_strategy_agent.py
│ │ ├── education_agent.py
│ │ ├── registry.py
│ │ └── shared.py
│ ├── schemas/
│ │ └── analysis.py
│ ├── services/
│ │ ├── analysis_service.py
│ │ ├── bedrock_service.py
│ │ ├── errors.py
│ │ ├── input_guardrails.py
│ │ └── pdf_service.py
│ └── tools/
│ ├── data_prefetcher.py
│ ├── finance_tools.py
│ └── search_tools.py
├── frontend/
└── scripts/
These rules keep the backend extensible:
- Keep API handlers thin.
- Put request/response models in
backend/app/schemas/, not inside route files. - Keep orchestration in
backend/app/agents/; avoid letting route handlers call tools directly. - Put provider-specific code in
backend/app/services/orbackend/app/tools/, never scattered across agent modules. - Extend the analysis result by adding fields in one place first:
backend/app/schemas/analysis.py. - Prefer adding new modules over growing one large file.
backend/tests/covers service fallbacks, guardrails, prefetching, and FastAPI error handling.- Prompt logic still lives with the agents and services; add
backend/app/prompts/if prompt templates need versioning or become hard to review.
Returns:
{ "status": "ok" }Request:
{
"question": "Compare Nvidia and AMD for a long-term investor"
}Optional planned execution:
{
"question": "Compare Nvidia and AMD for a long-term investor",
"plan": {
"entities": [
{ "company_name": "NVIDIA", "ticker": "NVDA" },
{ "company_name": "Advanced Micro Devices", "ticker": "AMD" }
],
"agents": [
{ "agent_id": "peer_comparison", "task": "Compare the two companies." },
{ "agent_id": "fundamental_analysis", "task": "Assess relative fundamentals." }
],
"report_style": "comparison"
}
}Response:
{
"title": "Comparative Financial Analysis: Compare Nvidia and AMD for a long-term investor",
"summary": "string",
"sections": [
{
"title": "Peer Comparison",
"agent": "peer_comparison",
"content": "string"
}
],
"verdict": "string",
"entities": [
{ "company_name": "NVIDIA", "ticker": "NVDA" },
{ "company_name": "Advanced Micro Devices", "ticker": "AMD" }
],
"warnings": [],
"orchestration": [
{
"step_id": "planner",
"label": "Planner",
"status": "completed",
"task": "Selected the best specialist agents for the question."
}
],
"pdf_meta": {
"report_style": "comparison",
"entities": [],
"specialists": [],
"headlines": [],
"warnings": []
}
}Request:
{
"question": "Compare Nvidia and AMD for a long-term investor"
}Response:
{
"entities": [
{ "company_name": "NVIDIA", "ticker": "NVDA" },
{ "company_name": "Advanced Micro Devices", "ticker": "AMD" }
],
"agents": [
{ "agent_id": "peer_comparison", "task": "Compare the two companies." },
{ "agent_id": "fundamental_analysis", "task": "Assess relative fundamentals." }
],
"report_style": "comparison"
}Returns application/pdf.
Two supported request shapes:
Generate a fresh report from a question:
{
"question": "Compare Nvidia and AMD for a long-term investor"
}Or render a cached analysis response directly to PDF:
{
"report": {
"title": "Comparative Financial Analysis: Compare Nvidia and AMD for a long-term investor",
"summary": "string",
"sections": [],
"verdict": "string",
"entities": [],
"warnings": [],
"orchestration": [],
"pdf_meta": {}
}
}If a cached report is provided, question may be omitted.
- Question guardrails run before planning and analysis.
- Guardrail failures return HTTP
422with a structured detail object. - Service failures return structured error payloads instead of raw tracebacks.
Example guardrail error:
{
"detail": {
"code": "out_of_scope",
"message": "FinSight only accepts genuine finance, investing, or market questions.",
"suggested_question": "Compare Nvidia and AMD for a long-term investor",
"category": "scope"
}
}# 1. one-time setup (venv + pip + npm)
./scripts/dev_setup.sh
# 2. fill in AWS credentials
# edit backend/.env
# 3. start backend (terminal 1)
./scripts/dev_backend.sh # → http://localhost:8000
# 4. start frontend (terminal 2)
./scripts/dev_frontend.sh # → http://localhost:5173From the repo root:
./scripts/dev_setup.sh
./scripts/dev_backend.sh
./scripts/dev_frontend.shOptional env overrides:
PORT=8010 ./scripts/dev_backend.shFRONTEND_PORT=5174 ./scripts/dev_frontend.sh
Required:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_DEFAULT_REGIONBEDROCK_MODEL_ID
Optional:
BEDROCK_RESEARCH_MODEL_IDAPP_ENVFRONTEND_ORIGIN
Defaults from backend/.env.example:
AWS_DEFAULT_REGION=us-east-1BEDROCK_MODEL_ID=amazon.nova-pro-v1:0BEDROCK_RESEARCH_MODEL_ID=amazon.nova-lite-v1:0APP_ENV=developmentFRONTEND_ORIGIN=http://localhost:5173
- Use
us-east-1unless you have confirmed another enabled region. - Confirm Amazon Nova model access in the Bedrock console before debugging code.
- Bedrock calls use the
bedrock-runtimeconverseAPI throughbackend/app/services/bedrock_service.py. BEDROCK_MODEL_IDis used for JSON-producing planner and report-agent calls.BEDROCK_RESEARCH_MODEL_IDis used for plain-text specialist agent sections.- The current default split is
amazon.nova-pro-v1:0for planning and synthesis, andamazon.nova-lite-v1:0for specialist research.
The React scaffold lives in frontend/README.md.
Default local split:
- backend:
http://localhost:8000 - frontend:
http://localhost:5173
If you are an AI coding agent, read AGENTS.md first.