My AI assistant runs my back office. I still press send myself.

Two small mechanical arms on a tidy desk sort white envelopes into flat trays, next to a steaming coffee cup and potted plants, in calm green flat editorial shapes.
Illustration generated with AI (Flux 1.1 Pro).

Before I have my first coffee, last night’s invoices are booked and both bank accounts have been checked. After the coffee I say “inbox”, and a few minutes later I know which three emails actually matter today. The replies are already sitting in Gmail as drafts.

That is my assistant. I built it myself, and by now it is the hardest-working member of my company. It has exactly one restriction, and the restriction is deliberate: it is not allowed to send anything.

What it does all day

I run a small software company in Madrid on my own: a dozen products, my own servers, customers who write in three languages, and the paperwork that comes with a Spanish S.L. This is what it handles now.

None of this is spectacular on its own. Together it is the part of my day I used to call “admin” in a tired voice.

Written instructions instead of improvisation

A language model is talented and moody. Ask it the same thing twice and you get two ways of working. So every recurring job is a skill in my setup: a written work instruction that Claude Code follows exactly the same way every time.

The “inbox” skill, for example, says:

  1. First get an overview of the whole inbox, read and unread, however old.
  2. Then sort by importance. Customers and prospects always come first.
  3. For every important email, a suggestion of what to do and a draft reply.
  4. Where there are several sensible options: alternatives, but its preferred version always first, with one sentence explaining why.
  5. Routine at the end as a single list that I wave through with one word.

So every morning runs the same way. That sounds boring. That is the point.

The memory: 178,000 entries

An assistant without memory is a polite stranger. A customer writes “as discussed”, and the assistant has to know what was discussed. Two weeks ago, two years ago, in a note or in a chat.

That is why the heart of the system is not an AI at all, but a search database (RAG). As of today it holds:

When an email comes in, it looks there first: earlier threads with the same person, where the project stands, what I promised last time. Only then does it write.

I built the database in the spring, on my Mac. Every text is cut into passages, and an open source model (bge-m3) turns each passage into a vector of numbers that captures its meaning. That is why a search for “invoice for the migration” also finds the email that says “factura de la migración”. In June everything moved to my own server. It has no graphics card, so the first full run took hours. Since then, only new material gets added.

It stays fresh thanks to a handful of unremarkable scripts. The server pulls in new mail every 15 minutes and my websites every night. Twice a day the Mac pushes whatever only lives on the Mac: notes, session logs, commits, documents. Private and financial folders are deliberately left out. Because the vectors are computed on my own server, my mail does not go to any AI provider to be indexed.

The most instructive failure belongs here. For ten weeks, one script did not index a single new session. Every run politely reported “0 new, status ok”, and the statistics showed a respectable number. The number was not wrong. It was frozen. Since then I do not trust any “ok” that does not also say how much actually happened.

The side effect I never planned: my own sent mail is the style guide. The drafts sound like me because they learned from five years of me. Even the short ones.

Guardrails written in code

In May, an email to a customer contained an IBAN that did not exist. It looked perfectly plausible, and that was exactly the problem. One correction email later there was a list of verified facts (bank details, tax numbers, addresses) and a hook that checks every outgoing email against it. If a hard fact appears that is not on the list, the draft is blocked.

That is how every rule here comes about: from a real mistake, and then as code, not as a good intention.

Which model, what it costs, where the data lives

Not every job needs the strongest model. Routine work runs on small, cheap models; diagnosis and anything that cannot be undone runs on the strongest one. When a new model comes out, it gets tested on real cases before it takes over.

The thinking at my desk runs on my Claude Code subscription, so a long session costs nothing extra. The service on the server that recognises invoices and reads the bank accounts around the clock uses small models through the API: 5,193 runs in 90 days, 2.50 dollars in total. I checked the sum twice.

And for customers who cannot let a single line leave the EU: the AI calls can run entirely through Amazon Bedrock in a European data centre.

None of this is finished. The bank connection has to be re-authorised every 90 days and has had weeks where it simply delivered nothing. Then I reconcile by hand, like everyone else.

The one line

For a while it did send. I approved an email in the terminal and the assistant sent it. That worked fine, and in October I switched it off anyway.

Not because of a disaster. Every email in my name is a promise, and I want to have seen the promise. Since then every outgoing email is created as a draft, and a hook blocks direct sending.

In the morning I open Gmail and the drafts are waiting. Most of them I send as they are, some I change, a few I delete and tell it what I actually meant. The next draft is better.

If a customer asks whether I answer with the help of AI: yes. The person who decides what gets said is still me.

Why I am telling you this

Because this is exactly what I now build for other companies. Not the same assistant, but the same pattern: your email, your invoices, your bank, your software and a memory made of your own history, connected to a model that prepares the work, with a person who makes the decisions. Every company gets its own instance.

I built it for myself first because I wanted to know where it breaks. It breaks in boring places: an expired bank consent, an invoice layout that changes overnight, a script that says “ok” for ten weeks, an IBAN that looks too plausible, a reminder to someone who paid long ago. The interesting part was never the model. It was deciding what it is allowed to do on its own.

If you can picture something like this in your company, just get in touch: on WhatsApp or through the contact form. Two sentences are enough: what is eating most of your time right now. I write the reply myself. The draft, maybe not.

← All posts