cold-email-outreach について
Supabaseの条件に合うリードをコールドメールキャンペーンへつなげるスキルです。対象選定、メールシーケンス作成、キャンペーン設定、記録までを扱い、SmartleadではMCPで自動化し、ほかのツールではCSVとインポート手順を用います。
主な機能
- 01Supabaseからリードを絞り込み
- 0284日間の連絡クールダウンを適用
- 03メールシーケンスの計画とレビュー
- 04Smartleadキャンペーン設定の自動化
- 05各ツール向けCSVのエクスポート
- 06アウトリーチ記録のSupabaseへの保存
活用シーン
- 01レビュー済みのSmartleadキャンペーンを開始
- 02Instantly、Lemlist、Apollo向けCSVの準備
- 03キャンペーンの連絡履歴とクールダウンの追跡
MCP 対応
SmartleadではMCPツールを使い、メールアカウントの一覧、キャンペーン作成、シーケンスや設定の構成、リードの登録、承認後の開始を行います。それ以外のアウトリーチツールではCSVをエクスポートします。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nikiandr/ goose-skills --skill cold-email-outreachインストール後、Claude Code で/cold-email-outreachを入力して読み込まれたか確認します。
同梱ファイルskill.meta.json
詳細
コールドメールのアウトリーチ
アウトバウンドパイプラインの最終段階です。Supabase から条件を満たすリードを取得し、email-drafting スキルを使ってメールシーケンスを作成し、ユーザーが選択したアウトリーチツールにキャンペーンを読み込み、すべての情報を Supabase に記録します。
ツールに依存しません: ユーザーが使用しているアウトリーチプラットフォームを尋ねます。MCP ツールが設定されている場合は、Smartlead をデフォルトとして使用します。それ以外のツールや手動のワークフローでは、CSV エクスポートに切り替えます。
自動読み込みのタイミング
次の場合にこのスキルを読み込みます。
- ユーザーが「キャンペーンを開始して」「アウトリーチを送信して」「これらのリードにメールして」「コールドメールを設定して」と言った場合
- 上流のスキルが「メールキャンペーンを作成して」と連携する場合、または「passes: supabase-eligible-leads」を渡す場合
- ユーザーが
lead-qualificationを完了し、その結果に基づいて行動したい場合
対応するアウトリーチツール
このスキルは特定のツールを前提としません。まずユーザーに尋ね、その後、選択に応じて対応します。
| ツール | 統合 | 動作 |
|---|---|---|
| Smartlead(デフォルト) | MCP ツール(mcp__smartlead__*) | 全自動:キャンペーンの作成、シーケンスの追加、リードのインポート、スケジュールの設定、開始 |
| Instantly | CSV インポート | Instantly のインポート形式に合わせた CSV を生成し、ユーザーが手動でアップロード |
| Lemlist | CSV インポート | Lemlist 互換の列を含む CSV を生成 |
| Apollo | CSV インポート | Apollo のシーケンスインポート形式に合わせた CSV を生成 |
| 手動/その他 | CSV +手順 | リードとメールを汎用 CSV としてエクスポートし、設定手順を提供 |
ツールの選択ロジック:
- フェーズ 0 でユーザーに「どのアウトリーチツールを使っていますか?」と尋ねます。
- Smartlead の場合 → MCP ツールを使って全自動で処理します
- Instantly/Lemlist/Apollo の場合 → 各ツール専用のインポート CSV を生成します
- その他または不明 の場合 → 汎用 CSV(各タッチにつき
email、first_name、last_name、company、title、subject、body)を生成し、使用するツールのインポート要件をユーザーに尋ねます
前提条件
Supabase
tools/supabase/schema.sql のスキーマに従って、人物データが Supabase に保存されている必要があります。people テーブルと outreach_log テーブルが存在している必要があります。新規にセットアップする場合は、python3 tools/supabase/setup_database.py を実行してください。
.env 内の環境変数:
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJ...
アウトリーチツール
- Smartlead:
mcp__smartlead__*経由で MCP ツールを利用できます。追加のセットアップは不要です。 - その他すべて: CSV エクスポートのみが必要です。API キーは不要です。
フェーズ 0:情報収集
すべての質問をまとめて尋ねます。カテゴリ別に整理します。上流のスキルですでに回答済みの質問は省略します。
キャンペーンの目標
- 目的は何ですか?(ミーティングの予約、デモのリクエスト獲得、返信の獲得、関係構築)
- アウトリーチの切り口やフックは何ですか?(採用の兆候、競合からの乗り換え、イベントに基づくもの、課題に基づくもの、コールドデータベース)
- このキャンペーンの名前は何にしますか?
アウトリーチツール
- どのアウトリーチツールを使っていますか?(Smartlead/Instantly/Lemlist/Apollo/その他/CSV だけでよい)
リードの選定
- どのリードを対象にしますか?選択肢:
- 特定の
client_nameのすべてのリード - 特定の
icp_segment - 役職のパターン(例:「VP Operations」「Director of Sales」)
- 業界または所在地のフィルター
- しきい値を超える
qualification_score - 特定の
source(crustdata、apollo、linkedin など) - カスタムフィルター(条件を説明してください)
- 特定の
- 除外する対象はありますか?(特定の企業、最近連絡したリード、特定の役職)
- キャンペーンの最大規模は?(デフォルト:200)
シーケンスの設計
- タッチ数はいくつですか?(デフォルト:3)
- タッチの間隔は?(デフォルト:1 日目/5 日目/12 日目)
- パーソナライズのレベルは?(レベル 1:差し込みフィールドのみ/レベル 2:セグメント別/レベル 3:リードごとに個別作成)
送信設定(CSV エクスポートの場合は省略)
- どのメールアカウントから送信しますか?(アカウントの一覧、または「利用可能なすべてを使う」)
- 送信スケジュールは?(デフォルト:受信者のタイムゾーンで月曜~金曜の午前 8 時~午後 5 時)
- アカウントごとの 1 日あたりの送信上限は?(デフォルト:1 日 30 件)
- 開封とクリックを追跡しますか?(デフォルト:開封は追跡、クリックは追跡しない)
フェーズ 1:Supabase からのリード選定
接続
共有 Supabase クライアントを使用します。
import sys, os
sys.path.insert(0, os.path.join("tools", "supabase"))
from supabase_client import SupabaseClient
client = SupabaseClient(os.environ["SUPABASE_URL"], os.environ["SUPABASE_SERVICE_ROLE_KEY"])
フィルターの構築
ユーザーの条件を、people テーブルの PostgREST クエリパラメーターに変換します:
| ユーザーの条件 | PostgREST フィルター |
|---|---|
| 「VP Operations」 | title=ilike.*VP Operations* |
| クライアント「happy-robot」 | client_name=eq.happy-robot |
| スコア > 7 | qualification_score=gte.7 |
| メールアドレスが確認済み | email_verified=eq.true |
| 業界「logistics」 | industry=ilike.*logistics* |
| 所在地「San Francisco」 | location=ilike.*San Francisco* |
| ソース「crustdata」 | source=eq.crustdata |
| 84日間連絡していない | or=(last_contacted.is.null,last_contacted.lt.{84_days_ago}) |
クールダウンフィルター(必須)
必ず、84日以内(12週間以内)に連絡した人を除外してください。これは任意ではありません。
共有クライアントの check_cooldown() メソッドを使用します:
in_cooldown = client.check_cooldown(client_name="happy-robot", cooldown_days=84)
# Returns set of person_id strings still in cooldown
または、直接クエリします:
outreach_logをクエリして、過去84日以内のsent_dateを持つperson_idを取得します:GET /rest/v1/outreach_log?select=person_id&sent_date=gte.{84_days_ago}&status=neq.bounced&client_name=eq.{client}- それらの
person_idを除外セットにまとめます peopleクエリにid=not.in.({excluded_ids})を追加します
提示して確認
サンプルテーブル(10~15件のリード)を表示します。以下を含めてください:
- 名前、役職、会社、業界、スコア、メールアドレス、最終連絡日
ユーザーに、対象となるリードの合計数、クールダウンにより除外された数、メールアドレスが確認済みの数を伝えます。
続行する前に、フィルターの確認または調整をユーザーに求めます。
フェーズ 2:シーケンスの設計
コピーを作成する前に、シーケンス案を表形式で提示します:
| タッチ | 日 | メールの種類 | フレームワーク | CTA |
|---|---|---|---|---|
| 1 | 1 | コールドイントロ | Signal-Proof-Ask | 15分の通話 |
| 2 | 5 | 新しい切り口/資料 | PAS | リソースの案内 |
| 3 | 12 | ソーシャルプルーフ | BAB | お話しできますか? |
フェーズ 3 でコピーを生成する前に、構成についてユーザーの承認を得ます。
フェーズ 3:メールの生成
email-drafting スキルを読み込み、次の情報を渡します:
- キャンペーンの背景(目標、切り口、製品、実績を示す要素)
- フェーズ 2 で決定したシーケンス構成
- 選択したリストからのサンプルリード 3~5 件
- パーソナライズのレベル
- 希望するトーン
パーソナライズのレベル別
レベル 1(汎用): 各タッチにつき、差し込みフィールド({first_name}、{company}、{title})を含むテンプレートを 1 つ生成します。すべてのリードに同じテンプレートを使用します。
レベル 2(セグメント): セグメントごと、タッチごとにテンプレートを 1 つ生成します。セグメントは役職、業界、シグナルの種類で定義します。セグメント間で課題と実績を示す要素を切り替えます。
レベル 3(詳細): リードごと、タッチごとに個別のメールを生成します。上限は 50 件です。それを超える場合は、レベル 2 を推奨します。
レビューループ
- まず 3~5 件のリード向けにサンプルメールを生成します
- ユーザーに提示してレビューしてもらいます
- 承認されるまで反復します(最大 3 回)
- 承認後、残りのメールを生成します
フェーズ 4:キャンペーンの設定
Smartlead の場合(MCP による自動化)
MCP ツールを使用して、完全に自動化します。次の順序で実行します:
ステップ 1:メールアカウントの一覧表示
mcp__smartlead__get_email_accounts
利用可能なアカウントを提示します。ユーザーに使用するアカウントを選択してもらいます。
ステップ 2:キャンペーンの作成
mcp__smartlead__create_campaign
name: {campaign_name}
返された campaign_id を保存します。
ステップ 3:シーケンスのステップを追加
mcp__smartlead__save_campaign_sequences
campaign_id: {campaign_id}
sequences: [
{ seq_number: 1, subject: "...", email_body: "...", seq_delay_details: { delay_in_days: 0 } },
{ seq_number: 2, subject: "...", email_body: "...", seq_delay_details: { delay_in_days: 4 } },
{ seq_number: 3, subject: "...", email_body: "...", seq_delay_details: { delay_in_days: 7 } }
]
マージ変数のマッピング: {first_name} → {{first_name}}、{company} → {{company}} に変換します(Smartlead では二重波括弧の構文を使用します)。
ステップ 4:リードのインポート(1 回につき 100 件)
mcp__smartlead__add_leads_to_campaign
campaign_id: {campaign_id}
lead_list: [{ email: "...", first_name: "...", last_name: "...", company_name: "...", ... }]
リードが 100 件を超える場合は、100 件ずつのグループに分けます。
ステップ 5:送信アカウントの割り当て
mcp__smartlead__add_email_accounts_to_campaign
campaign_id: {campaign_id}
email_account_ids: [...]
ステップ 6:スケジュールの設定
mcp__smartlead__update_campaign_schedule
campaign_id: {campaign_id}
schedule: { ... }
ステップ 7:設定の構成
mcp__smartlead__update_campaign_settings
campaign_id: {campaign_id}
settings: { track_opens: true, track_clicks: false, stop_on_reply: true }
CSV ベースのツールの場合(Instantly、Lemlist、Apollo、その他)
ステップ 1:CSV を生成する
列はパーソナライズのレベルによって異なります。
レベル 1(全員に同じテンプレートを使用):
- CSV の列:
email、first_name、last_name、company、title、custom_field_1(シグナル/フック) - シーケンステンプレート(件名+差し込みフィールドを含む本文)は別ファイルにします
レベル 2/3(セグメント別またはリード別のメール):
- CSV の列:
email、first_name、last_name、company、title、touch_1_subject、touch_1_body、touch_2_subject、touch_2_body、touch_3_subject、touch_3_body
ステップ 2:ファイルを保存する
skills/cold-email-outreach/output/{campaign-name}-{YYYY-MM-DD}.csv
ステップ 3:ツール固有のインポート手順を提示する
Instantly:
- CSV をアップロード → Sequences → Create new sequence
- 列を対応付けます:Email → email、First Name → first_name など
- 各ステップにシーケンステンプレートを貼り付けます
- ステップ間の遅延を設定します
Lemlist:
- People → Import → Upload CSV
- カスタム変数を列に対応付けます
- キャンペーンを作成 → メールのステップを追加 → 変数を挿入します
Apollo:
- Sequences → Create Sequence → メールのステップを追加
- Contacts → Import → Upload CSV
- インポートした連絡先をシーケンスに追加します
その他/手動:
- CSV のパスを提示し、列の構成を説明します
- ツールで必要な形式をユーザーに確認し、必要に応じて調整します
フェーズ 5:確認と開始
キャンペーンの概要を提示します。
Campaign: {name}
Leads: {count}
Sequence: {touches} touches over {days} days
Sending: {accounts} accounts × {daily_limit}/day = {daily_volume} emails/day
Estimated completion: {date}
Tool: {smartlead/instantly/etc.}
開始前の必須承認
ユーザーの明示的な確認なしにキャンペーンを有効化してはいけません。 概要を提示してから、次のように尋ねます:「開始してよろしいですか? 有効化するには「yes」と入力してください。」
- Smartlead:
mcp__smartlead__update_campaign_status→ ステータスを active に設定 - CSV ツール: ファイルをインポートできる状態であることをユーザーに伝え、ファイルのパスを提示します
フェーズ 6:追跡とログ記録
データベース書き込みポリシー
このフェーズでデータベースに書き込むには、すべてフェーズ 5 の開始ゲートでユーザーから事前承認を得る必要があります。 フェーズ 5 の承認(「開始してよろしいですか?」)は、キャンペーンの有効化とその後のログ記録の両方を対象とします。ただし、キャンペーンを CSV としてエクスポートした場合(Smartlead で開始していない場合)は、ログを記録する前にユーザーに確認してください。まだインポートまたは送信していない可能性があります。
Supabase にログを記録する
開始後(またはエクスポート後)、outreach_log にレコードを挿入します。
POST /rest/v1/outreach_log
Prefer: return=minimal
[
{
"person_id": "{person_uuid}",
"campaign_name": "{campaign_name}",
"external_campaign_id": "{smartlead_campaign_id or null}",
"channel": "email",
"tool": "{smartlead/instantly/lemlist/apollo/manual}",
"sent_date": "{ISO timestamp}",
"status": "sent",
"client_name": "{client_name}"
},
...
]
または、共有クライアントを使用します。
client.log_outreach(entries)
CSV ベースのツールの場合: status = "exported" として記録します。ユーザーがツールでキャンペーンを開始したと確認した時点で "sent" に変更します。
People レコードを更新する
このキャンペーンに含まれるすべての人物について、people テーブルの last_contacted を更新します。
PATCH /rest/v1/people?id=in.({person_ids})
{ "last_contacted": "{ISO timestamp}" }
概要を提示する
{count} people logged to outreach_log
last_contacted updated for {count} people
Campaign ID: {id}
Cooldown active until: {date + 84 days}
Next eligible re-contact: {date}
クールダウンの適用ルール
このスキル全体で使用するクールダウンロジックの参照セクションです。
| ルール | 詳細 |
|---|---|
| デフォルトのクールダウン | sent_date から 84 日(12 週間) |
| バウンスしたリード | クールダウンの対象外です。メールが届いていないためです。クールダウンを確認する際のフィルター:status=neq.bounced |
| 実施中のキャンペーンのリード | 常に対象外です。リードが実施中のキャンペーンに含まれている場合(ステータス = "sent" で、返信またはバウンスがない場合)、別のキャンペーンに追加できません |
| ユーザーによる上書き | ユーザーは特定のリードについてクールダウンを明示的に上書きできます。許可する前に確認してください |
last_contacted が null の場合 | これまで連絡していないリードは常に対象となります |
出力ディレクトリ
キャンペーンのエクスポートは次の場所に保存します。
skills/cold-email-outreach/output/
このディレクトリが存在しない場合は作成します。ファイル名は {campaign-name}-{YYYY-MM-DD}.csv です。