Outreach based on Slack membership
Membership in a Slack community is the qualification, so everyone in it is in scope, resolved by name and corroborated against their own words.
- TriggerTriggered
Weekly schedule
- CompletedSlack
Extract the roster
- CompletedSlack
Mine the #introduction channel
- Completed
SerperResolve identity
- Completed
FullEnrichEnrich, reject mismatches
- CompletedClaudeChatGPT
Segment and write
- Completed
Load the campaign
A community roster looks like a ready-made list and almost never is — most profiles carry a handle and nothing else, and pulling the list at all usually means scripting around a virtualized member panel that quietly stops rendering new rows the moment you stop scrolling by hand.
The real list is smaller and takes real work to build: mining the handful of members who introduced themselves properly, resolving the rest by name, and rejecting every match and every email that doesn't actually corroborate who the person said they were. What's left is a roster where membership itself is the qualification — nobody gets filtered out for being the "wrong" kind of member, they just get written to differently.
What you get
A staged, segmented campaign built from a community's own roster, every match corroborated and every email checked against what the person actually said about themselves, ready for a person to launch.
The part worth getting right
Treating membership as the whole qualification, instead of filtering by your own read of fit, is what keeps the list honest to its source. An investor, a solo founder, and an agency owner all belong in a community about the same category — filtering any of them out on a hunch throws away exactly the people the source already qualified for you.
Rejecting an email that doesn't corroborate what the person actually said about themselves is the check that's easy to skip and expensive to skip. Enrichment tools return a person's current employer, which isn't always the company they introduced themselves as — sending to the wrong address at the wrong company reads as sloppy in a way a missed contact never does.
Never referencing the source community in the copy itself is what keeps this from reading as surveillance. Members expect to see other members; they don't expect a cold email that proves someone was scraping the member list, and a single sentence that implies it costs the whole message its credibility.
The prompt
The real prompt behind the steps above — detailed enough that an agent with a people-search tool, email/phone enrichment, and CRM access can run it as written.
# Turn a community's member list into a campaign
You have access to web search and an email-enrichment tool, plus
browser access to the community itself (a Slack workspace, a forum, a
user group — anywhere members post in their own words). Run this
against **[the community you're a member of, and the segment it maps
to]**.
## 0. Set up (skip if you're already connected)
If you don't already have live tool access for this, connect it first
— this prompt is only as real as the tools behind it:
1. Create a free account at app.tulina.ai.
2. Add Tulina's MCP server to your assistant: https://mcp.tulina.ai/mcp
3. In Tulina, connect your own API keys for the tools this prompt uses
— web search and email enrichment.
Once connected, your assistant has real tool access and the rest of
this prompt runs as written.
## 0b. Already on Tulina? Three things around the run
An account and the MCP server are not the whole setup. Two of these come
before the run below and one after it, and together they turn this from a
one-off answer into a process your workspace keeps:
1. **Activate this process's connectors first.** Call
`oto_connector(op="list")`, match it against the tools named in step 3
above, and `oto_connector(op="select", name="...")` every one that
isn't active yet. Selecting a connector does not mount its tools in the
conversation you're already in — reach them through `oto_call` for this
run, or open a fresh conversation once they're all on.
2. **Attach the work to an existing project.** `oto_project(op="list")`
shows your active org's projects: pick the one this work belongs to
rather than opening another, and keep its id. The project is where this
process, the tables it writes to and the connectors it uses hang
together.
3. **When the run is done, save it as a process — with its graph.** Write
the body with `oto_procedure(op="set", ...)`, then attach it with
`oto_project(op="link", project_id=..., target_type="procedure",
target_ref="<your slug>")`. The body has to carry a drawing: read
`oto_guide(op="read", slug="procedure-flowchart")` and follow it
exactly — ONE untagged fenced block in that grammar, opening with the
trigger and a quoted example of what you'd type to start a run. Tulina
parses that drawing back into the graph it renders as the process's
default view, which is what makes it come out in the same style as
every other process in the app; a drawing the grammar can't read falls
back to raw characters instead. Saving a process needs org-admin
rights — without them, hand the finished body to someone who has them.
**Rule zero: membership is the qualification.** Don't filter the roster
by your own read of fit — a solo founder, an agency owner, and an
investor are all in scope; they get different copy, not a smaller list.
The only two legitimate gates are: can this person actually be
identified and reached, and is there a conflict (they work for a
competitor, they're already a customer, they're already in a live
campaign).
## 1. Extract the roster, and expect it to disappoint
Membership lists in chat tools are usually virtualized — only the
visible rows exist in the page at any moment, and the rest render in as
you scroll. **A script that sets scroll position programmatically often
scrolls a list that never actually redraws**, especially in a
browser-automated background tab, and silently re-reads the same
handful of rows forever. Clicks and screenshots keep working, which
makes the failure easy to miss. A real scroll event (a wheel event, not
a position jump) is what forces the list to repaint — loop: scroll,
read what's rendered, repeat.
Expect the raw roster to be thin: most member profiles carry a handle,
not a full name, and no company or title at all. That's expected — the
next step is where the real signal comes from.
## 2. Mine the #introduction Slack channel first
Most communities like this have an #introduction Slack channel, or a
thread serving the same purpose, where members state their own name, company, and what they do in plain prose.
That text is both the resolution key and the personalization source —
a bare handle is nearly unfindable, but "hi, I'm [name] from [company],
I do [role]" resolves in seconds and gives you a real detail to write
from.
Work the #introduction channel first, in full, before touching the rest of the
roster — it's a small fraction of the community but by far the highest
quality. Then work the rest of the roster as a second, higher-volume
pass with name-only search; it resolves far fewer people per hour, but
meaningfully grows the list beyond the #introduction channel alone.
## 3. Resolve identity — reward corroboration, not confirmation
Search each name (with their stated company, where you have one) for a
professional profile match. For roster-only people with no stated
company, the search result's own headline (name, role, employer) often
becomes the entire personalization source — capture it.
Accept a match only when something about it actually corroborates the
person — matching company, matching role, matching context — not just a
name that happens to match. Where two plausible profiles exist for the
same name and neither one corroborates, treat it as unresolved rather
than guessing. **Prefer no match to a weak one.**
## 4. Enrich email, and reject anything that doesn't corroborate
Enrich the resolved profile for a work email. Ask for email only, not
phone, unless you specifically need it — phone lookups typically cost
far more credits per hit.
Enrichment tools return the person's **current** employer's domain,
which isn't always the company they introduced themselves as. Someone
who described a side project or a new venture in the community may
still get an email at their day job. **Reject any email whose domain
doesn't match what the person actually said about themselves** — a
meaningful share of matches fail this check, and sending to the wrong
address at the wrong company is worse than not sending at all.
## 5. Segment, then write to each group's real problem
Group resolved people by role type — founders, in-house operators,
agencies/consultants, investors are common splits — since they don't
share a problem and a single angle won't land for all of them. Agencies
in particular are often a partnership opportunity rather than a direct
buyer; treat that as a different message, not a smaller version of the
same one.
Write two short sentences per opener, using the person's own words from
step 2 or 3 wherever you have them. Check each one with a simple test:
swap in a different person from the same segment — if the line still
reads true, it isn't personalization yet, it's a segment description.
**One hard constraint on the copy itself: never reference the community
the list came from, and never assert what tool the person uses based on
their membership in it.** A fact about your own product is fine to
state; an inference about their behavior, drawn only from where you
found them, isn't — there's no innocent way to know it, and naming the
source erodes trust in one line.
## 6. Load the campaign, ready for a person to launch
Before creating anything, check what's already sending — list live
campaigns and their enrolled people, and skip anyone already enrolled
elsewhere targeting a similar audience rather than adding them again.
Load each segment into its own track with its own copy. Verify the
personalization landed — spot-check a few loaded rows against what you
intended to send. Then stop: stage everything for review, and never
call a send or launch action. A person reviews drafts by segment and
launches from there.
## Output
Report: how many members extracted from the roster, how many resolved
through the #introduction channel vs. the wider roster, how many passed
identity resolution, how many emails were rejected for not corroborating
the person, the segment breakdown, and the campaign staged for review.
Questions about this process
Related processes
- Build a target list from a sentence
Describe the companies you want in one sentence, and get them sourced, scored on dated signals, enriched, deduplicated against your CRM, and staged as a campaign.
- Outreach based on government data
Every candidate's website is verified before a credit is spent, tiered by signal strength, then written one grounded opener that is checked for repetition.
- Prepare for a demo from the last call
The last calls, the deal's state, and fresh research become one prep brief, plus a deck built around that company's own use cases, posted before the meeting.