SignalScout: källbelagd outreach, eller ett tomt fält

Ett B2B-researchverktyg som gör en CSV med leads till öppningsrader för kalla mejl, var och en med käll-URL, datum och tillförlitlighetsnivå. När det inte vet säger det ingenting.

Kund
Nuits
År
2026
Status
Live
Roll
Ensam grundare, Produktdesign, Utveckling, AI-system
Teknik
Astro 7, Cloudflare Workers, Cloudflare D1, Durable Objects, Turnstile, OpenRouter, Exa, Firecrawl, Polar, Resend, Sentry
SignalScout: källbelagd outreach, eller ett tomt fält

Bakgrund

SignalScout är en kommersiell B2B-produkt från Nuits, min enmansstudio i Helsingfors. Du laddar upp en CSV med leads. Du får tillbaka en öppningsrad för var och en, och bredvid varje rad står URL:en den kom från, källans datum, och hur säkert systemet är på att de två hör ihop.

Om researchen inte hittade något användbart kommer fältet tillbaka tomt. Det kommer inte tillbaka rimligt.

Problemet

Varje AI-verktyg för outreach jag testat hade samma felmod, och det var ingen bugg i något av dem. Be om en personlig öppningsrad och du får en. Alltid. Det finns ingen indata som får saken att säga att den inte vet. Så du får ett självsäkert stycke om en finansieringsrunda som aldrig blev av, adresserat till en person som inte tog in pengarna, och du sätter ditt eget namn längst ner och trycker skicka.

Kostnaden är asymmetrisk. Att generera meningen kostar en bråkdel av en cent. Att skicka den kostar ditt anseende hos den enda kund du faktiskt ville ha. Ingen prissatte det rätt, mest för att en tom cell ser ut som en trasig produkt och en påhittad cell ser ut som en fungerande.

Min roll

Allt. Nuits har aldrig anställt någon.

Det betyder positioneringen, prismodellen, gränssnittet, tomma tillstånd, researchagenterna, utvärderingsriggen, betalningsintegrationen, transaktionsmejlen, feldashboarderna och meningen på prissidan som medger att AI-research kan ha fel. Jag designade det och jag skrev det. Det finns ingen att lämna den obekväma texten till.

Angreppssätt

Jag designade det tomma tillståndet innan jag designade något annat. Inte som ett gränsfall, utan som huvudskärmen. Om produkten ser korrekt och lugn ut när den inte hittat något kan resten av gränssnittet vara ärligt utan att be om ursäkt.

Därifrån följde formen. Varje påstående i resultatet bär ett ursprung köparen kan klicka på. Tillförlitlighet är en egenskap hos underlaget, inte en siffra jag bett en modell hitta på om sig själv. Och priset måste vara per lead i stället för per plats, eftersom ett pris per plats straffar precis den noggranna användare som skickar fyrtio bra mejl i stället för fyra tusen dåliga. Kreditpaketen ligger på $19, $79 och $249.

Så byggde jag det

Det körs på Astro 7 driftsatt på Cloudflare Workers. D1 håller konton, kreditreskontra och jobbposter. Varje researchbatch får ett Durable Object, vilket är det som gör produkten möjlig över huvud taget: ett lead tar tiotals sekunder att researcha ordentligt, en CSV med tvåhundra tar ett tag, och ett Durable Object överlever att användaren stänger fliken. Turnstile vaktar uppladdningsändpunkten så att den dyra vägen inte är gratis för främlingar.

Researchen körs i tre steg, och separationen är hela designen. Ett hämtningssteg använder Exa för neural sökning och Firecrawl för att hämta och extrahera sidorna det hittar, och returnerar kandidatdokument med URL:er och publiceringsdatum fästa vid sig. Ett skrivsteg ser bara de dokumenten och får inte hänvisa till något utanför dem. Ett bedömningssteg läser sedan varje genererat påstående tillbaka mot källtexten och slänger allt det inte kan hitta. Tillförlitligheten beräknas efteråt utifrån källornas färskhet och utifrån om oberoende källor är eniga, så modellen rättar aldrig sitt eget prov.

Modellerna kommer via OpenRouter, vilket låter mig routa per steg i stället för per produkt. Extraktion och klassificering körs på något billigt och snabbt, eftersom det utgör merparten av tokenvolymen. Bara den slutliga meningen, en gång per lead, går till en dyr modell. Kostnaden per lead håller sig förutsägbar nog att prissätta mot, vilket är det egentliga skälet till uppdelningen.

Felmoderna är den intressanta delen. Entitetskollisioner är värst: två företag delar namn, hämtningen returnerar båda, och öppningsraden beskriver fel företag på ett övertygande sätt. Domänmatchning och en kontroll av samma entitet i bedömningssteget fångar det mesta. Gamla källor kommer på andra plats: ett tre år gammalt pressmeddelande är tekniskt sant och socialt katastrofalt, så ålder matas direkt in i tillförlitligheten. Betalväggar och botväggar ger delvisa extraktioner som läses som fullständiga, vilket bedömningssteget behandlar som frånvaro i stället för som underlag.

Polar sköter betalningarna som merchant of record, så EU-moms är någon annans jobb. Resend skickar kvitton och avisering när ett jobb är klart. Sentry fångar det jag inte förutsåg, vilket är en längre lista än jag skulle önska.

Resultat

Den är live och den säljer krediter. Utdatan lämnar fält tomma, och prissidan säger rakt ut att AI-research kan ha fel, vilket är en märklig sak att sätta bredvid en köpknapp och skälet till att jag litar på köpknappen.

Vad jag skulle göra annorlunda

Jag byggde pipelinen i tre steg innan jag hade en utvärderingsuppsättning, så under första månaden var ”bättre” en känsla. Jag borde ha handmärkt hundra leads dag ett och låtit varje promptändring bevisa sig mot dem.

Jag prissatte också kreditpaketen innan jag visste min verkliga kostnad per lead. Nivån på $19 var optimistisk. Jag hade hellre lanserat ett enda pris, mätt i en månad och sedan byggt trappan.