How we find short-term rental owners, reach out to them, and keep every single step safe and approved.
A "lead" is a person we're trying to reach — a short-term rental owner. Every lead follows these exact steps. Nothing skips ahead.
We spot a short-term rental owner (Airbnb or VRBO host) we'd like to work with. Skylar adds them to the CRM as a lead — our word for a person we're actively trying to reach.
👤 Skylar does thisAttio is our memory — a database that stores everything about each person: their name, their phone number, every message we've ever sent, their replies, and whether they've ever asked us to stop. This is the source of truth.
⚡ AutomaticNothing happens automatically. Skylar runs a command called /enroll — this is how a lead actually enters a campaign. It creates the planned messages and sets the schedule. Skylar writes what each message says, picks the timing, and chooses who gets it. Claude (the AI) can suggest wording or fill in personalization, but Skylar is always the author and the one who kicks it off.
👤 Skylar runs /enroll ·🤖 Claude assists if askedEvery message needs a real human to approve it before it can go anywhere. Nothing sends on its own. If Skylar says no, the message disappears. If Skylar says yes, it gets scheduled. Creation = approval. No exceptions.
👤 Skylar must approve every sendThe Worker — a tiny robot program that runs in the cloud every 60 seconds — sees the approved message and sends it at the right time. It uses SignalHouse (our phone service) to actually deliver the text. Like a very reliable postal worker who never sleeps.
⚡ Worker + SignalHouse handle deliveryWhen the lead replies, the Worker catches the incoming message and logs it in Attio immediately. All future texts to that person are put on hold until Skylar reads the reply and decides what to do next. A reply could mean anything — the machine doesn't guess, a human decides.
⚡ Worker logs it ·👤 Skylar decides next moveIf the lead says stop, unsubscribe, opt out, or anything like it — they are removed from every channel instantly and permanently. No one can override this. Not Claude, not Skylar. It's built into the code.
🛑 Blocked forever on all channelsSix main parts. Each one has exactly one job. They talk to each other but can't do each other's jobs.
15 rules across 3 groups. These aren't suggestions — they're written into the code. Three groups: rules that protect the lead, rules that keep humans in charge, and rules that keep data clean.
🛡️ Group 1 — Protect the lead (machine enforces these automatically)
Text, call, or verbal — any opt-out blocks that person on every channel instantly and permanently. Even "stop" said out loud on a call is caught from the call transcript. No override. No undo.
The moment a lead writes back, all future messages are frozen instantly. The machine doesn't guess what it means. It waits. A human reads it and makes the call.
Before every text, the Worker runs a full checklist: opted out? Business hours? Reply pending? Daily cap hit? All must pass. One fail = no send. Always.
Weekdays, 9 am–5 pm in the lead's local time zone. A message due at 7 pm waits until 9 am next morning. Checked every single send.
Hard limit on texts per day. Once hit, the machine stops sending entirely — no override. Prevents a bug from blasting hundreds of people accidentally.
Every message has a unique ID. The Worker checks before sending — if it's already gone, it skips. A bug or retry can never double-text a lead.
✋ Group 2 — Keep humans in charge (machine helps, humans decide)
When Skylar runs /enroll (the command that adds a lead to a campaign), that act is the approval for the whole sequence. The Worker then runs each step automatically — no per-message clicking needed.
Skylar runs this command daily. It surfaces every frozen lead, every unread reply, every waiting decision. If she skips it, frozen leads stay frozen safely — nothing moves without her.
Claude writes messages and suggests next steps. Humans review anything consequential — a new campaign, a hot reply, an unusual situation. The AI does the legwork; the human makes the call.
If a rep hits a bug, they stop. Don't work around it. File a bug report in GitHub Issues (the to-do tracker) and wait for admin to fix it right.
One designated safe test number exists. All test sends go there only. A real lead's number is never used to test anything. Full stop.
The screen reps use (the Desk) holds no passwords or API keys. All keys live backstage in the Office. The Desk is fully untrusted — by design.
🗂️ Group 3 — Keep data clean (where things live and who sees what)
Any info about a real lead lives in Attio (the CRM database). Don't copy it into a doc, a chat, or a spreadsheet. It will go stale. Trust the CRM.
Rules, plans, specs — anything that needs to survive past a chat window goes in the GitHub repo (the code home). Not in a Slack message or someone's head.
Every rep sees only their own leads. The system blocks access to anyone else's book. "That's not your lead" — and it means it.
The engine is simple: a Worker that runs every 60 seconds + Attio memory + Claude brain + any provider we plug in. That unlocks a lot. Here's the full picture — what's live, what's coming, and what's possible the moment we wire it up.
Write it, schedule it, send it. Personalized per lead. Delivered by SignalHouse.
Record a short video on this machine with Cap, send it via text link. Feels personal — because it is.
System dials via SignalHouse. Call logged in Attio automatically.
⚠️ Autodialer (fully automated dialing without a rep clicking) still needs full end-to-end testing.
Smartlead (our email tool) is live. Sequences are being finalized. The only thing left is completing the inbox warmup period — after that, ready to go live.
⚠️ What's left: Complete email inbox warmup. Then go live.
Drop a pre-recorded audio message straight into their voicemail — no ringing, no awkward silence.
Trigger a printed postcard to a lead's address using a service like Lob. Stands out in a noisy inbox world.
A reply instantly freezes all future texts to that lead. Waits for Skylar to read and decide. Never assumes what a reply means.
A multi-step plan: text day 1, video day 4, follow-up day 10. Enrolled once — the Worker runs it automatically until a reply or the last step.
Fire a message on a specific date — seasonal check-in, "heading into peak season," or an anniversary of when they first reached out. The Worker checks every 60 seconds and sends any message whose date has arrived.
Leads that went cold 60+ days ago automatically get a fresh outreach — different message, different angle. Wake up the dead list.
Send version A to half a group, version B to the other half. The testing part is built. Automatic winner rollout (machine picks best and switches to it) is not yet implemented. Live end-to-end test still needed before this is production-ready.
⚠️ What's left: Build auto-winner rollout. Run a live end-to-end test across a real campaign.
Connect Calendly (scheduling tool) so when a lead says "yes" to a call, they get a booking link instantly — no manual back-and-forth.
Machine creates a to-do: "call Sarah today." Rep clicks, system dials. Call logged automatically in Attio.
Same as the call task — but queues a text instead. "This lead hasn't heard from us in 14 days. Text them today."
Queue a reminder: "Record a personal Cap video for this lead today." Opens Cap pre-loaded with context on who you're recording for.
"Check in with Mike in 30 days." Machine pings you on day 30. You decide what to do — text, call, or skip.
Machine queues: "Send this lead a gift card or Amazon item." Connect a gifting service and it ships automatically on approval.
Machine finds the lead's LinkedIn and queues a connection request task for the rep. Multi-channel without doing it manually.
Claude reads every reply and auto-detects "stop," "remove me," "wrong number," or call refusals. Acts immediately — no human needed.
AI reads a reply and suggests what it means: "Interested," "Not now," "Wrong number," "Hot lead." Skylar sees the suggestion before deciding.
AI gives each lead a score based on their profile: listing count, market, engagement history. Focus energy on the hottest prospects first.
Auto-generate a "what's happening in your market" snapshot for a lead's city. Send it as a value-add before asking for a call.
Calculate what Leveled could earn this specific owner based on their listings and market. Personalized proof point baked into the first message.
After running A/B tests across campaigns, Claude learns which messages work best for which markets and lead types — and uses that automatically.
Claude reads through past conversations and flags leads you should have followed up on but didn't. "This person seemed interested 3 weeks ago and nothing happened." Surfaces hidden revenue sitting in the existing book.
⚠️ What's left: Build the conversation analysis logic. Define what "missed opportunity" looks like in code.
Claude listens to call recordings and reads outreach history, then gives specific coaching: "You always lose momentum on the 3rd follow-up — here's why and what to say instead." Gets smarter the more calls and messages it analyzes.
⚠️ What's left: Wire call recordings into the analysis pipeline. Build the coaching output format.
Skylar runs /start-sales each morning — a pre-built checklist showing every frozen lead, every reply to read, every message waiting for a decision. One screen, 60 seconds.
⚠️ What's left: Formalize the daily review flow fully. Live testing to confirm it shows everything Skylar needs.
For any campaign: how many enrolled → sent → replied → booked. See exactly where leads drop off.
⚠️ What's left: Build the report renderer. The JSON data contract is already spec'd — needs the display layer built.
See every lead and where they are: Initial Contact → Engaged → No Response → Lost. Across all campaigns at once.
⚠️ What's left: Build the pipeline report renderer. Same as campaign funnel — data contract is spec'd, display layer needed.
Tracks the key numbers across the whole acquisition process — reply rate, book rate, cost per booked call, best-performing market, best-performing message type. Then surfaces the single highest-value move: "If you fix X, you get the most new clients for the least effort."
⚠️ What's left: Define which metrics matter most. Build the calculation layer. Build the "highest-value move" recommendation output.
A "campaign" is a named outreach plan — a group of leads, a series of messages, a goal. Here's how to set one up so it actually works.
Before you launch — the checklist
Personalization — make every message feel one-on-one
Use merge tags — little placeholders that get swapped out for each lead's real info when the message sends. Write one message, send a thousand personal ones.
Name tags
{{first_name}}
→ "Hey Sarah, ..."
{{full_name}}
→ "Hi Sarah Johnson"
Market & location tags
{{market}}
→ "owners in Newport Beach"
{{city}}
→ "your place in Scottsdale"
Property tags
{{listing_count}}
→ "you manage 3 listings"
{{platform}}
→ "your Airbnb" or "your VRBO"
Conditional block — show different text per group
Example — what a personalized first text looks like
Message template (what Skylar writes)
What the lead actually receives
Real example — what a full campaign looks like
Campaign name: Newport Beach Cold Outreach — Target: STR owners in Newport Beach with 3+ listings and no prior contact.
⚡ Drip pace — how many NEW leads start each day
Drip means starting new leads gradually instead of kicking off all 1,000 at once. Example: load 1,000 Newport Beach leads, then start 25 new leads each day — all 1,000 would be in motion after 40 days. Follow-up texts for already-started leads keep running alongside the new ones, so 25 new leads/day is not the same as only 25 texts sent that day. Here's why pacing matters:
25 new leads/day = a trickle of replies to handle. 1,000 at once = an unworkable flood the same week.
Phone carriers (AT&T, Verizon, etc.) flag numbers that send hundreds of texts at once as spam. A steady drip keeps you off their radar.
Each reply gets real attention instead of getting lost in a pile. Fewer leads in flight = better conversations.
Load 1,000 leads. Set a daily start rate — say 25. The system automatically kicks off 25 new leads each day and runs their sequences on its own. Follow-ups for earlier leads run alongside. You manage the reply volume, not the sending schedule.
Skylar types /enroll in the terminal to add the Newport Beach leads to this campaign. Enrollment = approval. Once enrolled, the system runs automatically — no per-message OK needed.
"Hey {{first_name}} — saw you're managing a place in {{market}}. I help STR owners there maximize revenue without more work. Worth a quick 15-min call?"
Worker fires within 60 seconds of enrollment. Consent gate checked. Logged in Attio. Stage → Initial Contact.
Terminal queues a call task: "Call {{first_name}} — followed up by text Day 0, no reply yet." Rep sees it in their calling session list, dials when ready, logs the result.
This step does NOT fire automatically. It appears as a task in the terminal. Rep decides when to work through it.
"Hey {{first_name}}, just circling back — I work with a handful of STR owners in {{city}} and have been able to bump their revenue 15–20%. Would love to show you what that looks like for your place."
Only sends if no reply has come in. A reply at any point freezes all future auto-sends for that lead.
Terminal queues a video task: "Record a short personal video for {{first_name}} — reference their {{listing_count}} listings." Rep records in Cap (a video tool), pastes the link into a text, sends manually.
High-touch step. Personal video converts better than another text. Rep controls timing.
"Hey {{first_name}} — last note from me. If the timing's ever right to chat about your {{market}} properties, I'm here. No pressure at all."
Campaign ends after this. No reply → stage moves to No Response. A reply at any point → stage moves to Engaged, auto-sends freeze, Skylar reviews.
The moment a lead replies, all remaining auto-sends for that lead freeze instantly. Stage → Engaged. Skylar reviews the reply in /start-sales (the daily morning command) and decides the next move — book a call, send a custom reply, or mark them lost.
Everything has one home. Put it in the right place and the whole machine stays clean.
Where things live
Every lead's name, phone, history, replies, and opt-out status. If it's about a real person, it lives here. Attio is always the source of truth.
If something is broken or needs to be built, it becomes a GitHub Issue (a to-do ticket). Not in a chat message. Not in someone's memory. In the tracker.
When the system fires an alert — a reply came in, something failed, or the daily health check runs — it goes to Discord. That's where the team stays in the loop.
The daily rhythm (what Skylar does each morning)
Golden rules for staying clean
These are the exact words we use in this system. Use them the same way every time so nothing gets lost in translation.
The 4 Stages a Lead Can Be In
People
Any human contact stored in the CRM. The raw record. Not yet being worked for a sale.
Don't say: contact, record, prospect
A Person we're actively trying to close. Someone being worked right now for a sale.
Don't say: prospect, deal
The full list of Leads a rep is allowed to work. Your assigned territory.
Don't say: assigned records, territory list
The rep who is responsible for a specific Lead. One lead, one owner at a time.
Don't say: assignee
A user who can see the whole team's Book and move Leads from one rep to another.
Don't say: admin (when talking to reps)
Someone with access to the code but no Badge (sign-in). Can only use Practice mode — no real data.
Don't say: unauthorized user
Work
Any recorded interaction with a Lead — a text sent, a call made, a note logged. The history.
Don't say: touch (to reps), event
The next approved action queued up for a Lead. "Text them on Thursday." One lead has one next step at a time.
Don't say: planned touch, task payload
Moving a Lead from one rep to another. Logged in the Paper Trail so nothing is lost.
Don't say: share, transfer
The full conversation tied to one Lead and their current Owner. One thread per lead.
Don't say: chat context, last conversation
One named outreach effort — a target group, a message shape, and a channel (text, email, etc.).
Don't say: blast, batch, run
A reusable message shape — like "first contact" or "follow up after 14 days." A template you run again and again.
Don't say: module, workflow template
The defined group of People a Campaign is targeting. "All STR owners in Phoenix with 3+ listings."
Don't say: segment (to reps)
Access & System
The terminal — the command-line tool where a rep runs the CRM. Type commands here to do anything in the system.
Don't say: CLI, client app
The back-end API — the trusted server that holds keys, enforces rules, and talks to SignalHouse and Attio.
Don't say: backend, Cloudflare Worker (to reps)
Your 7-day CRM sign-in. Proves who you are. The Office checks it on every command to confirm your access.
Don't say: token, credential, API key
Fake data and safe commands. Use this to train or test. Nothing in Practice can reach a real person.
Don't say: staging, fixtures
The automation that safely moves messages. The Cloudflare Worker that runs every 60 seconds and sends due texts.
Don't say: plumbing (for a specific send path)
The internal log of every change and every denied action. If something happened in the system, it's here.
Don't say: audit log (to reps)
A calling session is a focused block of time where a rep works through a list of leads by phone. One rep. No auto-dialing. The rep is in control of every call.
The terminal — the command-line tool the rep uses — shows a list of leads. Each lead has their name, phone number, and current pipeline stage (like "Initial Contact" or "No Response"). The system suggests who to call first. The rep decides who they actually want to call.
👤 Rep decidesThe rep copies the lead's phone number and pastes it into the browser dialer page. The page immediately shows that lead's details — name, stage, history — right next to the dial button. Any number can be dialed unless it matches a do-not-contact record — those are blocked automatically before the call connects.
🤖 DNC check automaticOne click dials via SignalHouse (our phone provider). The rep talks to the lead. That's it — no scripts required, no recordings yet. Just a real conversation.
👤 One rep onlyAfter hanging up, the rep saves three things: a call result (answered, no answer, left voicemail, etc.), an optional note (what was said), and the new stage for that lead (pre-filled by the system, editable by the rep).
After each call or at the end of the full session, the rep goes through everyone they spoke to and sets next steps. This is where the call turns into action — a follow-up text, another call in 3 days, a meeting booked, or marking them lost.
Option A — Close the loop after each call: Log result, set next step, move to next lead.
Option B — Close the loop after the full session: Power through all calls first, then go back and schedule next steps for everyone at once.
Hard rules for every calling session
One rep only. No shared dialing. Each session belongs to one person.
No auto-dialing. The rep clicks every call. Nothing dials on its own.
No auto follow-up sends. After the call, the rep sets next steps — nothing sends without approval.