← Tilbage til LLM CourseCase Study · Retrospektiv

Navigent. smart chat

Jeg byggede en chat-først AI til B2B cold outreach, over-engineerede den grundigt, overlevede et rigtigt hackforsøg — og slettede så det hele. Det her er hvad jeg lærte, og hvorfor det næste bliver bygget helt anderledes.

ArbejdstitelNavigent — Smart ChatDomæneB2B outbound · SMBStackHåndlavet state machine · LLM · Prospeo
State machineMulti-agentB2B SalesProspeoPrompt injectionLinkedIn (næste)
01 · Hvad jeg byggede

Idé til live kampagne på ti beskeder.

Du åbnede en chat, skrev noget i stil med “find Heads of Marketing i Berlin og send dem en cold email”, og en state machine på serveren kørte resten: find leads, skriv emails, vælg tone, planlæg, launch. Hvert trin kom tilbage som et interaktivt kort inde i chatten — målgruppe-preview, redigerbar email, schedule-editor. Det virkede. Det var også det mest over-engineerede jeg nogensinde har bygget.

02 · Arkitektur

Briefen sagde LangGraph. Det gjorde jeg ikke.

Jeg håndlavede en state machine i stedet. “Grafen” er i virkeligheden bare et register af felter plus rene funktioner der regner næste trin ud — rækkefølgen i et array er flowet. 1.339 linjer i én fil.

LangGraph føltes som overhead for et flow på ~10 mostly-lineære trin. Det var en forsvarlig beslutning dengang — men det løste ikke det egentlige problem, nemlig at jeg over-byggede selve flowet. (Mere om det i “Hvad jeg fik galt”.)

03 · Hvor sad intelligensen

Fire skills og en model-split

01

Goal-klassifikator

En billig model router intaket til det rette mål — find_leads, email_campaign, undecided.

02

Multi-intent nav

Ét LLM-kald pr. tur returnerer både primær intent og side-flags: off-topic, injection, spørgsmål.

03

Concierge (Q&A)

Svarer fra et videns-dokument og afviser off-topic og prompt-injection deterministisk — uden et modelkald.

04

Audience-architect

Naturligt sprog → Prospeo-filtre. Forfin, udvid eller bekræft målgruppen direkte i chatten.

05

Strategist

Vælger persona og skriver selve email-copyen — den dyre model, fordi det er det eneste brugeren bedømmer.

Pointen i model-splittet: brug den billige model til alt det kedelige — routing, parsing, Q&A — og gem den dyre til selve email-copyen. Ingen beundrer en klassifikators prosa; emailen en lead læser er det eneste output et menneske rent faktisk bedømmer.

04 · Hvad jeg fik rigtigt

Det kedelige forsvar var det bedste jeg lavede

  • Billig/dyr model-split — pengene brugt der hvor brugeren faktisk kan smage det.
  • Rate limits + cost caps. (De reddede min pengepung under et rigtigt hack.)
  • Hvert kort valideret af et schema — klienten stoler aldrig blindt på serveren.
  • En kill switch der fandtes før jeg fik brug for den.
  • Audit-logs der overlevede selv en slettet chat.
05 · Hvad jeg fik galt

Jeg byggede til fleksibilitet ingen brugte

  • En 1.339-linjers state machine til at gå 10 trin i rækkefølge. En wizard havde gjort det.
  • Chatten var den forkerte indpakning — kortene var værdien, ikke samtalen.
  • 3–5 LLM-kald før brugeren så et eneste ord tilbage. Langsomt og dyrt.
  • For meget magt gemt bag ét enkelt admin-flag (“god mode”).
  • Row-Level Security slået fra by default — og jeg tjekkede det ikke.
06 · Hacket

Så prøvede nogen rent faktisk.

Superadmin-view“God mode” slået tilSpam for at brænde mit budgetRate limits + caps holdtKill switch trukketSmidt ud

Mens den var live, kom en rigtig bruger ind i et superadmin-view, slog “god mode” til og begyndte at spamme chatten for at brænde mit OpenAI-budget af. Jeg sad ved skærmen og så det ske live. Mine rate limits og spend caps holdt, jeg trak kill switchen, smed ham ud — og brugte aftenen på at lukke døren han kom ind ad.

Det rigtige hul var ikke AI’en — det var databasen. Supabase serverer hver tabel gennem et auto-genereret, offentligt API, og Row-Level Security var slået fra. Jeg slog RLS til på hver eneste tabel samme aften. Lektien: giv ikke din AI — eller dit admin-flag — mere magt end opgaven kræver, og regn med at nogen prøver hver dør du glemmer at låse.

07 · Nuke

Så slettede jeg det hele.

788 filer. 181.757 linjer. Én commit. Plus ~800 linjers SQL der tømte databasen. Ingen kørende demo i dag — og det er lidt pointen. At bygge det var læringen; at beholde det havde været fejlen.

08 · Pivot

Hvad nu: LinkedIn, bygget mere skånsomt

Hvad ændrer sig

  • LinkedIn, ikke email — deliverability er et mareridt af spamfiltre og 20-sends-om-dagen warm-up.
  • En wizard, ikke et metro-net.
  • Færre LLM-kald, flere knapper, mindre gætteri.
  • Least privilege fra linje ét.

Hvad følger med

  • Audience-søgning via Prospeo.
  • AI-personalisering af copy.
  • Scheduling og opfølgnings-sekvenser.
  • Alle sikkerhedslektionerne.
09 · Næste skridt

De tre næste opgaver

01

LinkedIn-kanal

Connect-flow via Unipile + send/læs beskeder end-to-end, så en personaliseret besked kan afsted fra chatten.

02

Wizard, ikke chat

Knap-drevet flow gennem de samme trin. Klassificér kun når en knap ikke kan svare — minimér LLM-kald pr. tur.

03

Least privilege fra start

RLS slået til på hver tabel, ingen genvejs-“god mode”, og spend caps fra dag ét frem for som eftertanke.