I wanted to automate Virya outreach, but not in the usual "how many emails can we send before lunch?" sense. We are writing to festivals, radios, journalists, venues and people we may genuinely want to work with. Turning that into a volume game would save time and destroy the point.
Sending is the smallest part
The send button is actually the smallest part of the process. Before one useful message exists, somebody has to choose the right organisation, verify the contact route, find a real reason to write, check whether we contacted them before, prepare the material and remember what happened afterwards.
That is what I automated.
Automate the preparation
The workflow selects a candidate, checks the available route, scores relevance, builds a factual hook, prepares a draft, detects duplicates, writes everything into the outreach log and posts a preview to Discord. An approved record may become a Gmail draft. Sending remains manual.
The hook must be real
The factual hook matters most. A generic introduction to the band can be sent to anyone, which is exactly why nobody needs to read it. A useful message may refer to an open submission, a matching radio format, a recent article, an earlier conversation or a local event. AI can make those facts sound natural; it cannot create them because the email looks a little empty.
Gmail is not the process
Every candidate has a plain state: pending, approved, rejected, sent, replied, follow-up due or closed. Gmail stores the conversation, not the process. The CRM keeps the draft ID, thread ID, dates, next step and idempotency key, so I can ask useful questions instead of searching the inbox by memory.
Discord is the queue, not the truth
Discord only points us to the queue. It shows who the contact is, why the record matters and what needs a decision. Chat history is convenient, but it is not a source of truth.
One reminder, then stop
I also set a simple follow-up rule: one initial message, one reminder, then stop after a reply, rejection or manual closure. The timer starts after sending, not after creating a draft. I added that distinction after realising how easily the system could remind us to follow up on an email that had never left Gmail.
Social DMs stay manual
Social DMs stay separate. APIs often do not allow a cold conversation to be initiated programmatically, and I am not interested in designing around that restriction. When email exists, the system prepares a draft. When only a profile exists, it prepares the text and asks a person to send it.
The machine repeats the boring part. A person decides whether the relationship is worth starting. That is the automation I actually wanted.