personalization-subagent-pattern
personalization-subagent-pattern について
personalization-subagent-patternは、Claude Codeでコールドメールを大規模に個別化するための再利用可能な手順です。Taskサブエージェントを並列実行し、全件処理の前に承認ループで出力を調整します。
主な機能
- 01Taskサブエージェントの並列実行
- 02サンプル先行の承認ループ
- 03バッチ単位のリード個別化
- 04A/B/Cの文面バリエーション
- 05出力検証と品質チェック
活用シーン
- 01大量のリード向け個別化フィールドの作成
- 02一括生成前の文面調整
- 03キャンペーンテスト用の複数の切り口作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ growthenginenowoslawski/ coldoutboundskills --skill personalization-subagent-patternインストール後、Claude Code で/personalization-subagent-patternを入力して読み込まれたか確認します。
同梱ファイルreferences/prompt-template.md
詳細
パーソナライズ用サブエージェントのパターン
コールドメールを大規模にパーソナライズするには、リードごとに生成する必要があります。Claude Code の Task ツールを使うと、多数のサブエージェントに並列で処理を振り分け、それぞれがリードリストの一部をパーソナライズできます。このスキルでは、再利用可能な承認ループのパターンを定義します。
常に Task ツールを使用 — API キーは使用しない
このスキルは、Task ツールを使って Claude Code 内で完結します。Anthropic SDK の呼び出しも、OpenAI の呼び出しもありません。これは意図的な設計です。
- 追加の API 費用はかかりません。 Claude Code のプランを使用します。
- キー管理は不要です。 すぐに使えます。
- 並列処理を前提に設計されています。 Claude Code は1つのメッセージで複数の Task サブエージェントを起動するため、10件をパーソナライズする時間で100件を完了できます。
非常に大規模な場合(1,000件以上のリード)は、スループット向上のため、調整済みのプロンプトを Anthropic API に送信することもできます。ただし、プロンプトの調整と通常のキャンペーン実行(500件未満)では、必ず Task ツールを使用します。
承認ループ(全件への展開前)
500件をパーソナライズしてから、プロンプトが間違っていたと気付くのは避けましょう。まずループを回し、その後に規模を拡大します。
ラウンド 0 — 1件でサンプルを作成
- バッチから
company_descriptionが充実しているリードを1件選びます。 - ユーザーに「こちらの会社説明をもとに、どのようなパーソナライズ文にしますか?」と尋ねます。
situation_line、value_line、cta_softについて、あなた(Claude)が生成する内容を表示します。- 「この内容でよさそうですか?編集していただければ、調整し直します」と尋ねます。
ラウンド 1-N — 10件のバッチで承認を得る
- 現在のプロンプトと10件のリードを使って、Task サブエージェントを1つ起動します。
- 10件すべての結果を表で表示します。
Lead | situation_line | value_line | cta_soft [email protected] | You're building the only APM for Ruby. | Our Ruby customers find ... | Worth 10 min? [email protected] | ... | ... | ... - 「修正したい点はありますか?行番号を示して、問題点を教えてください」と尋ねます。
- ユーザーから修正があれば、プロンプトを更新(または「X という単語は絶対に使わない」などのルールを追加)し、新しいバッチを再実行します。
- 2ラウンド連続で修正が一切なければ、プロンプトを確定します。全リストに展開します。
拡大 — 全件に展開
プロンプトが確定したら:
- 残りのリードを10~20件ずつのバッチに分割します。
- 並列で Task サブエージェントを3~10個起動します(バリアントごと × バッチごとに1つ)。
lead_idを使って結果を統合します。
使用する場面
- リードごとのカスタム変数が必要なキャンペーン({first_name} だけでは足りない場合)
- リードが50件以上あり、手作業で文章を書かずにパーソナライズしたい場合
/auto-research-publicなどのオーケストレーションスキルで、並列パーソナライズが必要な場合
使用しない場面
- 少量のバッチ(10件未満)— メインの会話内で直接パーソナライズします(並列処理は不要です)
- 固定文面(すべてのリードに同じメールを送る場合)— パーソナライズするとトークンを無駄にします
使用する場面
- リードごとのカスタム変数が必要なキャンペーン({first_name} だけでは足りない場合)
- リードが50件以上あり、手作業で文章を書かずにパーソナライズしたい場合
/auto-research-publicなどのオーケストレーションスキルで、並列パーソナライズが必要な場合
使用しない場面
- 少量のバッチ(20件未満)— メインの会話内で直接パーソナライズします
- 固定文面(すべてのリードに同じメールを送る場合)— パーソナライズするとトークンを無駄にします
パターン
1. リードのバッチを準備する
並列処理に振り分ける前に、リードのバッチを次の情報を含む JSON 配列にします。
{
"lead_id": "<stable identifier>",
"first_name": "<str>",
"last_name": "<str>",
"email": "<str>",
"company_name": "<str>",
"company_domain": "<str>",
"company_description": "<1-3 sentences about what the company does>",
"title": "<str>",
"linkedin_url": "<optional>",
"enrichment_data": { ... any extra signals ... }
}
company_description が充実しているほど、パーソナライズの質が高まります。会社名しかない場合、出力は一般的なものになります。
2. 出力スキーマを定義する
各サブエージェントが返すフィールドをあらかじめ決めます。例:
{
"lead_id": "<same id>",
"situation_line": "<1 sentence — what you noticed about their company>",
"value_line": "<1 sentence — connecting their situation to your offer>",
"cta_soft": "<1 sentence — soft ask, e.g. 'worth a 15 min chat?'>"
}
フィールドが少ないほど、問題が起こりにくくなります。各バリアントのフィールド数は、最大でも3つを基本とします。
3. バリアント(A/B/C)に分ける
3種類の文面バリアントをテストする場合、会社ごと(またはバッチごと)に並列でサブエージェントを3つ実行します。それぞれに異なる切り口のプロンプトを与えます。
- バリアント A:相手の課題に気付いたことから始めます。「サイトで X を拝見しました……」
- バリアント B:称賛してから話題を移します。「Y に対する取り組みは独自性があります……」
- バリアント C:質問から始めます。「Z について、どのようにお考えですか?」
これにより、1つのリストから3倍のデータを得られます。どの切り口が反応を得られるか、A/B/C テストできます。
4. バッチサイズ
- 小さなバッチをデフォルトにします。サブエージェント1つあたりのリード数は10~20件です。
- バッチが大きいほど、エージェント数は少なくなり、コストは下がりますが、品質は低下します(エージェントがコンテキストを失うためです)。
- バッチが小さいほど、エージェント数は多くなり、品質は向上しますが、親エージェントでのコンテキスト使用量も増えます。
リードが100件の場合:
- サブエージェント10個 × リード10件 = 品質良好
- サブエージェント5個 × リード20件 = より高速
- サブエージェント2個 × リード50件 = 品質が低下
リードが1000件の場合:
- 親エージェントのコンテキスト制限に達するのを避けるため、100件ずつのラウンドで実行することを検討してください。
- 各ラウンドで、リード10件を担当するサブエージェントを10個起動します。
5. サブエージェントのプロンプトテンプレート
パーソナライズを行う各サブエージェントには、次のような形式のプロンプトを渡します。
You are personalizing cold email fields for N leads.
CONTEXT:
- We sell: <one sentence from client-profile.yaml>
- Our ICP: <one sentence>
- Our offer: <the CTA we're asking them to respond to>
- Tone: <casual | formal | peer-to-peer>
FIELDS TO GENERATE (per lead):
- situation_line: <definition + 1 good example + 1 bad example>
- value_line: <definition + 1 good example + 1 bad example>
- cta_soft: <definition + 1 good example + 1 bad example>
RULES:
1. Never fabricate facts. If the company description is thin, say something generic but not false.
2. Never use em dashes (—). Use periods or commas.
3. Never use the word "leverage", "synergy", "ecosystem".
4. Maximum length: <N words per field>.
5. If a lead is missing company_description, return "<fields cannot be generated — skip>"
LEADS:
<JSON array>
RETURN:
A JSON array with the same lead_ids and the personalization fields. Save to /tmp/personalization-<batch-id>.json and print "DONE" when complete.
6. ファンアウトのコードパターン
オーケストレーター(メインの Claude Code 会話で実行)の疑似コード:
leads = load leads from JSON
batches = chunk leads into groups of 10-20
for each batch:
for each variant in [A, B, C]:
Task(
description: "Personalize batch <i> variant <v>",
subagent_type: "general-purpose",
prompt: <template above with variant-specific angle>
)
# All tasks run in parallel (multiple tool calls in one message)
Wait for all tasks to finish, then read /tmp/personalization-*.json and merge.
または、複数の Task 呼び出しを含む単一のメッセージですべてを起動します。
# Launch 3 parallel sub-agents for one batch (variants A, B, C)
Task(description: "batch-1-variant-A", ...)
Task(description: "batch-1-variant-B", ...)
Task(description: "batch-1-variant-C", ...)
7. エラー処理
サブエージェントは次のようなことがあります。
- 不正な形式の JSON を返す
- リードをスキップする(データが不十分な場合)
- 生成を拒否する(内容にリスクがあると判断した場合)
オーケストレーターは次のことを行います。
- 返されたすべての JSON が出力スキーマに適合しているか検証します。
lead_idsが欠けている場合は、「厳格モード」のプロンプトで一度だけ再試行します。このプロンプトでは、スキップしないよう強調します。- パーソナライズが実際にできないリード(説明が欠けている場合)は、
personalization_status: "skipped"としてマークし、代わりに定型文を使用します。
「cannot be generated」などの文字列を含むパーソナライズ用フィールドは、絶対に配信しないでください。アップロード前にこれらを除外します。
8. マージとアップロード
すべてのサブエージェントの処理が完了したら、次の手順を実行します。
/tmp/personalization-*.jsonファイルを読み込みます。lead_idでマージします。- これで各リードは次の情報を持ちます。
{ ...original lead fields, "variant_a": { "situation_line": "...", "value_line": "...", "cta_soft": "..." }, "variant_b": { ... }, "variant_c": { ... } } - Smartlead/Instantly にアップロードするときは、各フィールドをカスタム変数に割り当てます。命名規則:
- Smartlead:
{{situation_line_a}}、{{value_line_a}}などを使用します。 - A/B/C の3つのキャンペーンを実施する場合は、variant_a のフィールドをキャンペーン A に、variant_b を B に、というようにアップロードします。
- Smartlead:
承認ループの停止ルール
次の場合、ループは自動的に終了します。
- ユーザーからの修正が、リード10件のラウンドで2ラウンド連続してゼロだった場合、または
- ユーザーが明示的に「これで確定、規模を拡大して」と伝えた場合
停止時の処理:
- 最終調整済みプロンプトを
~/cold-email-ai-skills/profiles/<business-slug>/personalization-prompt.txtに保存します。 client-profile.yamlにメタデータエントリーを保存します。personalization_prompt: path: profiles/<slug>/personalization-prompt.txt variant_count: 3 tuned_at: YYYY-MM-DD rounds_to_convergence: 3- 残りのリードに対して並列ファンアウトを開始します。
2ラウンド承認された後、N+1ラウンドでユーザーから編集があっても問題ありません。その場合、カウンターをリセットしてループを続行します。
品質チェック
アップロード前に、各バリアントからランダムに選んだリード5件を手動でスポットチェックします。よくある問題:
- リード間の繰り返し(サブエージェントが同じ文を10回書く)→ 多様性を指示して、そのバッチを再試行します。
- 事実に反する主張(実際には Y を行っている会社について、X を行っていると書く)→ プロンプトの「捏造しない」ルールを強化します。
- 不自然な言い回し(毎回「~に興味を持ちました」のような AI っぽい表現を使う)→ 禁止表現のリストを追加します。
- 曖昧な表現やぼかした表現(「御社は X を行っているかもしれません……」)→ 「断定し、曖昧にしない」というルールを追加します。
参考資料
references/prompt-template.md— コピーして使えるプロンプトテンプレートreferences/example-output.json— 適切にパーソナライズされたバッチの例references/failure-modes.md— よくあるサブエージェントの失敗と、その検出方法
次に行うこと
これはパターンを説明するドキュメントであり、単独で使うスキルではありません。 /auto-research-public と /campaign-copywriting が、リードごとのパーソナライズを大規模に行う必要があるときに呼び出します。
このドキュメントを直接読んでいる場合は、新しいキャンペーンオーケストレーションのフローを設計している可能性があります。ここに誘導したスキルに戻ってください。
関連スキル
/auto-research-public— このパターンの主な利用元/icp-onboarding— プロンプトが参照するclient-profile.yamlを作成します。/cold-email-starter-kitは、プロンプトが適用するコピーの原則について03-campaign-copywriting.mdを参照します。