LOG 012 · SHIPPED · CLIENT-WORK / AI / WHATSAPP / N8N / WHISPER

Nobody fills in the form. I automated it away with n8n and Claude.

Cover artwork: on the left a phone showing the WhatsApp exchange, the system asking for a serial number, spares and finish time, the technician answering in one line, and the report closing in one round. On the right the six-box flow behind it: voice note in, Whisper on their server, Claude structuring, a completeness check, PostgreSQL, report out, with Claude outlined in orange as the only call that leaves the network.

A field technician finishes a service at a customer’s plant, gets in the van, and drives home. Somewhere in there he’s supposed to fill in a service report. He usually doesn’t, or he does half of it, and the half he skips is the half that matters two years later.

I spent a few weeks with that problem and shipped a four-week pilot proposal for it. The client is a manufacturer of heat exchangers, electrovalves, pumps and process equipment, sold and maintained inside food, dairy and pharmaceutical plants. They’re not named here, and neither is anyone who works there.

What I proposed is one sentence long: the technician talks for two minutes on WhatsApp, and the system writes the report.

$ docker compose ps
n8n         running   orchestrator, and the dashboard
whisper     running   transcription, on their own server
postgres    running   healthy
gotenberg   running   html in, pdf out

An unfinished report is an audit finding

The report isn’t an internal formality. In a pharmaceutical or a dairy plant, quality receives it and files it as a controlled document. When an audit comes, that paper is what gets shown. So an unfinished report isn’t a form filled in badly. It’s a finding, in somebody else’s plant, with the manufacturer’s name on it.

Then there’s the side nobody is looking at. Without structured data there’s no failure history per machine and per customer. Every service starts from zero. Spares and warranties get estimated by feel, because there’s nothing to count.

THE PROBLEM An incomplete report costs three times over OUTWARD Risk at the customer Pharma and dairy plants file these as quality documents. Incomplete is an audit finding, not a bad form. INWARD A history nobody has No structured data, so no history per machine. Every service starts at zero and spares are guessed. FORWARD An asset going unbuilt That same history is what an after-sales service gets built on, and the Industry 4.0 they sell. The problem is not the form. It is the conditions it gets filled in.

The constraint that decides everything came out of watching how the report actually gets filled in, not from the form itself. The technician is dirty, in a hurry, in a plant that isn’t his, finishing at six in the evening. Anything that adds a step won’t get used. That’s not a training problem, and it won’t be fixed by a better form.

TAKEAWAY: when a process fails at the same point every time, look at the conditions at that point, not at the artifact. The form was never the problem.

From audio to report

Six steps. The technician is in exactly one of them.

FROM AUDIO TO REPORT, STEP BY STEP 01 02030405 06 Sends an audio Instant reply Transcribed locally The AI sorts it Asks for what is missing Report + history The technician is in step 01 only. Everything else runs without him waiting on anyone.

He opens WhatsApp, finds a contact, and talks. If he took photos he sends those too. He gets an acknowledgement immediately, which matters more than it sounds like: transcription takes a minute or two, and a person who sends something and hears nothing assumes it failed. With the acknowledgement he puts the phone away and drives.

Everything after that runs without him waiting on it. The audio is transcribed, the transcript is turned into the same fields every time (customer, machine, serial number, fault, cause, work done, spares), and the report comes out with the company’s own formatting.

The only real risk is that nobody uses it

The technical parts of this aren’t hard. Every one of them is a service that already exists. The risk is that the technicians don’t use it, and that risk isn’t a technical problem, so it can’t be solved with a technical answer.

So every design choice attacks adoption:

  • No new app and no training. It’s the WhatsApp he already has, plus one contact.
  • No waiting. The acknowledgement is instant. The processing runs while he drives back.
  • Everything missing, in one message. Not a conversation. One message with every gap in it.
  • Two rounds, never a third. If something is still missing after the second ask, the report closes anyway and records what is missing.
  • He always gets his report. He can read what the system put in his mouth and correct it.
Service Reports online TODAY Almost done, I just need: · serial number of the exchanger? · which spares did you use? · what time did you finish? 17:38 AX-40-2219, two NBR gaskets and I finished 17:40 17:41 Got it. Writing the report. 17:41 one round · report closed ALREADY ON HIS PHONE Zero apps It is the WhatsApp he already has, plus one contact. He opens it and talks. HE JUST ANSWERS Zero training It asks once, he answers in a single line from the van, and the report closes.

The exchange as it would run, translated. The real one is in Spanish, because the technician is. The system says it’s close to closing and asks three things at once, he answers in a single line from the van, and that’s the whole interaction.

The two-round cap is the decision I’d defend hardest. Chasing a technician a third time is exactly the friction this was built to remove. A report at ninety percent that arrives is worth more than a perfect one that never does, and the missing field can be filled by a person later. The technician who stops answering doesn’t come back.

The AI goes at the edges, never in the middle

This is the part that transfers to every other project, so it gets its own heading.

I counted the steps in the flow and asked which ones need judgement. Receiving the webhook: no. Checking the message isn’t a duplicate: no. Checking the number is authorized: no. Downloading the audio: no. Transcribing it: no. Reading the technician’s story and pulling the facts out of it: yes. Saving to the database: no. Deciding whether something is missing: no, that’s a length check. Generating the PDF: no. Sending it: no.

One out of ten. The other nine are plumbing, and plumbing has to give the same answer every time.

informe-de-servicio · última ejecución: OK no WhatsApp trigger Whisper transcribir Claude estructurar ↗ ¿Completo? IF PostgreSQL guardar Gotenberg PDF Repreguntar máx. 2

The n8n canvas exactly as it was sent, Spanish and all, because it’s the artifact rather than a drawing of one. Everything in it runs on their own hardware except the Claude node, outlined in orange: the single call that leaves the network, carrying text and never audio.

If a model runs the whole pipeline, every execution is a fresh decision. One day it names a field differently. One day it decides to tidy up the work description so it reads better, and now the content of a document that will be audited has been changed by something nobody instructed. The variability isn’t a defect of the model. It’s the whole point of the model. It’s just a defect here.

Three things follow from that, and they are the architecture:

Transcription runs on their own server. In two minutes a technician says the customer’s name, which plant, which machine, and what broke. That is competitive information about somebody else’s operation, spoken by a third party. Running it locally costs nothing but CPU and turns a long conversation with a pharmaceutical client into one sentence: the audio doesn’t leave the network.

The structured output is guaranteed, not requested. The fields are defined as a schema that the API enforces, rather than described in the prompt and hoped for. Every key comes back every time, and a field the technician didn’t mention comes back empty instead of invented. That’s the difference between a system you can query in a year and a pile of text.

Four points touch the outside world, and each one is a variable. Input, transcription, model, output. Each sits behind a switch that reads an environment variable and a step that normalizes the answer back to a fixed shape. Between them, the flow is identical in every configuration.

# the four edges. two lines are the whole difference between
# my laptop and their server, and neither one is an engine.
CANAL_ENTRADA=whatsapp        # or a watched folder, for the prototype
CANAL_SALIDA=whatsapp         # or a file on disk
STT_PROVIDER=whisper_local    # does not change
LLM_PROVIDER=claude           # or gemini, or a local model

That last one isn’t architecture for its own sake. It’s what makes the answer to “what if you leave” and “what if that provider has a bad day” a variable instead of a project.

TAKEAWAY: put the model where language enters and leaves the system, and nowhere else. A data pipeline has to be boring in the middle.

The subproduct is worth more than the report

The report fixes the problem they have today. The thing it leaves behind is worth more, and it’s the reason I’d have wanted this project.

At the volume the costing assumes, six months in they have a few hundred structured service records: which machine, at which customer, failed how, and what was replaced. No competitor selling into those plants has that, and it accumulates whether anyone is paying attention to it or not.

THE SUBPRODUCT WORTH MORE THAN THE REPORT At six months: the real history of every machine, at every customer CONTRACTS Preventive maintenance you can sell «This machine had four corrective jobs in a year» is the sentence that sells a maintenance contract. With data, not a hunch. STOCK Mirror stock, counted Real spare consumption per customer and per machine turns consignment stock from estimated into calculated. PRODUCT The bridge to Industry 4.0 A portal where a customer looks up their own history is a sellable product. And it is born of this data. The report is today's deliverable. The history is the asset that stays.

The three cards from the proposal deck, translated. The report is the deliverable. The history is the asset.

Three things become possible with it, and none of them are possible without it. “This machine had four corrective interventions in a year” is the sentence that sells a maintenance contract, and it needs data rather than an impression. Spare stock held at customer sites moves from estimated to counted. And a portal where a customer looks up the history of their own equipment is a product, built out of data they’d already own.

There is one small, boring decision that decides whether any of that works. If the technician says a customer’s nickname and we store it as free text, in six months the same customer exists four different ways and the history can’t be crossed with anything. So the proposal asks for one spreadsheet of customer codes, exported from their ERP, and matches against it. Not an integration. Not access. A spreadsheet.

TAKEAWAY: a field that costs nothing to add today costs a cleanup project later. Decide how records will be joined before you have any.

Four weeks, and what I left out of scope

  • Week 1, discovery. A full day in the field with a real service. Define the minimum useful report with maintenance and quality. Measure the baseline: of the last fifty reports, how many are complete, and how long did they take to arrive. Without that number, nothing at the end can be called a result.
  • Week 2, prototype. The whole flow running, tested internally, adjusted against real friction rather than imagined friction.
  • Week 3, field pilot. Two or three technicians on real services, iterating daily. This is when the PDF gets built, because that’s when the first report goes to an actual customer.
  • Week 4, measured result. Measure against the baseline. Hand over the code and the documentation on their infrastructure. Prioritize what comes next.

Explicitly out of scope, and written down as such: corporate hardening, hosting and backups; direct ERP integration, where the proposal only prepares the data to be joined later; and support after handover, which is quoted separately. Their IT lead owns where it runs, who has access, and what happens to the data. That’s his territory, and the design assumes it.

The whole thing runs on about three dollars a month at a hundred services. That’s the only recurring cost, it’s prepaid credit rather than a contract, and if the project stops, nothing keeps running.

The decisions, on the record

DECDecisionStatus
DEC 001The model goes at the edges of the pipeline, never in the middleSETTLED
DEC 002Transcribe on their own server; the audio never leaves their networkSETTLED
DEC 003A visual orchestrator over a script I write, so their IT lead can read the flowSETTLED
DEC 004Four interchangeable edges behind environment variablesSETTLED
DEC 005Structured output enforced by a schema, not requested in the promptSETTLED
DEC 006Answer the webhook immediately, then do the workSETTLED
DEC 007Two rounds of follow-up questions, never a thirdSETTLED
DEC 008Store the raw transcript and which model wrote each report, permanentlySETTLED
DEC 009Ask for a spreadsheet of customer codes, not access to the ERPSETTLED
DEC 010Serve the dashboard from the orchestrator; drop the BI tool I first proposedREVISED
DEC 011Run the structuring on a local model insteadRESEARCH

DEC 010 is the one I got wrong first. I proposed a full BI tool, and the honest objection came back that it was a second application to run, update and back up, all to answer six fixed questions, and that nobody would open it. Six queries and a page of HTML served from the orchestrator do the same job with one less thing to maintain.

DEC 011 stays open on purpose. Running the structuring on their own hardware would make the system fully on-premise at zero running cost, and I didn’t propose it, because a smaller model’s failure mode is to fill in a number nobody said, and that number would land in a document that audits a pharmaceutical plant. So the raw transcript and the model name are stored on every record from day one. When they want that conversation, it can be run on their own reports, and settled with data instead of opinion.

What happened next

I sent it on 2026-07-29. Weeks have passed and there has been no reply, and at this point I don’t expect one.

That’s the honest ending, and it doesn’t change what the work is. The proposal shipped. The thinking is on the record, the architecture holds, and the four-edge pattern and the local-transcription argument have both gone straight into how I scope the next one.

If I ran it again I’d change one thing. I’d put the field day before the proposal instead of inside week 1 of it, even unpaid. Everything in here that I’m confident about came from understanding how the work actually happens, and everything I’m less sure about is a thing I had to assume.

What carries over

Three things, none of them about this industry.

Find the point where the process actually breaks, and look at the conditions there rather than at the artifact. The form was never the problem.

Put the model where language enters and leaves, and write ordinary deterministic code for everything between. That single rule is what makes a system somebody else’s engineer is willing to trust.

And build the thing they asked for in a way that leaves behind the thing they didn’t know to ask for. The report was the deliverable. The history is the asset.

// Deadlink Labs

← Back to the log