Inspiration

Sell-side equity research has a structural honesty problem: a bank that wants to keep covering a company — and keep its banking relationship — rarely publishes a "Sell." The bearish case doesn't disappear; it just never gets written down. At the same time, the current wave of "AI equity research" tools mostly amounts to a chatbot that will confidently tell you a stock's fair value with no citation, no audit trail, and a number that was never actually computed — just predicted as the next plausible token.

We wanted to build the opposite of both of those things: a research pipeline that is forced to be bearish at least once, where every claim is traceable to a filing, and where every number on the page was produced by code, not by an LLM guessing digits. The name ghost.reviews comes from that idea — it's the review that got buried, brought back.

What it does

You give ghost.reviews a one-paragraph brief — "Initiate coverage on Apple, focus on whether the AI-enabled product cycle reaccelerates growth, comps against Samsung/Google/Qualcomm, 5-year model." From there, the pipeline runs end to end with no further input until a human sign-off gate at the very end:

  1. Plan — a planner agent turns the brief into a structured set of research objectives and a list of extraction prompts, which the analyst reviews before anything runs.
  2. Collect (Layer ①) — a retrieval + parsing pipeline pulls the relevant SEC filings (10-K, 10-Q, 8-K, DEF 14A, and FPI equivalents) and builds a matrix: rows are documents, columns are narrow extraction prompts, and each cell is one cited fact — "10-K p.42: revenue $12.0B."
  3. Aggregate — the matrix collapses into a structured, computable fact set: a revenue series, margins, share count, comparable multiples, and a list of qualitative risk signals.
  4. Analyze (Layer ②) — numbers go to deterministic code, never to an LLM doing arithmetic. The code runs a multi-year forecast, a DCF, comparable-company multiples, and a sensitivity table. Qualitative signals (management turnover, regulatory exposure, subsidy rollbacks) go to an analyst agent that judges what they mean and adjusts the assumptions feeding the model — it never touches the math directly.
  5. Reflect — an adversarial agent attacks the resulting thesis: builds the strongest bear case, checks for optimism bias, and verifies that the price target actually traces back to the stated assumptions and that every claim is cited. If it fails, the case gets pushed back into the queue for re-collection or re-analysis.
  6. Human gate — the analyst sees the thesis and the full reflection transcript, and approves or overrides the rating and price target. Nothing ships without this.
  7. Report — an Excel model and a PDF/HTML report are rendered from the final, signed-off case.

How we built it

The system is organized as a supervisor with an operation queue sitting on top of five independent agent blocks (planner, matrix/data collection, analyst, reflection, report), each with its own module (plannerAgent, matrixBlock, analystBlock, reflectionAgent, reportBlock). State for an entire research run lives in a single Case object — plan, matrix, fact set, analyst view, reflection history, and report — that the supervisor mutates incrementally as work completes, so a reflection failure can re-trigger just the affected step instead of starting over.

The valuation core is plain code, by design. The DCF discounts projected free cash flows at WACC and adds a terminal value:

$$ EV = \sum_{t=1}^{n} \frac{FCF_t}{(1+WACC)^t} + \frac{TV_n}{(1+WACC)^n}, \qquad TV_n = \frac{FCF_n (1+g)}{WACC - g} $$

and the comps path produces a multiple-based target, e.g. $PT_{\text{comps}} = EPS_{\text{fwd}} \times \overline{P/E}{\text{peers}}$. The agent's only job in this loop is to _set the inputs ($g$, $WACC$, peer multiples) based on what it read in the filings — the arithmetic is deterministic and reproducible every time.

On the front end, we built a Next.js console that streams the supervisor's state over ND-JSON in real time — you can watch the plan get drafted, the matrix fill in cell by cell with citations, the valuation compute, and the reflection debate happen live. We also built a replay mode that snapshots a completed real run (AAPL, NVDA) so the whole pipeline can be demoed without needing the backend running.

Challenges we ran into

  • Keeping the LLM out of the arithmetic. It's tempting to let the model "just compute the DCF" — it's faster to prototype and looks fine until the numbers are subtly wrong in a way that's invisible without re-deriving them by hand. We had to draw a hard line: the agent extracts assumptions, code does math.
  • Citation grounding at scale. Every cell in the matrix needs a real filing, page, and quote behind it — which meant building real retrieval/parsing over EDGAR documents rather than relying on a model's memory of a company's financials.
  • Tuning the reflection loop. An adversarial agent that's too lenient is a rubber stamp; one that's too strict loops forever. We capped reflection at two rounds with an explicit checklist (target traces to assumptions, every claim cited, bear case genuinely engaged) and an escalation path to the human gate if it can't converge.
  • Streaming multi-agent state to a UI. The supervisor's operation queue can branch and re-run steps mid-flight, so the frontend needed a single, consistent snapshot shape (CaseSnapshot) that's valid at any point in the run — not just at the end.
  • Demoing without a live backend. Turning a completed Case (a flat persisted dump) into the nested shape the live-streaming UI expects, so a real run could be replayed standalone, took a dedicated transform step.

Accomplishments that we're proud of

  • A fully working end-to-end run on real companies (Apple, NVIDIA) — real SEC filings in, a cited matrix, a code-computed DCF and comps valuation, an adversarial reflection pass, and a finished Buy/Hold/Sell report out.
  • Zero LLM-computed numbers anywhere in the valuation — every figure on the price target traces back through code to a cited filing.
  • A live, streaming console that makes the usually-invisible "thinking" of an agent pipeline — planning, retrieval, cell-by-cell extraction, reflection — visible and inspectable in real time.

What we learned

The biggest lesson was architectural: separating "what does this mean" (LLM judgment) from "what is the number" (deterministic code) isn't just safer, it's what makes the system debuggable. When a price target looks wrong, you can point at the exact assumption an agent set, rather than re-running an opaque end-to-end generation and hoping for a different number. We also learned how much an explicit adversarial step changes the character of the output — forcing a bear case to be written, not just permitted, surfaces risks that a single "write me a research report" prompt reliably skips.

What's next for ghost.reviews

  • Expand Layer ① beyond 10-K/10-Q/8-K/DEF 14A to earnings call transcripts and structured XBRL data for tighter financial extraction.
  • Support multi-company comps runs natively, so the comps table is built from the same pipeline rather than hand-specified peers.
  • Let the human gate edit assumptions inline and re-run just the valuation, instead of only approving/overriding the final number.
  • Deploy the pipeline backend so the live /console (not just replay) is available from the hosted demo.

Built With

Share this project:

Updates

Submission history