Community编程与开发github.com

keinsaasforever/gtm-pipeline-skills

B2B 销售领域的 Claude 技能,用于生成演示线索列表并创建个性化外联消息。

gtm-pipeline-skills 是什么?

该技能是一个专为 B2B 销售场景设计的 Claude 技能,主要用于生成高质量的演示线索列表。它能够通过解析用户的演示表单提示,自动识别理想客户画像 (ICP),并从多个数据源搜索潜在联系人。技能的核心流程包括:解析提示并建立 ICP、创建项目目录、执行人员搜索(优先使用 FullEnrich Finder 和 BetterContact)、基于 ICP 排名进行联系人过滤(联系人筛选)、仅限邮箱的人员丰富、可选的信号搜索,以及最终生成 2-4 个符合“钩子 → 桥梁 → 产品 → 软性行动号召”结构的高质量消息示例。该技能特别关注成本透明化,在调用付费数据源前会估算并披露费用。它支持两种模式:交互式(可在必要时提问)和无人值守/无头模式(从 webhook 调用时,自动推断所有信息并从头到尾执行)。对于信号搜索,默认关闭,但可以通过 `--with-signals` 标志或在提示中明确提及购买触发因素时启用,从而为消息提供基于真实近期新闻的强有力钩子。

兼容平台✓Claude Code~Codex CLI~Cursor✓Gemini CLI
npx skills add keinsaasforever/gtm-pipeline-skills

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

演示

生成一组包含约 10 个丰富联系人及个性化消息示例的演示线索列表,由 webhook 提示触发。

执行前请阅读 ~/.claude/skills/gtm-pipeline/_shared/conventions.md。


何时使用

  • Webhook 触发:用户提交一个描述其目标受众的免费演示表单
  • 目标:证明 AI 代理能够使用真实线索编写真实、非千篇一律的外联消息
  • 范围:约 10 个联系人,包含 LinkedIn 和邮箱丰富数据,2–4 个消息示例

演示限制

  • 不丰富电话号码 — 仅限邮箱
  • 约 10 个联系人(请求 10–15 个,预计丰富后会有所减少)
  • 消息生成是可选的,但推荐
  • 信号搜索为自愿加入 — 默认关闭。通过 --with-signals 标志或用户明确请求启用。请参见步骤 5.5。
  • 成本门槛: 在首次调用付费提供商之前,说明预期支出(按人员来源节奏的查找搜索大多是免费的;约 10-15 个邮箱丰富积分;如果启用信号搜索,费用 < $0.50)。交互模式:先与用户确认。无头模式:在 run_log.md 中记录估算并继续,切勿阻塞。

步骤 1 — 解析提示并建立 ICP

Webhook 提示描述了用户的目标受众。提取以下信息:

必须包含:

  • 你销售/提供什么?
  • 你的理想客户是谁?(行业、职位、公司规模、地点)
  • 你的价值主张是什么?
  • 语气是什么?(正式 vs. 随意,如有示例请提供)
  • 这是用于招聘还是向客户销售?

如果提示中未包含,则进行推断(不要停滞不前):

  • 目标职位、地点、公司规模/类型

在解释受众之前,先自动解析请求者(修复反复出现的“他们到底卖什么 / 为什么他们想要这个受众”的差距):

  1. 解析请求者自己的域名(例如 [email protected] → acme.de),抓取/丰富其信息,并确定他们销售什么。对于提供多种产品的公司:确认演示是针对哪个产品线 — 提示中所述的产品可能与实际产品不符。
  2. 确定与目标受众的关系 — 目标术语(例如“呼叫中心”)通常是指他们向其销售的细分市场,而不是他们自己所属的类别。分类:销售给 / 从...购买 / 收购 / 合作 / 招聘。人物关键词由此衍生,而非猜测。

交互模式 vs. 已部署(无头模式):

  • 交互式: 如果在自动解析后,某个必须包含的信息确实存在歧义,则提出一个简洁的澄清问题。否则继续。
  • 已部署/无头模式(通过 webhook 调用 claude -p 调用 — 请参阅部署):切勿因问题而阻塞。 根据提示和请求者域研究推断每个字段,将假设记录在 context/icp.md 的“假设”标题下,并端到端地继续执行。

在 ICP 足够清晰以构建有意义的筛选条件之前,不要进行搜索。

将 ICP 保存到: {client-slug}-gtm/context/icp.md(包括产品、关系分类以及任何无头模式下的假设)。


步骤 2 — 创建工作目录

按照 conventions.md 中的定义创建 {client-slug}-gtm/ 目录结构。将 ICP 定义写入 context/icp.md。


步骤 3 — 人员搜索(10 个联系人)

使用 people-search 技能查找约 10–15 个联系人。

演示的提供商选择: 遵循 conventions.md 中的查找节奏 → 人员来源节奏 — FullEnrich Finder → BetterContact → Pipe0 → Amplemarket/Crustdata(最后手段),每个来源最多尝试 2 次,对于中小企业/所有者主导/非英语细分市场,首选 FullEnrich (FE)。FE 和 BC 都直接返回 LinkedIn URL(邮箱丰富所需)。如果没有公司列表(基于人物的提示),则使用 Parallel FindAll 或 BC Search。对于通过目录/抓取获取的公司列表,按公司名称 + 地点进行搜索,绝不能按精确域名搜索(约定 #11)。

要收集的关键字段:

full_name, first_name, last_name,
job_title, company_name, company_domain,
linkedin_profile_url, location

遵循人员搜索的执行协议:沙盒 → 测试 → 审查 → 运行。


步骤 4 — 联系人筛选(ICP 排名)

对找到的 10–15 个联系人运行 contact-filter。即使是小批量,ICP 排名也很有益——它确保丰富步骤集中在最合适的联系人上。

  • 应用职位层级、行业层级、地点层级和公司规模分类
  • 拒绝硬性非 ICP 联系人
  • 按优先级对通过的联系人进行排名
  • 输出:csv/intermediate/contacts_filtered.csv

对于演示:使用宽松的硬性拒绝阈值(允许层级 1–5 通过),优先考虑排名而非筛选。


步骤 5 — 人员丰富(仅限邮箱)

对筛选后的联系人运行 people-enrichment。演示模式:仅限邮箱,无电话。

推荐流程:

  1. FullEnrich v2(邮箱)— 所有联系人
  2. Pipe0 waterfall — 仅针对 FE 遗漏的联系人

用于消息个性化的额外丰富(如可用):

  • LinkedIn 标题和摘要(通过 PhantomBuster 抓取 LinkedIn)
  • 最近的 LinkedIn 帖子(每个联系人 2–3 条)— 显著提高消息质量

用于消息生成的最小可行字段:

name, job_title, company_name, linkedin_profile_url,
headline (optional), summary (optional), recent_posts (optional)

低产出: 如果通过筛选和丰富后幸存下来的联系人少于约 8 个,则在继续生成消息之前,再执行一次查找(按人员来源节奏的下一个来源)。


步骤 5.5 — 信号搜索(可选)

默认:关闭。 在以下情况下启用:

  • 用户明确要求基于信号锚定的消息
  • Webhook 提示提到购买触发因素(融资、招聘、转型、最新新闻)
  • 客户的产品依赖于时机信号才有意义(例如“我们帮助后 A 轮公司扩展运营”)
  • 向演示调用传递了 --with-signals 标志

成本说明: 每个独特公司增加约 $0.01–0.05(网络搜索 + 评分)。对于一个 10 个联系人的演示,通常有 5–10 个独特公司,因此费用 < $0.50。

信号搜索所需的输入

信号搜索需要三个上下文文件:

  • context/icp.md — 已在步骤 1 中收集
  • context/offering.md — 步骤 1 中的价值主张块(如果尚未保存,请立即写入)
  • context/signal_criteria.md — 与产品相关的信号类型列表(项目符号格式)

如果 signal_criteria.md 不存在,请询问用户:“一家公司现在正在做什么,表明他们需要你提供的东西?” — 捕获 5–10 个项目符号并保存。

运行

# 从丰富联系人中提取独特公司列表
python3 -c "
import csv, sys
seen = set()
with open('csv/output/contacts_enriched.csv') as f, open('csv/input/companies_raw.csv', 'w', newline='') as out:
    reader = csv.DictReader(f)
    writer = csv.DictWriter(out, fieldnames=['company_name', 'company_domain', 'company_website'])
    writer.writeheader()
    for row in reader:
        c = row.get('company_name') or row.get('company') or ''
        if c and c not in seen:
            seen.add(c)
            writer.writerow({
                'company_name': c,
                'company_domain': row.get('company_domain') or '',
                'company_website': row.get('company_website') or row.get('website') or '',
            })
"

# 对独特公司运行信号搜索
source \"$HOME/.claude/skills/gtm-pipeline/_shared/resolve_env.sh\" && \
export $(grep -E '^(PARALLEL_API_KEY|OPENROUTER_API_KEY|FIRECRAWL_API_KEY|GEMINI_API_KEY)=' \"$GTM_ENV_PATH\" | xargs) && \
  python3 ~/.claude/skills/gtm-signal-search/signal_search.py \
    --client-dir {client-slug}-gtm

resolve_env.sh 的 source 行确保即使在新的 shell 中也设置了 $GTM_ENV_PATH(请参阅 signal-search SKILL.md / 约定)。对于演示,请将 Firecrawl 和 Parallel 丰富关闭— 对于一个约 10 个联系人的线索列表,网络搜索 + 评分就足够了。仅当站点内容(职业页面、博客)是主要信号源时才启用 Firecrawl;如果此机器仅通过 MCP 拥有 Firecrawl(无 FIRECRAWL_API_KEY),请使用 signal-search 技能中记录的 --firecrawl-pages-dir 路径。

将信号合并回联系人

import csv, json
signals = {}
with open('csv/intermediate/signals.csv') as f:
    for row in csv.DictReader(f):
        signals[row['company_name']] = {
            'overall_score': row.get('overallScore', ''),
            'scored_signals': row.get('scoredSignals', ''),
            'overall_summary': row.get('overallSummary', ''),
        }

rows_out = []
with open('csv/output/contacts_enriched.csv') as f:
    for row in csv.DictReader(f):
        s = signals.get(row.get('company_name') or row.get('company') or '', {})
        row['company_overall_score'] = s.get('overall_score', '')
        row['company_scored_signals'] = s.get('scored_signals', '')
        row['company_overall_summary'] = s.get('overall_summary', '')
        rows_out.append(row)

with open('csv/output/contacts_enriched.csv', 'w', newline='') as f:
    w = csv.DictWriter(f, fieldnames=list(rows_out[0].keys()))
    w.writeheader()
    w.writerows(rows_out)

然后,步骤 6 中的消息生成步骤将为每个联系人提供 company_overall_summary 和 company_scored_signals — 使用评分最高的信号作为消息钩子。


步骤 6 — 生成消息示例

在承诺批量生成之前,先生成 2–4 个样本消息。

消息结构

每条消息必须遵循:钩子 → 桥梁 → 产品 → 软性行动号召

部分目的长度
钩子引用此人的特定内容(帖子、职业变动、公司信号)1 句话
桥梁将他们的处境与你的产品联系起来1 句话
产品你提供什么,清晰陈述1 句话
行动号召软性请求 — 不是“让我们安排一次通话”1 句话

总计:320–450 个字符。 问候语后不留空行。段落之间用单个换行符分隔。

质量规则

必须包含:

  • 具体的钩子(帖子引用 OR 职业洞察 OR 有评分的购买信号 — 不能是通用的)
  • 清晰的价值主张
  • 自然、对话式的语气
  • 软性行动号召

必须避免:

  • 重复他们已经知道的个人资料信息(“你在 Y 公司担任 X 职位”)
  • 通用观察(“令人印象深刻的背景”、“我注意到你从事 [行业]”)
  • 企业行话或流行词
  • 咄咄逼人的行动号召(“让我们本周安排一次通话”)

如果步骤 5.5 已运行: 对于每个联系人,优先使用 company_scored_signals 中评分最高的信号作为钩子,而不是通用的 LinkedIn 帖子引用。一个评分 >= 70 的、基于真实近期新闻的信号是演示能产生的最强钩子。

生成过程

  1. 编写特定于客户的系统提示(保存到 prompts/message_prompt.md)
  2. 生成 2–4 个样本 — 包括有和没有 LinkedIn 帖子的联系人
  3. 对照上述质量检查清单进行审查
  4. 如果发现问题,优化系统提示并重新生成
  5. 仅在质量通过后才进行批量生成

系统提示模板(关键部分)

- 客户上下文:他们销售什么,针对谁,他们的价值主张,语气
- 禁止规则:不重复个人资料,不进行通用奉承
- 消息结构:钩子 → 桥梁 → 产品 → 行动号召
- 钩子示例:有帖子/无帖子
- 字符限制:320–450

步骤 7 — 清理与输出

步骤 7a — 清理(强制、确定性的、不使用 LLM)。 csv/intermediate/ 保留所有字段。 在构建任何面向线索的内容之前,运行共享的清理器,以便重复的手动清理(提供商标签、空列、错误的邮箱、过时的信号)得以一致地应用。

相关技能