Inspiration

A venture studio partner told us about a company he passed on because the product was unclear. A year later, they had built exactly what he'd asked for, and he never went back.

That isn't a one-off. The average VC firm screens about 200 companies a year and invests in about 4 (Gompers et al., Journal of Financial Economics, 2020). Most of those no's really mean "not yet": pre-product, no enterprise customers, too early on revenue. The reason gets typed into a CRM field and nobody reads it again. That happens across roughly 2,984 US VC firms (NVCA 2026 Yearbook).

A second interview, with a founder-side operator, changed the design. Going back to a founder you passed on can feel awkward. Sometimes the better move is to find a comparable company that has already cleared the same bar. That became our second view.

Affinity remembers why you said no. 2ndLook tells you when that reason stops being true, with dated proof.

What it does

A fund connects Affinity, or uploads a document. 2ndLook then re-reads every deal the fund passed on, checks whether the specific reason for each pass has since been disproven by dated public evidence, and ranks which companies deserve a call back.

Two views:

  • Anti-Portfolio: deals you passed on whose original risks now look cleared.
  • Comps: new companies like the ones you passed on that have already cleared the same risk.

For each deal, 2ndLook produces:

  • A one-page re-underwrite memo, with the original pass reason on the left and dated proof on the right
  • A re-engagement note that leads with the founder's progress and never mentions why you passed
  • An .ics calendar invite, a deal lead, a follow-up date, and the status written back to Affinity

There's also a founder-facing milestone tracker, where founders submit their own proof. Roundtable bot detection protects it.

How we built it

Stack: Next.js 15, React, TypeScript, Tailwind CSS 4, Zod, Supabase (Postgres), Vitest, Node 22, deployed on Vercel.

Pipeline:

  1. Ingest. Pull passed deals and each partner's free-text pass note from the Affinity API v2.
  2. Parse the "no." A model call turns each note into 1–3 of 7 risk codes, plus the traits the partner liked: PRE_PRODUCT · NO_ENTERPRISE_CUSTOMERS · TOO_EARLY_REVENUE · TEAM_GAP · GTM_UNPROVEN · MARKET_SIZE · ROUND_DYNAMICS
  3. Gather evidence. For each company, akta.pro by Wokelo runs company search, pulls news published since the pass date, and fetches enrichment sections. Hacker News (Algolia) serves as a free supplementary source, and SEC EDGAR is also referenced.
  4. Label with receipts. Each piece of evidence is labeled supports, contradicts, or irrelevant, and the model must quote the source word for word. lib/quoteCheck.ts normalizes whitespace and quote marks, then requires an exact substring match. If the quote isn't found, the evidence is forced to irrelevant. No quote, no proof.
  5. Rules decide the verdict, not the model. lib/scoring.ts is a set of pure, unit-tested functions. They return one of DERISKED, PARTIAL, OPEN, NO_COVERAGE, or PARTNER_CALL. Evidence strength $s$ for a proof point is:

$$ s = \begin{cases} 1.0 & \text{company is the article's primary subject AND event type matches the risk} \ 0.6 & \text{otherwise} \ 0 & \text{published before the pass date} \end{cases} $$

MARKET_SIZE is always a PARTNER_CALL. That one needs human judgment.

  1. Rank. The conviction score is always shown broken into its parts, never as a single unexplained number:

$$ \text{Conviction} = 0.5 \cdot \text{De-risking} + 0.3 \cdot \text{Thesis fit} + 0.2 \cdot \text{Traction} $$

Sponsor tools: | Tool | Role | |---|---| | akta.pro (Wokelo) | Company search, news since the pass date, enrichment. This is the core external evidence source. | | Nicrron | AI gateway for every model call: temperature 0, pinned models, responses cached by prompt hash | | PRISM by Block Convey | Wired to trace the evidence-labeling calls, viewable on our /audit page | | Roundtable | Bot detection on the founder-facing milestone tracker |

Data integrity: The 30 companies are real, so the akta.pro evidence is real. The fund ("Harbor Street Ventures"), its partners, and every pass note are synthetic, as the event rules required. Pass dates run from May to October 2025. Every proof point carries a source, a link, and a date after the pass date.

Challenges we ran into

  • The docs were a starting point, not a spec. Logging response bodies turned HTTP status codes into documentation. 307 responses meant the endpoints needed trailing slashes. A 422 named the wrong parameter: Company Search takes query, not domain. Enrichment wanted company plus sections. Then came 402 Insufficient credits. News cost about 0.2–0.35 credits per call and enrichment about 2.0. We ran out, so our 12 comps were built from data we had already prefetched rather than live calls.
  • Searching by name silently returns the wrong company. Querying decagon.ai returns four companies named Decagon: the real one, plus Decagon Devices (decagon.com) and Decagon Institute. Our client took the first result. That bug never crashes. It just attaches a stranger's news to your deal and calls it proof. We now require an exact domain match and return "No coverage" rather than guess.
  • A scoring dead end hidden in plain sight. Full-strength proof needed both a primary-subject match and a matching event tag, but the news payload carried no tags. Every proof point was capped at partial, so no deal could ever reach "De-risked," which is the whole product. We now derive the event match from the article text.
  • A shape mismatch that would have silently blanked the UI. Nothing errored; the page would simply have rendered empty.
  • Flaky transport. api.akta.pro sometimes timed out, reset connections, or failed TLS handshakes, even on domains that had just succeeded. One blip silently dropped a deal from a 30-company batch. Transport failures now retry with backoff, behind a 20-requests-per-minute throttle.

Accomplishments that we're proud of

  • Real evidence on real companies: 413 proof candidates distilled into 61 labeled proof points across the 30-company ledger. Our hero deal, Decagon, has 7 dated proof points.
  • Proof that can't be made up: every proof point is verified against an exact quote from its source, or it's thrown out.
  • A model that advises but doesn't decide: verdicts come from deterministic rules covered by 28 passing tests (18 for scoring, 10 for quote verification).
  • Honest failure modes: when we can't find coverage, 2ndLook says "No coverage" rather than guessing.

What we learned

  • Silent failures are worse than crashes. The wrong-company match, the missing event tags, the dropped batch item, and the blank UI all "worked" while being wrong.
  • In finance, the model should argue and the rules should decide. Exact-quote checks plus deterministic scoring make every verdict traceable back to a dated sentence.
  • Coverage is a real limit. Only 9 of our 30 deals had qualifying proof inside akta.pro's roughly 187-day news window and our credit budget. Showing "No coverage" honestly beats padding the ranking.
  • Talk to the user first. The Comps view came straight out of an operator interview, not our original plan.

What's next

  • Scheduled re-checks, so a deal turns green the day its pass reason stops being true
  • Deeper evidence: more filing types, hiring signals, and product launches beyond news
  • More CRMs beyond Affinity
  • Alerts sent to the partner who originally passed on the deal
  • A full PRISM audit trail for every run

Built With

  • affinity-api
  • akta.pro
  • hacker-news-api
  • next.js
  • nicrron
  • node.js
  • postcss
  • postgresql
  • prism-by-block-convey
  • react
  • roundtable
  • sec-edgar
  • supabase
  • tailwindcss
  • typescript
  • vercel
  • vitest
  • zod
Share this project:

Updates

Submission history