关于 sales-outreach
sales-outreach 是帮助销售人员撰写个性化触达内容的技能,先查找近期且可核实的个人或公司信号,再据此起草文案。它涵盖邮件、电话、LinkedIn 消息和回复处理,并要求没有真实线索时明确说明。
主要功能
- 01检索近期个人与公司信号
- 02按邮件、电话及 LinkedIn 编写触达内容
- 03生成多种切入角度供测试
- 04编写异议应对与回复
- 05无可靠线索时避免杜撰
适用场景
- 01根据近期动态撰写冷邮件
- 02为目标客户准备电话脚本和异议分支
- 03撰写 LinkedIn 邀请、私信及跟进内容
- 04按来信类型起草相应回复
MCP 相关
技能通过 Crustdata MCP 的 Code Mode 获取个人帖子、公司动态、融资和招聘信息,并将其作为触达内容的事实依据。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ crustdata/ skills --skill sales-outreach安装后在 Claude Code 中输入/sales-outreach确认已加载。
附带文件evals/evals.jsonREADME.md
详细介绍
销售拓展
只做一件事:我该说什么——对方能看出我确实做过功课吗?
文案是容易的那一半。触达有效的原因,在于开头提到了关于读者的具体、近期且真实的信息:对方上周写的一篇帖子、上个月完成的一轮融资、刚发布的职位,或刚聘请的高管。本技能会先从 Crustdata 提取这些信息,再围绕它来撰写文案。
先找切入点,再写文案。始终如此。 一封写得再漂亮、内容却只是“我看到你们在金融科技领域”的邮件,也不过是模板。一封直白的三行邮件,如果提到“你周二那篇关于值班轮换的帖子”,就能收到回复。如果某个目标没有真实信号,就如实说明,并提供其他角度——绝不要捏造切入点。
Code Mode 基本规则(读一遍,处处适用)
所有 Crustdata 调用都作为纯 JavaScript 脚本,在 Crustdata MCP 服务的 execute 工具中运行
(install.crustdata.com/mcp)。以下每段代码都遵循这些规则:
- 只能使用纯 JavaScript。 根据
get_schema提供的类型化工具接口编写代码,但脚本主体不得包含任何类型注解——: Type、as或泛型都会导致解析错误,使整个运行在调用任何工具前失败,且不产生任何费用。 - 每个脚本都必须以带来源标记的注释开头:对于用户的原始请求,使用
// user query: ...;对于推导出的步骤,使用// model query: ...。没有此类注释的脚本会在运行前被拒绝。 - 唯一的 I/O 原语:
const r = await callTool(name, params)→{ ok: true, data }或{ ok: false, status, errorType, message }。务必根据r.ok分支处理——调用失败不会中止脚本,因此未检查的失败会悄悄使用空数据继续执行,看起来像是“对方近期没有动态”。这正是导致切入点被捏造的情况。 fields是响应白名单。 结果只包含你列出的分组;之后读取未列出的分组时会得到undefined,看起来就像数据缺失。请列出你会读取的所有分组。- 只返回最精简的数据投影。 只有脚本返回的内容会传给模型。用于拓展时,这意味着只返回候选切入点——日期、一行文字和链接,绝不要返回原始帖子或完整个人资料。
- 使用
await parallelMap(items, fn)并行执行互不依赖的任务;有单次调用上限时,先使用chunk分块。绝不要并行处理游标分页或存在依赖关系的阶段。在耗费较大的阶段后调用checkpoint(acc),以便即使超时,也能返回已经花费资源获取的切入点。
步骤 0 — 收集信息(始终在动笔前执行)
- 配置文件是基础,但绝不能阻塞。 如果工作目录中存在
config/persona-profile.md或config/gtm-config.md,请读取它们:销售代表的表达风格(语气、句长、结尾署名、禁忌清单)、销售的产品以及购买者。如果文件不存在,就在对话中提一个简短问题(“你卖什么?署名怎么写?”),或推荐 icp-builder 技能,该技能可根据一个 LinkedIn URL 生成这两个文件。配置文件缺失绝不能阻止起草——使用简洁直接的语气撰写,并说明这一点。 - 用一行确认请求:对象(个人、客户或名单)——渠道(邮件 / 电话 / LinkedIn)——时机(首次触达 / 跟进 / 回复 / 异议)——目标(约会议?获得答复?寻求引荐?)。
- 找到切入点(见下一节)。一个精准的切入点胜过五个泛泛的切入点。
切入点层(这就是本技能)
四个来源,按成本从低到高、按具体程度从高到低排列。只提取一个;找到合适的信息就停止。在同一个人身上跑完全部四项,通常是在浪费点数。
Hook 1 — 他们说了什么(他们的帖子)
这是最好的 Hook,因为内容来自他们本人,而且有日期。根据此人的职业社交平台个人资料 URL 查找。每篇帖子消耗 1 个积分,所以 limit 是控制花费的旋钮——5 就足以找到一个 Hook。
// user query: write a cold email to https://www.linkedin.com/in/example — find a hook first
const url = "https://www.linkedin.com/in/example";
const cutoffMs = Date.now() - 60 * 24 * 3600 * 1000; // hooks older than ~60 days read as stale
const r = await callTool("social_post_list_live", {
professional_network_profile_url: url, // person key; company_domain / crustdata_company_id key the company feed
limit: 5, // 1 CREDIT PER POST — set this deliberately
fields: ["text", "date_posted", "post_type", "engagement", "hyperlinks", "share_url"], // whitelist
});
if (!r.ok) return { hooks: [], error: r.message };
const parse = (d) => { const t = Date.parse(d ?? ""); return Number.isNaN(t) ? null : t; };
const posts = (r.data.posts ?? []).map(p => ({
date: p.date_posted,
ms: parse(p.date_posted),
type: p.post_type,
url: p.share_url, // the link to the post itself — the rep needs it to verify in five seconds
text: (p.text ?? "").slice(0, 400),
reactions: p.engagement?.total_reactions,
comments: p.engagement?.total_comments,
links: p.hyperlinks?.other_urls ?? [],
}));
return {
fresh: posts.filter(p => p.ms !== null && p.ms >= cutoffMs),
stale: posts.filter(p => p.ms !== null && p.ms < cutoffMs).length,
undated: posts.filter(p => p.ms === null), // never silently drop these — read them yourself
};
解读结果时:优先选择他们原创的帖子,而不是没有评论的转发;优先选择观点,而不是公告。有真实看法的帖子能让你找到一句可以赞同或反驳的话,而这正是促成回复的关键。
Hook 2 — 公司发生了什么(融资、新闻、增长)
company_identify 免费,但匹配不够精确——一个域名可能匹配多家公司。选取最高的 confidence_score,然后按 id 补充信息,这样你只需为一个匹配结果付费(2 个积分)。改用域名或名称补充信息,可能会模糊匹配多家公司,并按每个返回的匹配结果收取 2 个积分;exact_match: true 可以缩小范围,但不能保证最终只匹配一家公司。
// model query: recent company events at acme.com worth opening an email with
const idr = await callTool("company_identify", { domains: ["acme.com"] }); // free, one identifier type per call
if (!idr.ok) return { error: idr.message };
const matches = idr.data[0]?.matches ?? [];
const best = matches.slice().sort((a, b) => (b.confidence_score ?? 0) - (a.confidence_score ?? 0))[0];
if (!best) return { error: "no company match for acme.com" };
const companyId = best.company_data?.basic_info?.crustdata_company_id ?? best.company_data?.crustdata_company_id;
const er = await callTool("company_enrich", {
crustdata_company_ids: [companyId], // one id = one match = exactly 2 credits
exact_match: true, // narrows the fuzzy match; by-name/by-domain can still return >1 -> N x 2 cr
fields: ["basic_info", "funding", "headcount", "news"], // whitelist: list EVERY group you read
});
if (!er.ok) return { error: er.message };
const cd = er.data[0]?.matches?.[0]?.company_data ?? {};
const news = (firstArray(cd.news) ?? []).slice(0, 10).map(n => ({
title: n.article_title, url: n.article_url, date: n.article_publish_date,
}));
return {
name: cd.basic_info?.name,
lastRound: cd.funding?.last_round_type,
lastRaise: cd.funding?.last_fundraise_date,
lastRoundUsd: cd.funding?.last_round_amount_usd,
investors: cd.funding?.investors,
headcount: cd.headcount?.total,
growth12m: cd.headcount?.growth_percent?.["12m"],
news,
};
融资是有时效性的 Hook。3 周前完成的一轮融资,可以用“恭喜 + 接下来通常会遇到的问题”来切入;14 个月前完成的融资只是背景信息,不适合作为开场。新闻文章有真实的发布日期——把日期写进句子里,如果引用具体说法,也要链接到文章。
Hook 3 — 他们在招什么人
招聘信息是公司发布的内容中最真实的一类。他们正在招聘的岗位,代表他们已经决定投入资金解决的问题。
// model query: what acme.com is hiring for, and whether their posts name our category
const domain = "acme.com";
const term = "<the tool you displace>"; // a brand/product/tech name -> ALWAYS [.] exact token, never (.)
const [fresh, named] = await parallelMap([
{
filters: eq("company.basic_info.primary_domain", domain),
sorts: [{ field: "metadata.date_added", order: "desc" }],
fields: ["job_details", "location", "metadata"],
limit: 15,
},
{
filters: and_(
eq("company.basic_info.primary_domain", domain),
exactToken("content.description", term) // [.] guarantees the literal token; (.) is typo-tolerant and pulls lookalikes
),
fields: ["job_details"],
limit: 1, // count query — read total_count, don't download rows
},
], async (params) => await callTool("job_search", params));
if (!fresh.ok) return { error: fresh.message };
return {
newest: fresh.data.job_listings.map(j => ({
title: j.job_details?.title,
city: j.location?.city,
added: j.metadata?.date_added,
})),
total_open: fresh.data.total_count,
postings_naming_term: named.ok ? named.data.total_count : null,
};
按职位名称筛选岗位,而不要用 job_details.category——类别字段粒度较粗,大多数招聘信息都会归到“其他”类别。如果你想说“你们有 4 个数据工程岗位正在招聘”,就按职位名称计数。
根据岗位情况,Hook 往往不言自明:有 3 个 SDR 职位空缺,说明他们刚刚提高了销售管道目标。首次招聘安全岗位,说明他们即将购买安全工具。指出具体职位以及招聘信息的发布时间。
Hook 4 — 已经发生的信号
最理想的情况:所需工作已经完成。sales-prospecting 的联系人追踪器、扩张雷达和客户排名都会输出带日期的信号行。直接交接其中一行,完全跳过抓取。
交接行可能长这样:某人——曾在[你的客户公司]担任[职位]——现任[新公司][职位]——于[日期]入职。这就是 Hook,而且已经带有日期。“于 2026-04-12 完成 B 轮融资”或“6 周前聘用了数据副总裁”也是如此。
不要重新抓取交接给你的内容。只有在需要补充背景时才花费积分(比如获取对方在新岗位发布的第一篇帖子),而且只在草稿确实需要时才这样做。
信号 → 切入角度
| 信号 | 切入角度 | 开场方式 |
|---|---|---|
| 刚完成融资(不到 3 个月) | 扩张压力——员工人数增加后哪些环节会出问题 | 用半句话祝贺,然后谈融资带来的压力 |
| 新上任的同职能高管 | 新职责、90 天计划、新预算 | 以“刚刚上任”的氛围切入:他们接手了什么 |
| 核心联系人跳槽到新公司 | 他们已经知道你们合作得如何 | “恭喜——你知道接下来会是什么情况”(最温暖的触达方式) |
| 相关团队集中招聘 | 他们已经认定问题确实存在 | 提到相关职位;询问从现在到新人入职这段时间会发生什么 |
| 发表了有真实观点的帖子 | 赞同、补充观点,或礼貌地提出不同意见 | 回应他们的观点,而不是他们发帖这件事 |
| 招聘信息中提到技术 | 技术栈契合或替换可能 | 点出工具,说明衔接点 |
| 公司新闻 / 产品发布 | 时机 | 把发布消息与产品能消除的问题联系起来 |
没有钩子,就不要编造
如果拉取结果为空——没有近期帖子、融资是两年前的事、没有开放职位—— 就直说,并提供其他选择,不要编造依据:
- 从职位层级的洞察切入(“300 人规模的公司,每位工程副总裁都会遇到这个问题”),并明确标注 这是职位层级的洞察——好的泛化内容胜过虚假的具体信息。
- 找同一客户公司的另一位活跃人士来挖掘钩子——如果你已经有对方的个人资料 URL(来自用户清单,或来自负责发掘联系人的 sales-prospecting / account-research),就对他们运行 Hook 1。
- 使用客户公司自己的话:按
company_domain调用social_post_list_live,即可获取个人动态不活跃时的公司动态。 - 建议等待信号出现,并在 sales-prospecting 的关键人物追踪器中设置监控。
钩子写入草稿前必须通过三项测试:是他们自己的内容吗(而非行业内容)、有时间信息吗(帖子不超过 60 天,融资/新闻不超过 90 天),以及他们能否一眼认出来。
触达类型
1. 冷邮件
少于 90 个单词。 主题为 3-5 个单词,尽量小写,不用标题党,也不写“快速问个问题”。
- 第 1 行——钩子。 写他们自己的事,注明时间,用他们的语言。读者应该会想: “对,我确实做过这件事。”
- 第 2 行——衔接。 用一句话把他们的事与您能解决的痛点联系起来。
- 第 3 行——一个具体成果。 给出数字或明确的客户情境,而非价值主张。
- 第 4 行——一个请求。 选择既能推动进展、又最不费力的说法(“周四聊 15 分钟怎么样?”或“要我把两行版本发给你吗?”)。
- 如果角色配置中有他们的落款,就使用该落款。icp-builder 编写的配置会记录语气和风格,但不记录落款,因此第一次请直接询问,并在之后沿用。
一个钩子,一个想法,一个请求。提供 2-3 个角度变体供测试(使用不同钩子,或用同一钩子切入不同痛点),并说明你会发送哪一个。
2. 电话脚本
- 开场白 + 征求许可的话术(“突然打给你——能占用 30 秒,之后你可以让我挂电话吗?”)。
- 来电原因,与同一个钩子相关。冷电话一说“只是联系一下”就会失败。
- 价值假设,用一句话表达,并说明这只是一个可以由对方纠正的猜测。
- 2-3 个开放式探索问题——他们现在如何处理这件事,以及这给他们造成了多大成本。
- 请求:约一次会,而不是卖东西。
- 异议应对分支,逐项写出:不感兴趣/发邮件给我/我们已经在用其他方案/没有预算/守门人。每项都用一句话表示理解,再问一个能让通话继续下去的问题。
- 15 秒语音留言和一行后续短信,两者都提到同一个钩子,让各次触达彼此衔接。
3. LinkedIn 触达
- 建立联系备注——最多 300 个字符,不推销。写上钩子,以及建立联系的理由。
- 第一条私信——提供价值,或提出一个聪明的问题。仍然不推销。
- 后续跟进——只有在对方回复或出现信号之后,才提出一个轻量请求。
- 结束跟进——一行即可,礼貌得体,并为以后留下空间。
在做任何这些之前,先推荐 1-2 条值得认真评论的近期帖子——Hook 1 已经提供了这些帖子,无需额外成本。在发送联系请求前三天认真评论一条帖子,效果胜过任何开场白。
4. 回复处理
先分类,再推进。匹配对方回复的长度和语气——对方回两行,你也回两行。
| 回复类型 | 应对方式 |
|---|---|
| 感兴趣 | 提出两个具体时间。别说其他内容。不要重新推销。 |
| 提问 | 用一段话直接回答,然后提出请求。 |
| 异议 | 参考话术(见下文)。 |
| 转介(“去找某某”) | 向对方致谢,请他们引荐,或征求许可说明是他们介绍的;然后以这位介绍人为钩子开启新的对话。 |
| 现在不行 | 确定日期。“我第一季度再联系你,怎么样?”然后务必记录下来。 |
| 明确拒绝 | 礼貌地回复一句,然后结束。不要最后再推销一次。 |
| 取消订阅 | 立即照办。不要反向挽留,也不要说“只是确认一下”。将对方从所有序列中移除。 |
5. 异议应对话术
先判断真正的异议是什么。“太贵了”通常意味着“价值不明确”或“公司内部没有支持者”。“时机不对”通常意味着“不是优先事项”。回答之前,先说出你认为真正的异议是什么。
然后:**认可 → 重新阐释 → 给出一个真实的证明 → 委婉地再次提出请求。**只给出一个证明,而且必须真实:具体的情况、经得起推敲的数据。绝不要编造案例。
给出两个版本:直接版(适合直言不讳的买家)和委婉版(适合仍在建立关系的对象)。
Playbook 模式:将团队最常遇到的 8-10 个异议整理到一份文档中,每个异议都包括判断、两个版本,以及需要避免的陷阱。这份内容值得渲染成页面,参见 Rules 下的 artifact 规则。
6. 序列构建器
- 先制作节奏表:日期、渠道、切入角度、个性化程度。在不同触达中变换角度:问题 → 证明 → 另一种角色的痛点 → 社会认同 → 结束联系。不要换几种说法,把同一个观点发五遍。
- 然后用类型 1-3 编写每次触达的内容。
- 标记每次触达是
1:1(销售代表撰写一条定制内容),还是merge-field(可用于整个名单),并准确标出销售代表必须补充只有自己知道的信息的位置。 - 保持开场内容新鲜:第 1 次触达使用挖掘到的开场信息。到了第 4 次触达,这条信息已经过时两周,要么重新挖掘,要么改用不依赖时效性的角度。在表格中说明选择了哪种方式。
典型形式(根据销售方式调整,不要原样照搬):
| 日期 | 渠道 | 切入角度 | 个性化 |
|---|---|---|---|
| 1 | 邮件 | 开场信息 + 由此体现的痛点 | 1:1 |
| 3 | 联系邀请说明,使用相同的开场信息,不推销 | 1:1 | |
| 5 | 电话 + 语音留言 | 拨打原因 = 开场信息 | 1:1 |
| 8 | 邮件 | 证明,在同一邮件线程中 | merge-field |
| 12 | 邮件 | 另一种角色对该痛点的理解 | merge-field |
| 18 | 邮件 | 结束联系,只写一句 | merge-field |
7. 由信号触发的草稿
输入:刚刚出现的信号(新一轮融资、高管入职、支持者离职、招聘激增),通常由 sales-prospecting 提供。输出:根据上方的信号 → 角度表,撰写一份提及实际触发事件及其日期的草稿。
让这类草稿奏效的规则是:信号出现当周就必须能发出去。融资六周后才发“祝贺完成新一轮融资”的邮件,还不如什么都不发。如果信号已经过时,就说明这一点并更换角度。
要让信号自动持续流入,请引导用户使用 sales-prospecting 的支持者追踪器来设置定期监控。
禁止敷衍规则(适用于每份草稿,无一例外)
在展示任何文案之前,都要逐条检查。带有 AI 痕迹的触达内容比不触达更糟糕,它会让读者觉得自己只是名单上的一员。
发现以下内容,立即删除:
- **长破折号。**改用句号或逗号。
- “希望你一切都好”“我想联系你”“有个小问题”“再跟进一下”“只是跟进一下”。
- “深入探讨”“利用”“简化”“解锁”“提升”“无缝”“强大”。
- 三段式结构(“更快、更便宜、更可靠”)。
- 否定式并列结构(“不只是 X,而是 Y”)。
- 填充性副词:“真的”“其实”“确实”“极其”。
- 假装熟络(“希望你最近进展神速!”)和虚假的紧迫感。
- 任何替换公司名称后仍然成立的句子。如果这句话适用于任何公司,那就不适用于任何公司。
然后大声读出来。听起来应该像销售代表在给一位聪明的同事发消息。如果草稿读起来像模板,就重写,不要敷衍了事。
列表模式——多个账户,一次运行
当输入是一个列表(通常是 sales-prospecting 生成的评分列表)时,顺序始终是:抓取钩子 → 撰写文案 → 导出。不能反过来。
步骤 1——并行抓取钩子。 每个人互不相关,因此使用 parallelMap。运行前说明成本:每篇帖子消耗 1 个积分,因此对 40 个人设置 limit: 3,最多消耗 120 个积分。
// user query: draft outreach for these 40 accounts — pull a hook for each first
const people = inputs.people; // [{ name, profileUrl, company, domain }]
const cutoffMs = Date.now() - 60 * 24 * 3600 * 1000;
const hooks = await parallelMap(people, async (p) => {
const r = await callTool("social_post_list_live", {
professional_network_profile_url: p.profileUrl,
limit: 3, // 1 cr/post x 3 x N people — quote this before running
fields: ["text", "date_posted", "post_type", "share_url"],
});
if (!r.ok) return { name: p.name, hook: null, reason: r.message };
const fresh = (r.data.posts ?? [])
.map(x => ({ date: x.date_posted, ms: Date.parse(x.date_posted ?? ""), url: x.share_url, text: (x.text ?? "").slice(0, 300) }))
.filter(x => !Number.isNaN(x.ms) && x.ms >= cutoffMs);
return { name: p.name, company: p.company, hook: fresh[0] ?? null, reason: fresh.length ? null : "no recent post" };
});
checkpoint(hooks);
return {
withHook: hooks.filter(h => h.hook),
needCompanyFallback: hooks.filter(h => !h.hook).map(h => ({ name: h.name, company: h.company, reason: h.reason })),
};
对于所有 needCompanyFallback 中的人,使用账户层级的钩子 2 或钩子 3,或者如实使用合并字段模板。绝不能让空结果变成编造的第一句话。
步骤 2——联系人信息补全为可选项,且须确认成本。 运行前先报出最高成本,然后再运行:
“为 40 个人查找商务邮箱:最多约 40 个积分(每个匹配的人 1 个)。添加个人邮箱和电话号码会将上限提高到每人 5 个积分,因此总计约 200 个。只查商务邮箱——可以吗?”
// user query: get business emails for the 40 people on the list (worst case ~40 credits, confirmed)
const urls = inputs.profileUrls;
const batches = chunk(urls, 25); // hard cap: 25 URLs per call
const results = await parallelMap(batches, async (batch) => {
const r = await callTool("person_contact_enrich", {
professional_network_profile_urls: batch,
fields: ["contact.business_emails"], // narrow the request; see the cost note below
});
return r.ok ? r.data : batch.map(u => ({ matched_on: u, matches: [], error: r.message }));
});
const rows = results.flat();
return {
contacts: rows.map(m => ({
url: m.matched_on,
email: m.matches?.[0]?.person_data?.contact?.business_emails?.[0]?.email ?? null,
status: m.matches?.[0]?.person_data?.contact?.business_emails?.[0]?.status ?? null,
})),
unmatched: rows.filter(m => !m.matches?.length).map(m => m.matched_on),
};
省略 fields 会请求全部三个层级(商务邮箱、个人邮箱、电话号码),并将上限提高到每个匹配的人 5 个积分。将白名单缩小到你实际需要的层级,并查看响应中的 credits_remaining,以了解实际消耗。如实报告未匹配的行——绝不能用猜测的邮箱格式凑数。
步骤 3——交付。 提供两个文件,不包含凭据,也不自动发送:
- 营销活动 CSV:
email, first_name, last_name, company, title, linkedin_url, hook_text, hook_date, hook_url, personalization_line, tier。钩子、日期及其链接都随文件一并提供,以便销售代表在发送前逐行核对。 - 营销活动规范,供用户粘贴到其使用的任意序列发送工具中:包含每一步的完整文案、使用的合并字段、发送时段和时区、每日发送量递增计划(新域名从每天 20-30 封开始)、邮件线程设置(后续邮件在同一线程中发送)以及启用回复后停止发送。
- 规范中的送达率防护措施:已预热的域名,第 1 次触达最多包含一个链接,优先使用纯文本而非 HTML,立即处理退订。
规则
- 切入点优先,而且必须真实,否则就不要写。 切勿捏造帖子、引言、融资轮次、共同联系人或案例研究。“我没找到此人的近期动态,下面改用一个基于其职位的切入角度”是有效且诚实的回答。
- 为草稿和给销售代表的备注中的每条引用注明日期,让他们能在 5 秒内核实。
- 每次触达只讲一个切入点、一个想法、提出一个请求。简洁胜过巧思。
- 绝不自动发送任何内容。 邮件草稿必须保持为草稿。此技能绝不会写入 CRM;在写作之前,任何日志条目都由你自行记录。序列器配置应是一份规范和一个 CSV,由销售代表自行加载并启动。
- 立即并完全尊重退订请求。 绝不能试图通过增加发送量来绕过合规限制;如果用户希望这么做,必须明确由其自行承担责任。
- 每份交付内容都必须遵守“杜绝水文”规则(完整清单见上文):不使用长破折号,不用“delve”/“leverage”/“streamline”,不加废话,也不写任何替换公司名称后仍然适用的内容。
- 成本都是真实的:在拉取帖子、扩展名单或丰富联系人信息之前,先说明预期费用。每条
execute响应都包含credits和credits_remaining;account_credits可免费查询余额。 - 每份交付内容的结尾都必须询问交付方式:直接贴在聊天中、提供 CSV 和供序列器使用的活动规范,还是生成排版好的文档。
- 根据内容调整布局,绝不能让布局遮挡内容。 品牌系统固定,布局不固定。如果真实内容放不下,例如公司或人名较长、标题有 12 个词、包含 200 行,就调整布局,而不是内容:增大卡片、自动换行而非截断、改为单栏、加宽列、提高上限,或为宽内容添加独立的滚动容器。绝不要通过裁切卡片、省略姓名或悄悄删掉行来解决适配问题。如果确实无法避免设置上限,需在 UI 中注明(“显示 214 项中的前 50 项”)。交付前检查渲染结果,并修复所有被截断的内容。
- 渲染输出中的图标:使用 Lucide,也就是仪表板的图标集,并以内联 SVG 形式呈现,描边设为
currentColor。制品 UI 中不得使用表情符号。 - 照片和徽标均可免费使用,可用于渲染输出。
basic_profile.profile_picture_permalink(人物照片)位于提供给你的任何人物记录的basic_profile组中;basic_info.logo_permalink(公司徽标)由company_identify和company_enrich的basic_info免费提供。两者都不额外消耗点数。将两者以内联 Base64 的形式写入data:image/jpeg;base64,...URI,因为媒体 CDN 会以binary/octet-stream提供文件,远程<img src>会显示为空白。图片缺失时使用姓名首字母徽标作为后备。 - 制品品牌标识:默认在聊天中直接提供文案,CSV 保持为纯数据文件,不要为了渲染而渲染制品。但如果交付内容被渲染为网页或文档(异议处理手册、序列规范、活动单页),则必须在页眉或页脚中加入 Crustdata 品牌标识组合:小号大写字样“Powered by”,加上官方 Crustdata 字标,并链接到 crustdata.com。此技能的
assets/中提供了成对字标文件:crustdata-logo-light.png(深色文字,适用于浅色背景)和crustdata-logo-dark.png(白色文字,适用于深色背景)。根据主题以内联 Base64 形式嵌入对应版本,字标高度约为 17px;绝不要使用远程图片链接,因为渲染后的制品无法获取远程图片。品牌强调色:#5547E2(深色背景上使用#8387FF)。正文使用 Geist 字体;若无法嵌入,则使用系统字体栈。
错误处理
- 危险的情况不是显而易见的情况,而是调用失败。 拉取帖子后出现
r.ok === false,看起来和“此人没有发帖”完全一样。请针对这种情况添加分支,将其报告为错误,并回退到 Hook 2 或 Hook 3——绝不要把它伪装成个性化内容,塞进一条通用开场白里。 - 403 指明某个字段 = 该字段对应的投影受套餐限制。从
fields中移除该字段并重新运行。403 指明某个端点(联系人信息丰富化是常见情况)= 套餐不包含该功能;请明确说明,并交付不含邮箱的名单,而不是猜测邮箱地址格式。 - 帖子为空、新闻为空、没有开放职位都是正常结果,并非失败。请报告哪些来源返回了空结果,并采用上文的无 Hook 路径。
company_identify为同一个域名返回多个匹配项是预期行为,因为它采用模糊匹配。请选取confidence_score最高的匹配项;如果两个分数接近,请同时列出并询问。- 名单处理过程中未匹配的行要按名称报告,绝不能丢弃,也不能悄悄换成模板行。
成本速查表
| 调用 | 成本 |
|---|---|
company_identify、autocomplete、get_schema、account_credits | 免费 |
social_post_list_live | 每条帖子 1 cr — limit 是控制开销的旋钮 |
按 id 调用 company_enrich,并设置 exact_match: true | 一个匹配项需 2 cr |
job_search | 每个结果约 0.03 cr;limit: 1 + total_count ≈ 0.03 cr |
person_contact_enrich | 无基础费用;按每位匹配人员返回的联系人类型计费(工作邮箱 1、个人邮箱 2、电话 2),每人最多 5 cr。缩小 fields 范围可以限定最高预估成本,但不能保证封顶——曾观察到只请求一个层级,却按每人 5 cr 的上限计费并返回全部三个层级,因此请按每人 5 cr 作为最高成本估算,并读取 credits_remaining 确认实际开销 |
| 撰写、分类、编排序列 | 免费——这些都由模型处理 |
一封 Hook 充分的冷邮件通常需要 3-5 个积分。包含 Hook 和工作邮箱的 40 人序列,成本约为 150-200 个积分。
配合使用
- sales-prospecting — 建立名单并触发本技能撰写内容所需的信号。Champion-tracker 中的行是这里转化率最高的输入。
- account-research — 在重要客户触达前深入研究客户;其客户计划会提供桥接句所需的痛点地图。
- icp-builder — 根据一个 LinkedIn URL 撰写
config/persona-profile.md(语气)和config/gtm-config.md(你的销售内容),让草稿从首次运行起就听起来像销售代表本人。 - warm-path-workspace — 如果有熟人引荐的路径,就利用它:引荐开场白胜过你能写出的最佳冷邮件。
工具依赖项
此技能需要:
- Crustdata MCP 服务(install.crustdata.com/mcp):
一个提供
list_tools、get_schema和execute的 Code Mode MCP。所有 Crustdata 数据工具都通过execute({ code })中的纯 JavaScript 脚本调用,使用await callTool(name, params)——请依据get_schema提供的类型化接口编写代码,但脚本主体不得包含类型注解(类型注解会导致解析错误,使整个运行失败)。此处使用的工具:social_post_list_live、company_identify、company_enrich、job_search、person_contact_enrich(选择启用并确认费用)、account_credits。 - 除此之外不需要其他内容。 不需要序列工具凭据,不需要发送邮件权限,也不需要 CRM 写入权限。此技能的外发内容为文案、CSV 和书面营销活动规范——由销售代表加载并启动。