Free Guide

Turn your coaching calls into content automatically

Every coaching call I run gets recorded, transcribed, and mined into structured content ideas without me opening anything. The ideas land in a database with their source, their teaching, and the exact quotes I used. Then my phone buzzes and I reply with numbers. This is the whole system, built from scratch.

This is the most involved of my four automations. If you would rather have it running than build it, I do this for people.

Book a call with me

Watch the walkthrough

I cover this build as Automation 1 at 0:37. The player above starts there automatically.

What you're building

A loop that starts when a call ends and stops at your thumb.

  1. You run a coaching call. It records and transcribes itself.
  2. The transcript lands in a Drive folder.
  3. An always-on agent notices the new file, reads all of it, and pulls out the distinct teaching moments.
  4. Each one becomes an Idea Packet: the problem as the member experienced it, the teaching you gave, your verbatim quotes, which pillar it belongs to, and whether it suits a course video, a short, or both.
  5. Each packet gets a row in your content database with a unique ID, its own Drive folder, and a link back to the source transcript.
  6. If a teaching already exists from a previous call, it does not create a second row. It appends the new transcript to the existing one, so repeated teachings accumulate evidence rather than clutter.
  7. Your phone buzzes with a summary. You reply with kill, park or proceed.
  8. Anything you proceed on becomes a first-draft script filed in the right folder.

The thing that makes this work is not the AI. It is the database. An agent with a well-shaped place to put things becomes reliable. An agent with nowhere to put things produces text you then have to file yourself, which is most of the work you were trying to remove.

How hard this actually is

I would rather tell you now than have you discover it in step 4.

The other three automations in my video are afternoon projects. This one is not. It took me the better part of a week of real building, and I found roughly a dozen genuine bugs on the way, several of which reported success while doing nothing at all.

What makes it heavy is that you are standing up a service, not writing a script. It needs somewhere to live that is not your laptop, its own identity, its own permissions, a database with an enforced shape, and a monitoring layer so you find out when it breaks rather than noticing three weeks later that nothing has been mined.

What makes it worth it is that this is the only one of the four that compounds. Every call you run makes the library bigger, and the library is what everything else draws from.

If a week of building is not something you want to spend, skip to the lightweight version near the end. It gets you 60 percent of the value in an afternoon with no server involved.

What you'll need

  • Coaching calls that record and transcribe. Google Meet on a Workspace plan does this natively. Zoom and Fathom both work, the transcript just arrives somewhere different
  • A Google account for the database and the Drive folders
  • A small cloud server. I rent one for about $10 a month. This is what makes it always-on
  • An agent framework. I use Hermes, which is free and open source. It handles the Telegram connection, the scheduling, the memory and the skill loading
  • A model subscription for the agent's own thinking. I run mine on a flat-fee coding subscription rather than metered API pricing, because an agent doing this work makes a lot of tool calls and metered pricing gets alarming fast
  • Claude Code on your own machine to do the building. Roughly $100 a month
  • Telegram, free, which is how you talk to the agent from your phone

All in, mine costs about $310 a month, and the largest line item is the coding subscription I would pay for anyway.

The four pieces

Before any building, understand the shape. Every piece exists to serve one of four jobs.

The database. A Google Sheet with one tab per content type. This is the spine. Every idea, every script, every published piece has a row and a unique ID.

The store. A Drive folder per piece of content, holding its documents and assets, linked from its row.

The agent. A small always-on program on a rented server that can read and write both of those, transcribe things, and message you.

The skills. Instruction files that teach the agent your specific procedures. Mining a call is a skill. Writing a course video is a different skill. Each one loads only when it is needed.

Build them in that order. The mistake is to start with the agent, because the agent is the exciting part, and then discover it has nowhere sensible to put anything.

Step 1: Build the content database

Everything else references this, so it goes first.

Prompt 1: the database
Build me a content database in Google Sheets.

Create one spreadsheet with these tabs, each one a registry of a single
content type: SHORTS, YOUTUBE, NEWSLETTER, CAROUSELS, COURSE_VIDEOS.

Every tab gets the same first four columns:
  CID, Title, Brand, Card State

Then a block of production status columns starting at column E. For
COURSE_VIDEOS use: Packet, Script, Prep Materials, Record, Edit, Captions.

Then these reference columns, in this order:
  Source Refs, Idea Packet, Script Doc, Captions Doc, Drive Folder,
  Publish Date, Notes, Created, Last Updated

Rules:
- CID is a single unified series across every tab, C0001 upward. A CID
  appears in exactly one tab and is never reused.
- Card State is exactly one of: active, parked, scrapped, published.
- Every status column is exactly one of: not_started, in_progress,
  needs_review, done, skipped.
- Newest rows go at the top, not the bottom.
- Add dropdowns for Card State and the status columns.

Then explain to me, in plain English, what each column is for and how I
would read a row at a glance.

Four design decisions in there are worth defending, because I got each of them wrong first.

One unified ID series, not one per tab. I originally used a different prefix per content type. It looked tidy and it meant that every time a piece changed type, or an idea spawned a second format, I had two identifiers for one thing. Migrating 203 rows and 594 Drive items back to a single series was a bad afternoon. Start unified.

Status columns with a fixed vocabulary. Five values, no free text. The reason is not neatness. It is that you can then ask "show me everything scripted but not recorded" and get a real answer, which is the entire point of having a database rather than a notes app.

Resolve columns by header name, never by letter. Write this rule down and put it in your agent's identity file. The day you insert a column, every hardcoded letter reference silently points at the wrong data. I inserted nine columns into a tab once and every document link shifted four columns to the right.

Newest at the top. Trivial until you realise it means row numbers change constantly, which is exactly why the header-name rule matters and why anything writing to a row must find that row by its ID immediately before writing, not by remembering where it was.

Step 2: Set up the Drive structure

Every piece of content gets a folder. Same shape every time, created automatically, never by hand.

Mine looks like this: a folder named with the content ID and title, containing an Audio folder, a Videos folder, each split into Final and Originals, and a Prep Materials folder holding the Idea Packet doc, the Script doc and the Captions doc.

Ask Claude Code to write you a small script that builds that tree and creates the three documents, then have it return the folder link and the three document links so they can be written straight into the database row. Have it run once for a test ID, then look at the result in Drive with your own eyes before wiring it into anything.

The rule that saves you later: even a raw idea gets its folder and documents created immediately, sparse and mostly empty. The alternative is a two-tier world where some ideas have somewhere to live and others do not, and you end up checking which is which forever.

Step 3: Turn on call transcripts

In Google Meet on a Workspace plan, recording and transcription are toggles you hit when the call starts. Both land in your Drive automatically when the call ends.

Three practical notes from running this for a while.

The transcript finishes before the recording does. If anything downstream expects both, it should tolerate the recording being missing and carry on with the transcript.

Check that captions were actually on. I have one 50 minute call whose transcript document exists, records that the meeting ended, and contains zero words. Fifty minutes, unrecoverable, because captions were off. If a call matters, glance at the transcript afterwards.

Where a session was exported twice, you can end up with two documents where one is nearly empty. If your system grabs the newest, it will sometimes grab the empty one. Have it check word count and prefer the substantive file.

Step 4: Stand up the agent

This is the part that needs a server. The reason is simple: your laptop closes, and an agent that only works when your laptop is open is not an automation.

I rent a small Linux server from Hostinger, around $10 a month, with Docker pre-installed. Docker means the agent runs in its own sealed box, so it cannot interfere with anything else and you can rebuild it cleanly if you break it.

Prompt 2: the server
I want to run an always-on AI agent on a cloud server so it keeps working
when my laptop is closed. Walk me through it one command at a time. I am
not technical. Before each command, tell me what it does and what I should
expect to see. Verify each step worked before moving to the next one.

Here is the setup I want:
1. A Linux server I rent by the month, with Docker already installed.
2. The agent running inside Docker, in its own folder, so it cannot
   interfere with anything else on the box.
3. Pin the agent to a specific known-good version number. Do not use the
   "latest" tag.
4. No public ports open. The agent should only talk outbound.
5. A folder on the server that survives restarts, holding all its data,
   settings, memory and skills.

Stop after each numbered item and confirm with me before continuing.

Pin the version. I cannot stress this enough and it cost me half a day. I started on the latest release, and the agent hung forever at "connecting to Telegram". I ruled out the network, the DNS, the address family and the HTTP library one at a time before finding it was a known bug in that release. Pinning to an older known-good version fixed it in one line. Use a specific version number, always.

Then a Telegram bot, which is how you talk to it. Message BotFather inside Telegram, ask for a new bot, get a token. Two things to do immediately: lock the bot so only your own account can talk to it, and then send the bot a message yourself before you expect it to message you. A bot cannot start a conversation with someone who has never messaged it. I spent an hour debugging alerts that were never going to arrive.

Step 5: Connect Google

The agent now needs to read and write your sheet and your Drive. That means a one-time sign-in flow where you approve the permissions.

Ask Claude Code to set this up over the connection to your server, walking you through each step. When it produces a sign-in link, you open it, pick your account, approve, and hand back the code from the resulting URL.

Two things here caught me out badly enough to be worth your attention.

The success screen looks like a failure. After you approve, the browser tries to send you to a local address and shows an error page. That error page is the success. The code you need is sitting in the address bar of the page that failed to load.

Check your app's publishing status. If the Google Cloud project behind the sign-in is in Testing mode, the permission you just granted expires after seven days and every write starts failing silently. I found this with four days to spare. If both accounts are in the same Workspace organisation, set the app's user type to Internal and the problem disappears permanently. Publishing it externally is the wrong fix, because Drive and Gmail permissions are restricted and publishing triggers a formal Google review.

One more thing to decide deliberately rather than by accident: which Google account the agent authenticates as. Mine runs as a dedicated automation account rather than my personal one, which is cleaner, but it does mean that account owns the documents it creates. Decide that on purpose.

Step 6: Give the agent an identity

Out of the box your agent is a general assistant that happens to have your credentials. The identity file is what makes it yours.

Prompt 3: the identity file
Write the agent's identity file. This is the document it reads before
every single message, so it should be short and load-bearing, not a
manual.

Include:
- Who I am, what my business is, and who my audience is.
- The spreadsheet it works in and the rule that it must resolve columns by
  reading the header row, never by assuming a column letter.
- The legal values for Card State and for the status columns, and a note
  that spreadsheet dropdowns do NOT constrain what a program writes, so it
  has to enforce them itself.
- How to mint a new CID: read the highest existing CID across every tab
  and add one.
- The privacy rule, in its own section: never name a client, student or
  participant in any output, ever. Refer to them as "a member" or "a
  client".
- Which tabs are read-only because other systems own them.
- What this agent does NOT do, so it never invents work.

Keep it under about 7KB. Everything longer belongs in a skill file that
loads only when it is needed.

Alongside it, keep the things that change per person in a separate small settings file: your name, your spreadsheet ID, your Drive folder ID, your offer, your links. Keep your voice rules and your topic pillars in two more files. That split is what lets you rebuild this for a second person by swapping four files rather than editing forty.

Two hard-won notes about how these files get used.

Length is a real constraint, and not for the reason you think. A 9KB instruction file does not cost meaningful money in tokens. It costs attention. Rules dilute each other. I put a soft ceiling of about 8KB on procedure files and, more usefully, a rule that a correction must not grow the file. New rule in, old rule out or merged. Otherwise every piece of feedback you ever give accumulates forever and the file stops meaning anything.

The first line of a skill's description is doing more work than the rest of it. In my setup the router that decides which skill to run only sees the first 57 characters of each description. Every skill I shipped had its trigger phrases buried past that cutoff, so automatic discovery was running on a fragment and picking wrong. Front-load the trigger words. Whatever framework you use, find out how much of your description it actually reads before you trust it to route.

Step 7: The call-mining skill

This is the heart of the system.

Prompt 4: call mining
Build a skill called call-mining.

Trigger it when I say things like "mine this coaching call" or "pull ideas
from this transcript".

What it does, in order:

1. Take a transcript from a Google Doc, a Drive folder, or pasted text.

2. Read the whole thing and find distinct teaching moments. A teaching
   moment is a place where a real problem came up and I taught something
   in response. Not a nice-sounding line. An actual before and after.

3. For each one, write an Idea Packet as its own Google Doc:
   - The problem, stated the way the member experienced it, anonymised.
   - The teaching, summarised in my own vocabulary.
   - Verbatim quotes of the key lines I said.
   - Which of my content pillars it belongs to.
   - Whether it suits a course video, a short, or both.
   - A source line pointing at the transcript's full Drive link.

4. Before writing anything, check the Source Refs column of my database
   for that transcript's Drive ID. If the same teaching already exists as
   a row, do NOT create a duplicate. Append this transcript's link to the
   existing row's Source Refs instead, so a repeated teaching accumulates
   evidence rather than clutter.

5. Write one row per new packet into the COURSE_VIDEOS tab: next CID,
   title, Card State active, Packet in_progress, the source link, and
   links to the packet doc and its Drive folder.

6. Update a running "Course Map" doc that clusters the packets into themes
   and lists the gaps where I have no material yet.

7. Send me a summary in Telegram with each new packet as kill, park or
   proceed so I can reply with numbers.

Hard rules:
- Never name a member. Grep your own output for every name in the
  transcript before you write it anywhere, and fail loudly if one appears.
- No em dashes anywhere in a packet.
- Every claim traces to something actually said in the transcript. Invent
  nothing.

The Idea Packet is the primitive. Not a title, not a one-line idea. A structured document with the problem, the teaching, the verbatim quotes and the source. The difference is enormous when you come back three weeks later. A title tells you nothing. A packet tells you what you actually said and why it mattered.

Deduplication is what makes it usable past call three. You teach the same frameworks repeatedly, which is the point of having frameworks. Without deduplication your database fills with near-identical rows and becomes noise. With it, a teaching that appears in three separate calls ends up as one row carrying three source links, which is a much stronger signal that it deserves a video.

Deduplicate on the transcript's Drive ID rather than its filename. Filenames repeat and get renamed. IDs do not.

The moment this became real for me was watching it mine a session from two years earlier, under the program's old name, and correctly merge those teachings into rows created from a call last month. That is the behaviour that turns an archive into a library.

The Course Map is the sleeper feature. Clustering the packets into themes is mildly useful. The gaps list, the themes where you have almost no material, is the thing I now plan content from.

Step 8: The drop-and-notify loop

Now make it run without you asking.

Prompt 5: the watcher
Set up the drop-a-file loop.

1. Create a Drive folder called "Call Transcripts" and point the agent's
   config at it.
2. Schedule a job that runs on a timer, compares every file in that folder
   against the Source Refs column in my database, and mines exactly one
   file that has not been mined yet.
3. Deliver the resulting digest to my Telegram.
4. If nothing new is there, say nothing at all.

Two things to get right, because I have been burned by both:
- The delivery target must be explicit. A job configured to "deliver to
  telegram" with no chat identifier will run, report success, and silently
  drop the message. Set the target as platform plus chat id.
- Prove delivery with a throwaway job that just sends the word "test"
  before you trust the real one. A green status is not proof a message
  arrived.

Then tell me how to change the timer, and what a sensible cadence is given
that this is a poll, not an instant trigger.

The bug called out in that prompt was the single worst one in my entire build, so it is worth a paragraph of its own.

My scheduled job ran on time. It read the folder correctly, mined the transcript correctly, wrote the rows correctly, and generated the digest correctly. Then it dropped the message and logged a status of ok. The proactive notification, the feature the whole thing is pitched on, had never worked once, on either of the two agents I was running, and the success status hid it completely.

The cause was that the delivery target was set to a platform with no chat identifier. The lesson generalises far beyond this build: a green status means the job finished, not that the outcome happened. Verify outcomes, not statuses. Send a throwaway "test" through the real delivery path before you trust it.

One honest limitation. Drive does not push events to your server, so this is a poll on a timer, not an instant trigger. Every 15 minutes is fine for testing and wasteful as a permanent setting. Daily is usually right, with the ability to message the agent and say "mine the folder now" when you want it immediately.

Step 9: Packet to script

Mining gives you a library. Now turn an approved packet into something you can record.

Prompt 6: the scripting skill
Build a second skill called course-video.

I run it by saying "write the course video for C0123".

What it does:
1. Read that packet doc and the row it belongs to.
2. Refuse to run if I have not approved that packet. Approval is a human
   step and it does not get skipped.
3. Write a 450 to 750 word script for a lesson inside my paid community.
   No hook, no call to action, no growth framing. These people already
   bought. Teach.
4. Load my voice file and my banned-phrase list, and run the deterministic
   writing checks before it hands me anything.
5. Mark where I should demo something on camera rather than talk.
6. End on one thing the viewer should go practise.
7. Save the script into that CID's Drive folder and update the row.

Reference the voice and gate files by their full absolute path, not a
relative one. A skill that references a shared file by relative path looks
fine until the first time it actually runs.

Keep this as a separate skill from mining. Mining is cheap and runs unattended. Scripting is expensive, needs your approval first, and has completely different quality rules. Bundling them means you cannot run either one without the other.

Note the difference in what a course video is. No hook, no growth framing, no call to action. Those exist to win attention from strangers. Inside a paid community you already have the attention, and hook-shaped teaching reads as slightly insulting. Teach, mark where you will demonstrate on camera, and end on one thing to go practise.

Expect roughly 80 percent. AI will not hand you a finished script and anyone claiming otherwise is selling something. Starting from a structured 80 percent draft grounded in something you genuinely said is a different job from starting at a blank page, and that difference is where the hours go.

Step 10: Keep it honest

Skip this section and you will have a system that quietly stops working and does not tell you.

Four things I run, all of them small.

A heartbeat. Every ten minutes, check the agent is alive and has disk space. If not, message me. I also register it with a free dead-man's-switch service, which alerts me if the whole server disappears, since a dead server cannot send its own alert.

A credential canary. Once a day, refresh the Google connection, read one cell from the real sheet and write one cell to a throwaway sheet. This is what catches an expired permission on day one instead of the day you need it.

A daily backup. Export every tab to CSV and keep 30 days. This has saved me once already.

A drift check. Every few hours, compare what the database says against what actually exists in Drive, and report differences without changing anything. Agents write invalid values to spreadsheets more often than you would like. Worth knowing: a dropdown in Google Sheets does not constrain what a program writes. It stops a human. It does nothing to an API call. The enforcement has to be in your code.

The privacy rule

Your calls contain named people describing their real problems. That material is not yours to publish, and the fact that a machine did the extracting changes nothing.

My rule is absolute: no participant is ever named in any output. Not in a packet, not in a script, not in a course map, not in a Telegram digest. Everyone is "a member" or "a client".

Do not rely on the model being careful. Make it a hard check. After every mining run, take every proper name from the transcript and search the generated documents for each one. If any appears, the run fails and nothing gets written. I run that check on every single mining pass, including one session with a room of twelve named participants, and I check the result rather than assuming it.

Two more habits. Work on copies of transcripts, never originals, so a bad run cannot damage your record of what was said. And if you plan to use any of this material publicly in a form that could identify someone, ask that person directly. The automation is not a consent mechanism.

What went wrong for me

  • Proactive delivery never worked and reported success. The worst bug in the build. A green status is not proof of delivery.
  • The "latest" version hung on startup. A known upstream bug. Pin a specific version.
  • A bot cannot message you until you message it. Every alert and digest silently failed until I sent the bot a single "hi".
  • The Google permission was seven days from expiring. Testing-mode apps expire refresh tokens. Set it to Internal.
  • Rebuilding the container lost dependencies. Some things I installed lived in the image, not the data folder, so a restart kept them and a rebuild silently did not. Keep a list of what needs reinstalling after a rebuild.
  • A skill referenced a shared file by relative path. Invisible until the day it first ran, which was weeks later. Absolute paths. And treat the first real run of any skill as its actual test.
  • A bulk write nearly overwrote every title in the sheet because two tabs used the same header name for different things. The dry run caught it. Always dry-run a bulk write.
  • Spreadsheet dropdowns do not constrain the API. Invalid values appeared hours after I added validation. Enforce in code.
  • Sheets rate limits are real. Roughly 60 writes a minute. Pace bulk operations a couple of seconds apart, and write one row at a time so a failure halfway leaves a consistent sheet.
  • A pre-filled template left 700 invisible rows. Appending landed the first packet at row 774. Clear the values, not just the visible rows.
  • I assumed a background job had finished when its wrapper said so. It had not. I reported it wrote nothing. Verify by reading the artifact.
  • Formatting drifted across runs. Packet headings picked up an em dash because the format was never pinned in the skill. If a detail matters, state it explicitly rather than hoping for consistency.

The lightweight version

If a server is more than you want to take on, this is the honest 60 percent, and it takes an afternoon.

Build the database in step 1. Build the Drive structure in step 2. Turn on transcripts in step 3. Then skip the server entirely and run the mining skill inside Claude Code on your own machine, pointed at a transcript you paste or a Drive link you hand it.

What you lose: it does not run while you sleep, nothing buzzes your phone, and you have to remember to do it. What you keep: the packets, the deduplication, the database, the course map, the scripts. All of the compounding value, none of the infrastructure.

My honest advice is to run the lightweight version for a month first. If you find yourself doing it after every call without being nagged, the always-on version will pay for itself. If you do not, the server was never the problem.

What's next

Once the library exists, the interesting question stops being "what should I make" and becomes "which of these 30 things is most worth making".

Directions worth taking from here: a morning digest that scores your open ideas against your pillars and surfaces five, with a cooldown so the same idea does not resurface every day. A repurposing step that turns one approved course video into a short. A gaps report from the course map that tells you what your library is missing.

All three are the same shape as what you have already built. Read the database, apply judgment, write back, notify.

Want this built for you? This is the one people ask me to build most, and the one that takes longest to do alone. If you would rather have it running against your calls than spend a week on it, let's talk.

Book a call with me