Salzburg: Agentic Portfolio Risk Analyst

Built for the Amazon Nova Hackathon

A grounded portfolio risk copilot for real investors.

Markets move on narratives, but most portfolio tools still speak in spreadsheets. Salzburg turns holdings, live quotes, headlines, fundamentals, earnings, institutional ownership, and macro signals into an evidence-backed portfolio risk investigation that ordinary investors can actually follow.

Salzburg is not a free-form investing chatbot. It is a bounded, agentic risk copilot built around Amazon Nova 2 Lite. Nova plans what to inspect, selects bounded tools, verifies which findings are actually supported, simulates one-step portfolio changes, rejects unsafe proposals, and synthesizes the final verdict.

The result is a system that can explain why a portfolio is risky right now, what changed since the last run, which claims are evidence-backed versus weak inference, what happens if one holding or one weight changes, and which proposal is actually safer after simulation.

Inspiration

Salzburg came from a simple frustration: portfolio tools are usually good at showing numbers and bad at explaining risk.

Investors can often feel that a portfolio has become crowded, fragile, or overexposed, but the tools they use rarely help with the next layer of reasoning. They show prices, charts, and weights, but they do not help users understand the actual source of risk, what changed, which claims are grounded, or what a safer bounded move would look like after simulation.

I wanted to build something that behaves less like a dashboard and more like a disciplined risk editor: investigate the portfolio, ground the findings, test one bounded change at a time, and explain the result in plain language.

What Salzburg Does

  • Agentic portfolio investigation
    Nova runs a bounded investigation loop over the portfolio: plan -> fetch -> verify -> synthesize.

  • Deterministic score, AI explanation
    The portfolio risk score is computed by a rules-based engine. Nova does not invent the score. It explains and prioritizes what matters around it.

  • Evidence-backed claims
    Findings are tied to fetched evidence. If data is stale, partial, or missing, Salzburg degrades gracefully instead of bluffing.

  • Safe bounded proposals
    Salzburg proposes one bounded portfolio change at a time, simulates it, and rejects unsafe or worsening moves before they ever reach the apply flow.

  • Interactive analyst chat
    Users can ask follow-ups, request fresh news, test what-if scenarios, explore candidate replacements, and apply one validated proposal at a time.

  • What-changed intelligence
    Salzburg can explain what changed after a proposal and what changed since the previous investigation, instead of forcing the user to compare snapshots manually.

  • Inline narrated brief
    Users can ask for an audio brief in chat and play it directly in the same screen.

Why This Is Agentic

Salzburg is not a generic chatbot wrapped around market data.

  • Nova chooses from a bounded tool set instead of answering from scratch.
  • The system executes those tools and streams what happened.
  • A verifier pass checks which findings survive.
  • Portfolio changes are bounded, simulated, and only applied after confirmation.
  • Unsafe proposals are rejected before they are shown as actionable.

That means Salzburg uses AI to make investigation decisions inside a constrained workflow, not just to decorate a static report.

How I Built It

Salzburg is a split system with a deterministic risk core and an agentic orchestration layer on top.

Frontend

The frontend is an Android app built with Kotlin and Jetpack Compose.

It provides:

  • a chat-first analyst experience
  • focused workspaces for signals, evidence, portfolio structure, actions, and factors
  • NDJSON streaming for both investigation and follow-up chat
  • inline Amazon Polly playback for narrated briefs

Backend

The backend runs on AWS Lambda using a streamed Python ASGI setup behind Lambda Web Adapter.

It exposes:

  • POST /investigate/stream
  • POST /chat/stream
  • GET /health

Core architecture

  • Deterministic risk engine
    Computes the portfolio risk score independently from the LLM.

  • Bounded proposal engine
    Generates one-step proposal candidates, simulates them, scores them, and rejects unsafe or worsening moves.

  • Amazon Nova 2 Lite
    Plans, verifies, synthesizes, and explains the investigation.

  • Alpha Vantage MCP integration
    Fetches quotes, headlines, fundamentals, earnings, institutional holdings, and macro indicators.

  • Amazon Polly
    Generates narrated brief playback directly inside the app.

  • Security and trust controls
    HMAC request signing, optional Play Integrity, bounded proposal validation, and explicit degradation behavior when evidence is weak.

How Amazon Nova is used

Amazon Nova 2 Lite is part of the shipped core flow, not a side feature.

  • Nova plans the investigation by selecting which bounded tools should run.
  • Nova verifies candidate findings and rejects weak or unsupported claims.
  • Nova synthesizes the final verdict, drivers, and action path from the deterministic baseline and fetched evidence.
  • Nova powers the conversational follow-up layer on top of the latest portfolio analysis.
  • Nova explains the surviving bounded portfolio proposal after deterministic simulation and validation.
  • Nova is also used for structured brief generation when the user asks for a narrated summary.

In Salzburg, Nova is strongest where model judgment actually matters:

  • planning
  • verifying
  • synthesizing
  • explaining

The deterministic layer owns the score and safety-sensitive proposal logic.

Challenges I Faced

The hardest challenge was making the system useful without letting it become careless.

  • Grounding
    A system like this becomes dangerous quickly if it sounds confident without enough support. I had to make sure findings stay tied to evidence, weak claims can be rejected, and the final answer remains honest when data is partial or stale.

  • Proposal safety
    I did not want Salzburg to behave like a free-form portfolio optimizer. I scoped it as a risk copilot. That meant bounding proposal types, simulating every proposal first, and refusing “safer” moves that actually worsen score or concentration.

  • Latency and UX
    A user should not tap investigate and stare at a frozen screen. I solved that by streaming the analyst loop live so planning, tool execution, verification, and synthesis are visible as they happen.

  • Trust boundaries across follow-up chat
    It was not enough to generate smart answers. The system also had to remember proposal state correctly, explain what changed after apply, and keep that flow deterministic across reruns.

  • Narration inside the product
    I wanted the audio brief to feel native to the conversation, not like an export button, so I built playback directly into the chat experience.

What I Learned

The strongest AI products in this space are not the ones that let the model do everything. They are the ones that give the model the right job.

In Salzburg:

  • the deterministic layer owns the risk score
  • the bounded proposal engine owns simulation and safety checks
  • Nova owns planning, verification, synthesis, and explanation

That separation made the system more trustworthy, easier to debug, and much easier to defend technically.

I also learned that agentic products are as much about orchestration and UX as they are about model output. Streaming, fallback behavior, refusal handling, memory hygiene, and transparent evidence matter just as much as the text itself.

What I’m Proud Of

I’m proud that Salzburg is not just a one-shot LLM wrapper around market data.

It is a structured, streamed system with:

  • deterministic scoring
  • evidence-aware verification
  • bounded what-if simulation
  • safe refusal behavior
  • mobile-first UX
  • inline narrated brief playback

It does not just sound intelligent. It behaves in a way that is grounded, legible, and disciplined.

Why It Matters

Salzburg is designed to create value in two ways.

Enterprise impact

The system can help advisors, analysts, and portfolio operators reduce the time needed to understand:

  • where portfolio fragility comes from
  • what changed since the last run
  • which claims are actually supported
  • which bounded move is worth considering next

That makes it useful as a decision-support layer, not just a reporting tool.

Community impact

For individuals, Salzburg makes portfolio risk more understandable. It turns opaque market context into something legible, explainable, and easier to act on responsibly.

Core User Flow

  1. Create or load a portfolio in the Android app.
  2. Tap Investigate Portfolio.
  3. Salzburg streams the analyst loop live: planning, tool execution, verification, and synthesis.
  4. Review the verdict, main driver, and action path.
  5. Ask follow-up questions in chat.
  6. Test one bounded portfolio change at a time.
  7. See the simulated impact before applying it.
  8. Ask for a narrated brief and play it inline.

What’s Next

  • scheduled morning portfolio editions
  • deeper cross-run change tracking
  • multi-proposal comparison workflows
  • broker integrations for practical rebalance workflows
  • multilingual reporting and narrated briefs

Note

Salzburg is an informational portfolio risk investigation tool. It is not investment advice.

Built With

  • alpha-vantage-mcp
  • amazon-bedrock
  • amazon-nova
  • amazon-polly
  • android
  • aws-lambda
  • jetpack-compose
  • kotlin
  • python
  • retrofit
Share this project:

Updates

posted an update

We shipped a big post-hackathon reliability pass for Salzburg.

The headline change is that Salzburg now handles portfolio proposals much more cleanly end to end. We tightened the Nova agent loop, moved proposal handling onto a safer seed-based contract, and fixed the “apply and rerun” flow so the app can explain what changed after a rebalance instead of losing that state on refresh.

We also made chat feel more grounded. Clarified requests like “make this safer” are much more likely to turn into a real bounded rebalance, candidate exploration now carries forward into later actions, and stale proposal memory is no longer leaking into follow-up answers.

On the client side, we updated the Android app to materialize proposal changes locally from the active portfolio, improved the inline brief UX, and made Polly narration degrade more gracefully when speech marks are unavailable.

Under the hood, this branch adds a lot more regression coverage across backend orchestration, memory reconciliation, proposal validation, and demo flows. Salzburg is still the same risk copilot, but it is now much safer, more explainable, and more reliable in live interaction.

Log in or sign up for Devpost to join the conversation.