I dag har jeg brugt formiddagen på at få nyhedspipelinen til folkets.dk til at køre helt automatisk. Den henter nyheder fra internationale nyhedsservices hvert tiende minut, lader en LLM omskrive dem til danske notitser, og udgiver dem på sitet via Drupals JSON:API.
Det interessante er ikke at det virker. Det interessante er hvad det ikke indeholder.
Der er ingen agent framework. Ingen workflow engine. Ingen Docker-compose med syv containere. Ingen Kubernetes. Ingen managed service hos en cloud-leverandør. Ingen "AI orchestration layer".
Der er en systemd-timer der peger på en Nushell-fil der appender en linje til en JSONL-fil. Og en anden systemd-timer der læser den fil, kalder en LLM, og POST'er resultatet til en Drupal-endpoint.
Det er det.
Hvorfor systemd
Systemd er omkring 15 år gammel. Den kører på stort set alle Linux-servere i drift i dag. Det er ikke spændende teknologi. Det er heller ikke det den prøver at være.
En systemd-timer er to små tekstfiler:
# cnn-to-database.timer
[Timer]
OnCalendar=*:0/10:*
Persistent=true
Unit=cnn-to-database.service
[Install]
WantedBy=timers.target
# cnn-to-database.service
[Service]
Environment=PATH=/home/lk/.local/share/mise/shims:/usr/local/bin:/usr/bin:/bin
ExecStart=/home/lk/.config/nushell/scripts/collectors/cnn-to-database.nu
Persistent=true betyder at hvis maskinen var slukket da timeren skulle fyre, så kører den når maskinen kommer op igen. Det har jeg ikke selv kodet. Det er bare en linje.
journalctl --user -u cnn-to-database viser logfilen. Det har jeg heller ikke kodet. Det er bare en kommando.
Når systemd-unit'en fejler er der en exit code, en log, en "last successful run", og en automatisk genstart hvis jeg vil have det. Alt sammen uden at jeg har skrevet en eneste linje med "retry logic" eller "circuit breaker pattern".
Hvorfor JSONL
Datalaget mellem collector (henter nyheden) og publisher (omskriver og udgiver) er en fil med én JSON-linje per nyhed:
{"title":"…","content":"…","datetime":"…"}
{"title":"…","content":"…","datetime":"…"}
Append-only. Dedupliceret på titel. Læses med open file.jsonl | lines | each { from json }.
Ingen database. Ingen schema migration. Ingen connection pool. Ingen ORM. Når jeg vil debugge en post læser jeg filen med tail. Når jeg vil rulle tilbage sletter jeg sidste linje med en editor.
Den vil holde til mange tusinde nyheder før jeg overhovedet skal overveje SQLite. Når jeg en dag gør det, er konverteringen et 10-liners script.
Det jeg brugte formiddagen på
Formiddagens commits handlede ikke om at finde på en arkitektur. Den havde jeg. Det handlede om de små ting der altid driller når man limer rigtige systemer sammen:
PATHi systemd-units.mise's shims ligger ikke på standard-PATH, såenv nukunne ikke findenu-binæren. Tilføj én linje:Environment=PATH=....- Refactor af scripts ind i
collectors/ogpublishers/så strukturen matcher den mentale model: noget der henter, og noget der udgiver. - Migration fra et tidligere format til JSONL med titel-dedupe så jeg kan starte/stoppe collectors uden at få dubletter.
- Skifte LLM-model til Gemini Flash Lite fordi den er fem gange hurtigere og forskellen i output-kvalitet er ikke målbar for notits-omskrivninger på 80 ord.
Det er kedeligt arbejde. Det er præcis derfor det virker.
Hvorfor det her er en pointe i AI-rådgivning
Jeg får jævnligt spørgsmål fra SMV'er om hvilket "AI-platform" de bør vælge til at automatisere et eller andet. De har set et webinar hvor en konsulent demonstrerede et glansbillede af et workflow med 14 noder og tre AI-agenter der "samarbejder".
Mit svar er næsten altid det samme: start med en cron-job (eller en systemd-timer) og en fil. Læg AI-kaldet ind midt i pipen som ét af mange skridt. Lad resten af systemet være forudsigeligt, gennemskueligt, og noget IT-supporten allerede ved hvordan virker.
Den dag pipelinen fejler, så fejler den i den linje du selv har skrevet — ikke fem lag nede i et framework hvis docs er forældede. Den dag du skal forklare en revisor hvad systemet gør, kan du gøre det på en serviet.
Stabile, gamle, velafprøvede metoder er ikke retrograd nostalgi. Det er hvad du står tilbage med når marketing-laget skrælles af.
Systemd-timeren der lige nu kører i baggrunden mens jeg skriver det her, har sandsynligvis 10+ års levetid foran sig uden vedligehold. Det kan ikke alle nye AI-frameworks sige.