sales-outreach

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Sales Outreach

销售触达

One job: what do I say — and can they tell I actually looked?
The copy is the easy half. The reason a touch lands is that it opens with something specific, recent, and true about the person reading it: a post they wrote last week, the round they closed last month, the role they just opened, the exec they just hired. This skill pulls that from Crustdata first, then writes around it.
The hook comes before the copy. Always. A beautifully written email built on "I saw you're in fintech" is a template. A blunt three-line email built on "your Tuesday post about the on-call rotation" gets replies. If no real signal exists for a target, say so and offer a different angle — never invent a hook.

核心目标:我该说什么——对方能看出我确实做过功课吗?
撰写文案是简单的部分。触达内容能获得回应的原因,在于开头提到了收件人具体、近期且真实的信息:比如他们上周发的帖子、上月完成的融资轮次、刚发布的招聘岗位、新聘请的高管。本技能会优先从Crustdata提取这类信息,再围绕其撰写内容。
钩子永远先于文案。 一封写着「我了解到您从事金融科技行业」的精美邮件,本质还是模板。而一句直白的「您周二发布的关于值班轮岗的帖子」作为开头的三行邮件,却能获得回复。如果目标对象没有真实信号,就直接说明并提供其他角度——绝对不要编造钩子。

Code Mode ground rules (read once, apply everywhere)

代码模式基本原则(阅读一次,全局适用)

All Crustdata calls run inside the
execute
tool of the Crustdata MCP server (install.crustdata.com/mcp) as a plain-JavaScript script. Every snippet below follows these rules:
  • Plain JavaScript only. Author against the typed tool surface from
    get_schema
    , but the script body carries zero type annotations — a
    : Type
    ,
    as
    , or generic is a parse error that fails the whole run before any tool call, at zero spend.
  • Open every script with a source-labeled comment:
    // user query: ...
    for the user's literal ask,
    // model query: ...
    for a derived step. Scripts without one are rejected before running.
  • One I/O primitive:
    const r = await callTool(name, params)
    { ok: true, data }
    or
    { ok: false, status, errorType, message }
    . Always branch on
    r.ok
    — a failed call does not abort the script, so an unchecked failure silently proceeds on empty data and looks like "they have no recent activity". That is exactly the failure that produces a fabricated hook.
  • fields
    is a response whitelist.
    The result carries only the groups you list; an omitted group reads as
    undefined
    later and looks like missing data. List every group you read.
  • Return the smallest projection. Only what the script returns reaches the model. For outreach that means hook candidates — date, one line of text, a link — never raw posts or whole profiles.
  • Fan out independent work with
    await parallelMap(items, fn)
    ;
    chunk
    first where there is a per-call cap. Never parallelize cursor pagination or dependent stages.
    checkpoint(acc)
    after a costly stage so a timeout still returns the hooks you paid for.

所有Crustdata调用都在Crustdata MCP服务器(install.crustdata.com/mcp)的
execute
工具中,以纯JavaScript脚本运行。以下所有代码片段均遵循这些规则:
  • 仅使用纯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)
    ,这样即使超时,也能返回已获取到的钩子内容。

Step 0 — Intake (always, before writing a word)

步骤0 — 需求接收(撰写内容前必须完成)

  1. Config backbone, never blocking. If
    config/persona-profile.md
    or
    config/gtm-config.md
    exist in the working directory, read them: the rep's voice (tone, sentence length, sign-off, never-do list), what they sell, who buys. If they don't exist, ask one inline question ("What do you sell, and what's your sign-off?") or point at the icp-builder skill, which writes both files from one LinkedIn URL. A missing config never blocks a draft — write in a plain, direct voice and say you did.
  2. Confirm the ask in one line: WHO (person, account, or list) — CHANNEL (email / call / LinkedIn) — MOMENT (first touch / follow-up / reply / objection) — GOAL (a meeting? an answer? an intro?).
  3. Pull the hook (next section). One sharp hook beats five soft ones.

  1. 配置为基础但绝不阻塞流程。如果工作目录中存在
    config/persona-profile.md
    config/gtm-config.md
    ,请读取它们:包含销售代表的语气(语调、句子长度、签名、禁忌内容)、销售产品、目标客户。如果不存在,可直接提出一个简短问题(「您销售的是什么产品?您的邮件签名是什么?」),或推荐使用icp-builder技能,该技能可通过一个LinkedIn URL生成这两个配置文件。即使缺少配置,也绝不阻塞草稿生成——使用简洁直接的语气撰写,并说明情况。
  2. 用一句话确认需求:对象(个人、客户账户或列表)——渠道(邮件/电话/LinkedIn)——场景(首次触达/跟进/回复/异议处理)——目标(约见?获取答复?获得引荐?)。
  3. 提取钩子(下一节内容)。一个精准的钩子胜过五个模糊的钩子。

THE HOOK LAYER (this is the skill)

钩子层(本技能核心)

Four sources, cheapest and most specific first. Pull one; stop when you have something good. Running all four on one person is usually a waste of credits.
四个信息来源,按成本从低到高、精准度从高到低排序。提取一个即可;找到合适内容后立即停止。对同一个人运行全部四个来源通常是浪费积分。

Hook 1 — what they said (their posts)

钩子1 — 对方的言论(他们发布的帖子)

The best hook there is, because it's theirs and it's dated. Keyed on the person's professional network profile URL. 1 credit per post, so
limit
is the spend dial
— 5 is plenty to find one hook.
js
// 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
};
Reading the result: prefer a post they wrote over a reshare with no commentary, and an opinion over an announcement. A post with a real take gives you a sentence you can agree or disagree with, which is what earns a reply.
这是最佳钩子,因为内容属于对方且带日期。以用户的职业社交平台个人资料URL为检索键。每篇帖子消耗1积分,因此
limit
是控制成本的关键
——设置为5就足以找到一个合适的钩子。
js
// 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 — what happened to the company (funding, news, growth)

钩子2 — 公司动态(融资、新闻、增长)

company_identify
is free but fuzzy — one domain can match several companies. Take the top
confidence_score
, then enrich by id so you pay for exactly one match (2 credits). Enriching by domain or name instead can fuzzy-match several companies and bill 2 credits per returned match, which
exact_match: true
narrows but does not guarantee down to one.
js
// 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,
};
Funding is a hook with a shelf life. A round closed 3 weeks ago is "congrats + here's what usually breaks next"; a round closed 14 months ago is background, not an opener. News articles carry a real publish date — use it in the sentence and link the article if you reference a specific claim.
company_identify
是免费但模糊的工具——一个域名可能匹配多个公司。选择
confidence_score
最高的结果,然后通过ID进行信息补充,这样你只需为精准匹配的一个公司付费(2积分)。如果通过域名或名称补充信息,可能会模糊匹配多个公司,每个返回的匹配项都会收取2积分;即使设置
exact_match: true
,也无法保证只返回一个结果。
js
// 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,
};
融资作为钩子有保质期。3周前完成的融资轮次,可以用「恭喜+接下来可能遇到的痛点」作为切入;14个月前的融资轮次只能作为背景信息,不能作为开头。新闻文章带有真实发布日期——在文案中提及日期,如果引用具体内容,还需附上文章链接。

Hook 3 — what they're hiring for

钩子3 — 公司招聘需求

Job posts are the most honest thing a company publishes. The roles they're opening are the problems they've agreed to spend money on.
js
// 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,
};
Scope roles by title, not
job_details.category
— the category field is coarse and most postings land in the catch-all. If you want to say "you've got four data engineering roles open", count titles.
The hook writes itself from the shape: three SDR reqs open means a pipeline target they just raised. A first security hire means they're about to buy security tooling. Name the actual role and when it was posted.
招聘启事是公司最真实的公开信息。他们发布的招聘岗位,正是他们愿意花钱解决的问题。
js
// 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个数据工程师岗位在招」,请按岗位名称统计。
钩子可以直接从招聘需求推导:3个销售开发代表(SDR)岗位空缺,意味着他们刚刚设定了新的 pipeline 目标;首个安全岗位招聘,意味着他们即将采购安全工具。请明确提及具体岗位名称和发布日期。

Hook 4 — a signal that already fired

钩子4 — 已触发的信号

The best case: the work is already done. sales-prospecting's champion tracker, expansion radar, and account ranking all emit dated signal rows. Hand one straight in and skip the pull entirely.
A handed-over row looks like: person — was [role] at [your customer] — now [title] at [new company] — landed [date]. That IS the hook, and it's already dated. Same for "raised Series B on 2026-04-12" or "hired a VP Data 6 weeks ago".
Do not re-pull what you were handed. Spend a credit only to add colour (their first post in the new job, say) and only if the draft needs it.
最佳情况:工作已完成。sales-prospecting的冠军追踪器、拓展雷达和客户账户排名工具,都会生成带日期的信号行。直接使用这些信号行,无需再提取。
传入的信号行示例:某人——曾在[你的客户公司]担任[职位]——现在在[新公司]担任[职位]——入职日期[date]。这本身就是钩子,且已带日期。类似的还有「2026-04-12完成B轮融资」或「6周前聘请了数据副总裁」。
不要重复提取已传入的信息。仅在草稿需要补充细节时(比如对方在新岗位发布的第一篇帖子)才消耗积分,且仅在必要时进行。

Signal → angle

信号→切入角度

SignalThe angleThe opening move
Fresh raise (<3 months)Scaling pain — what breaks at the next headcountCongratulate in half a sentence, then the pain the round creates
New exec in your functionNew mandate, 90-day plan, fresh budget"New in seat" energy: what are they inheriting
Champion moved to a new companyThey already know you work"Congrats — you know how this goes" (warmest touch there is)
Hiring surge in a relevant teamThey've agreed the problem is realReference the roles; ask what happens between now and the hires landing
A post with a real opinionAgree, extend, or politely disagreeRespond to the idea, not to the fact that they posted
Tech named in job postsStack fit or displacementName the tool, name the seam
Company news / launchTimingTie the launch to the pain your product removes
信号切入角度开场方式
近期融资(<3个月)扩张痛点——下一阶段人员规模增长会遇到的问题用半句话恭喜,然后引出融资带来的痛点
你的业务领域新上任高管新任务、90天计划、新预算以「新上任」为切入点:他们接手了什么工作
老客户跳槽到新公司对方已经了解你的产品「恭喜——你知道我们的合作模式」(最有效的暖场触达)
相关团队大规模招聘他们已确认问题真实存在提及招聘岗位,询问从现在到人员到岗期间的计划
带有真实观点的帖子认同、延伸或礼貌反驳回应观点本身,而非对方发布帖子这件事
招聘启事中提及特定技术技术栈匹配或替代方案明确提及工具名称和适配场景
公司新闻/产品发布时机契合将发布事件与你的产品能解决的痛点关联

No hook, no fabrication

无钩子则绝不编造

If the pulls come back empty — no recent posts, funding two years old, no open roles — say that out loud and offer the alternatives instead of inventing a reference:
  • Write from a role-level insight ("every VP Eng at 300 people hits this") and label it as such — a good generic beats a fake specific.
  • Pull a hook on a different person at the same account who is active — if you already have their profile URL (from the user's list, or from sales-prospecting / account-research, which do the person discovery), run Hook 1 on them instead.
  • Use the account's own words:
    social_post_list_live
    keyed on
    company_domain
    gives the company feed when the individual is quiet.
  • Recommend waiting for a signal and setting up the watcher in sales-prospecting's champion tracker.
A hook must pass three tests before it goes in a draft: is it theirs (not their industry's), is it dated (post ≤60 days, funding/news ≤90 days), and would they recognize it in one read.

如果提取结果为空——无近期帖子、融资已超过2年、无招聘岗位——直接告知用户,并提供替代方案,绝不要编造参考信息:
  • 基于岗位层级的洞察撰写(「所有300人规模公司的工程副总裁都会遇到这个问题」),并明确标注——优质的通用内容胜过虚假的个性化内容。
  • 提取同一客户账户中其他活跃人员的钩子——如果你已有他们的个人资料URL(来自用户列表,或sales-prospecting / account-research工具,这些工具可发现目标人员),则对他们运行钩子1的提取流程。
  • 使用客户账户自身的内容:以
    company_domain
    为检索键调用
    social_post_list_live
    ,可获取公司动态,当目标人员无动态时使用。
  • 建议等待信号触发,并在sales-prospecting的冠军追踪器中设置监控。
钩子必须通过三项测试才能用于草稿:是否属于对方(而非行业通用)、是否带日期(帖子≤60天,融资/新闻≤90天)、对方能否一眼认出

THE TOUCH TYPES

触达类型

1. Cold email

1. 冷邮件

Under 90 words. Subject 3-5 words, lowercase-ish, no clickbait, no "quick question".
  • Line 1 — the hook. Their thing, dated, in their language. The reader should think "yes, I did that".
  • Line 2 — the bridge. One sentence connecting their thing to the pain you solve.
  • Line 3 — one concrete outcome. A number or a named customer situation, not a value prop.
  • Line 4 — one ask. The lowest-friction version that still moves ("worth 15 minutes Thursday?" or "want me to send the two-line version?").
  • Their sign-off, if the persona config carries one. The config written by icp-builder records tone and style but not a sign-off, so ask for it inline the first time and reuse it after.
One hook, one idea, one ask. Offer 2-3 angle variants for testing (different hook, or same hook different pain) and say which one you'd send.
字数不超过90词。主题3-5词,小写风格,无标题党,避免使用「quick question」这类表述。
  • 第1行——钩子。对方的真实动态,带日期,用对方的语言表述。读者看到后应会想「是的,我确实做过这件事」。
  • 第2行——衔接。用一句话将对方的动态与你能解决的痛点关联起来。
  • 第3行——具体成果。用数字或真实客户案例说明,而非空泛的价值主张。
  • 第4行——明确请求。选择最低摩擦但能推进流程的请求(比如「周四抽15分钟聊聊可以吗?」或「要不要我发一个两行版的简要说明?」)。
  • 如果有 persona 配置文件,使用其中的签名。icp-builder生成的配置文件会记录语气和风格,但不包含签名,因此首次使用时可直接询问,后续复用即可。
一个钩子、一个核心观点、一个请求。提供2-3个角度变体用于测试(不同钩子,或同一钩子不同痛点),并说明你会选择发送哪一个。

2. Call script

2. 通话脚本

  • Opener + permission line ("caught you cold — 30 seconds and you can tell me to go away?").
  • Reason for the call, tied to the same hook. Cold calls die on "just reaching out".
  • Value hypothesis in one sentence, framed as a guess they can correct.
  • 2-3 open discovery questions — how they handle it today, what it costs them.
  • The ask: a meeting, not a sale.
  • Objection branches, written out: not interested / send me an email / we already use something / no budget / gatekeeper. Each is one acknowledgment plus one question that keeps the call alive.
  • 15-second voicemail and a one-line follow-up text, both referencing the same hook so the touches stack.
  • 开场+许可话术(比如「突然打扰您——给我30秒时间,您随时可以让我结束通话,可以吗?」)。
  • 通话理由,与同一个钩子关联。冷通话失败的原因往往是「只是联系一下」这类表述。
  • 价值假设,用一句话表述,以猜测的方式让对方可以纠正。
  • 2-3个开放式探索问题——他们当前如何处理该问题、成本是多少。
  • 请求:约见,而非推销
  • 异议应对分支,完整撰写:不感兴趣/发邮件给我/我们已使用同类产品/无预算/对接人权限不足。每个分支包含一句确认语和一个能延续通话的问题。
  • 15秒语音留言一行跟进短信,均关联同一个钩子,让多次触达形成协同效应。

3. LinkedIn touches

3. LinkedIn触达

  • Connection note — 300 characters max, no pitch. The hook plus a reason to connect.
  • First DM — value or a smart question. Still no pitch.
  • Follow-up — a soft ask, only after a reply or a signal.
  • Break-up — one line, gracious, leaves the door open.
Before any of it, suggest 1-2 of their recent posts worth a genuine comment — you already have them from Hook 1, at no extra cost. A real comment three days before a connection request does more than any first line.
  • 连接请求备注——最多300字符,无推销内容。包含钩子和连接理由。
  • 首次私信——提供价值或提出有深度的问题。仍无推销内容。
  • 跟进消息——仅在对方回复或有新信号时发送,提出温和请求。
  • 终止跟进——一句话,礼貌得体,留有余地。
在发送任何消息前,建议对对方近期的1-2篇帖子发表真实评论——你已从钩子1获取了这些帖子,无需额外成本。在发送连接请求前三天发表真实评论,比任何开场话术都有效。

4. Reply handler

4. 回复处理

Classify first, then advance. Match their length and their energy — a two-line reply gets a two-line answer.
Reply typeThe move
InterestedPropose two concrete times. Nothing else. Do not re-pitch.
QuestionAnswer it directly in one paragraph, then the ask.
ObjectionGo to talk-tracks (below).
Referral out ("talk to X")Thank them, ask for the intro or permission to name them, then open the new thread with the referral as the hook.
Not nowGet the date. "Should I come back in Q1?" Then actually log it.
Hard noOne gracious line, exit. No last-ditch pitch.
UnsubscribeHonor immediately. No counter-offer, no "just confirming". Remove from every sequence.
先分类,再推进。匹配对方回复的长度和语气——对方用两行回复,你也用两行回应。
回复类型处理方式
感兴趣提出两个具体时间。无需其他内容,不要再推销。
提问直接用一段文字回答,然后提出请求。
异议使用下方的异议应对话术。
引荐他人(「联系X」)感谢对方,请求引荐或允许提及对方姓名,然后以该引荐为钩子开启新对话。
现在没时间获取具体日期。比如「我在第一季度再联系您可以吗?」并记录该日期。
明确拒绝一句礼貌的回复,结束对话。不要做最后一搏的推销。
取消订阅立即执行。不要提出反要约,不要发送「确认取消」的消息。将对方从所有触达序列中移除。

5. Objection talk-tracks

5. 异议应对话术

Diagnose the real objection first. "Too expensive" is usually "value unclear" or "no internal champion". "Bad timing" is usually "not a priority". Say what you think the real one is before answering it.
Then: acknowledge → reframe → one real proof point → soft re-ask. One proof point, and it must be real — a named situation, a number you can defend. Never invent a case study.
Give two variants: direct (for a buyer who's blunt) and soft (for a relationship you're still building).
Playbook mode: the team's top 8-10 objections in one document, each with the diagnosis, both variants, and the trap to avoid. This one is worth rendering as a page — see the artifact rule under Rules.
先诊断真实异议。「太贵了」通常意味着「价值不明确」或「内部无支持者」。「时机不对」通常意味着「不是优先事项」。在回答前,先说出你认为的真实异议。
然后遵循:确认→重构→一个真实证明点→温和重提请求。仅提供一个证明点,且必须真实——真实客户案例、可验证的数据。绝不要编造案例研究。
提供两个变体:直接版(适合直率的买家)和温和版(适合仍在建立关系的对象)。
手册模式:将团队最常遇到的8-10个异议整理成一份文档,每个异议包含诊断、两个变体和需要避免的陷阱。这份文档适合以页面形式呈现——请参考「规则」中的成品规则。

6. Sequence builder

6. 序列构建器

  1. The cadence table first — day, channel, angle, personalization level. Vary the angle across touches: problem → proof → a different persona's pain → social proof → break-up. Never send the same idea five times in different words.
  2. Then write every touch using types 1-3.
  3. Mark each touch
    1:1
    (rep writes a custom line) vs
    merge-field
    (scales across the list), and flag exactly where the rep must add something only they know.
  4. Hook freshness: touch 1 carries the pulled hook. By touch 4 that hook is two weeks old — either re-pull or switch to an angle that doesn't depend on recency. Say which in the table.
Typical shape (adapt to the motion, don't ship this as-is):
DayChannelAnglePersonalization
1EmailThe hook + the pain it implies1:1
3LinkedInConnection note, same hook, no pitch1:1
5Call + voicemailReason-for-call = the hook1:1
8EmailProof point, in-threadmerge-field
12EmailA different persona's version of the painmerge-field
18EmailBreak-up, one linemerge-field
  1. 先制作节奏表——日期、渠道、切入角度、个性化程度。在不同触达中切换角度:问题→证明→不同角色的痛点→社交证明→终止跟进。绝不要用不同的语言重复发送同一个观点。
  2. 然后撰写所有触达内容,使用类型1-3的规则。
  3. 标记每个触达内容
    1:1
    (销售代表需撰写自定义内容)或
    merge-field
    (可批量应用于列表),并明确标注销售代表必须添加个人专属信息的位置。
  4. 钩子时效性:第1次触达使用提取的钩子。到第4次触达时,钩子已过去两周——要么重新提取,要么切换到不依赖时效性的角度。在节奏表中说明选择。
典型结构(根据场景调整,不要直接套用):
天数渠道切入角度个性化程度
1邮件钩子+隐含痛点1:1
3LinkedIn连接请求备注,同一钩子,无推销1:1
5电话+语音留言通话理由=钩子1:1
8邮件证明点,线程内回复merge-field
12邮件不同角色的痛点版本merge-field
18邮件终止跟进,一句话merge-field

7. Signal-triggered drafts

7. 信号触发式草稿

Input: a signal that just fired (new funding, exec hire, champion moved, hiring surge), usually handed over from sales-prospecting. Output: a draft that references the actual trigger with its date, mapped through the signal → angle table above.
The rule that makes these work: the draft must be sendable the week the signal fired. A "congrats on the round" email six weeks late is worse than nothing. If the signal is already stale, say so and re-angle.
To keep signals flowing automatically, point the user at sales-prospecting's champion tracker, which sets up the recurring watcher.

输入:刚触发的信号(新融资、高管任命、老客户跳槽、大规模招聘),通常来自sales-prospecting工具。输出:引用实际触发事件及其日期的草稿,根据上述「信号→切入角度」表进行映射。
关键规则:草稿必须能在信号触发的当周发送。融资完成六周后才发送「恭喜融资」的邮件,还不如不发。如果信号已过期,说明情况并调整切入角度。
为了自动获取信号,可引导用户使用sales-prospecting的冠军追踪器,该工具可设置定期监控。

THE NO-SLOP RULE (every draft, no exceptions)

零冗余规则(所有草稿必须遵守)

Run this pass on every piece of copy before showing it. A touch that smells like AI is worse than no touch — it tells the reader they were on a list.
Kill on sight:
  • Em dashes. Use a period or a comma.
  • "I hope this finds you well", "I wanted to reach out", "quick question", "circling back", "just following up".
  • "delve", "leverage", "streamline", "unlock", "elevate", "seamless", "robust".
  • Rule-of-three constructions ("faster, cheaper, and more reliable").
  • Negative parallelism ("not just X, but Y").
  • Filler adverbs: "really", "actually", "truly", "incredibly".
  • Fake familiarity ("Hope you're crushing it!") and fake urgency.
  • Any sentence that would survive a find-and-replace of the company name. If it works for any company, it works for none.
Then read it out loud. It should sound like the rep texting a smart colleague. If a draft reads like a template, rewrite it — do not ship slop.

在展示任何文案前,都要执行以下检查。看起来像AI生成的触达内容,还不如不发送——这会让读者知道他们在批量列表中。
立即删除以下内容:
  • 破折号。使用句号或逗号替代。
  • 「I hope this finds you well」「I wanted to reach out」「quick question」「circling back」「just following up」这类套话(中文对应「祝您一切顺利」「我想联系您」「快速提问」「再次跟进」「只是跟进一下」等)。
  • **「delve」「leverage」「streamline」「unlock」「elevate」「seamless」「robust」**这类浮夸词汇(中文对应「深入探讨」「利用」「优化」「解锁」「提升」「无缝」「强大」等)。
  • 三段式结构(比如「更快、更便宜、更可靠」)。
  • 否定式并列(比如「不仅是X,更是Y」)。
  • 填充性副词:「really」「actually」「truly」「incredibly」(中文对应「真的」「实际上」「确实」「难以置信地」等)。
  • 虚假的亲切感(比如「祝您工作顺利!」)和虚假的紧迫感。
  • 任何替换公司名称后仍通用的句子。如果适用于所有公司,就不适用于任何公司。
然后大声朗读文案。听起来应像销售代表给聪明的同事发短信。如果草稿读起来像模板,请重写——不要发送冗余内容。

LIST MODE — many accounts, one run

列表模式——批量客户账户,一次运行

When the input is a list (usually a scored list from sales-prospecting), the order is always: hooks → copy → export. Not the reverse.
Step 1 — fan out the hooks. Independent per person, so
parallelMap
them. State the cost before running: posts are 1 credit each, so
limit: 3
across 40 people is up to 120 credits.
js
// 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 })),
};
Everyone in
needCompanyFallback
gets Hook 2 or Hook 3 at the account level, or an honest merge-field template. Never let an empty pull turn into a made-up first line.
Step 2 — contact enrichment is opt-in and cost-confirmed. Quote the worst case before you run it, then run it:
"Business emails for 40 people: at most ~40 credits (1 per matched person). Adding personal emails and phones raises the ceiling to 5 per person, so ~200. Business only — go?"
js
// 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),
};
Omitting
fields
requests all three tiers
(business email, personal email, phone) and takes the ceiling to 5 credits per matched person. Narrow the whitelist to the tiers you actually need, and read
credits_remaining
on the response for the real spend. Report unmatched rows honestly — never pad a list with guessed email patterns.
Step 3 — hand off. Two artifacts, no credentials, no auto-send:
  • Campaign CSV:
    email, first_name, last_name, company, title, linkedin_url, hook_text, hook_date, hook_url, personalization_line, tier
    . The hook, its date, and the link to it ride in the file so the rep can sanity-check every row before it sends.
  • Campaign spec the user pastes into whatever sequencer they run: the sequence steps with the full copy per step, the merge fields used, send window and timezone, daily ramp (start at 20-30/day on a new domain), threading (follow-ups in-thread), and stop-on-reply ON.
  • Deliverability guardrails in the spec: warmed domain, at most one link in touch 1, plain text over HTML, unsubscribe honored instantly.

当输入是列表(通常是sales-prospecting工具生成的评分列表)时,流程顺序始终是:钩子→文案→导出。绝不要颠倒顺序。
步骤1——批量提取钩子。每个客户的钩子提取是独立的,因此使用
parallelMap
处理。运行前说明成本:每篇帖子1积分,因此对40人设置
limit: 3
,最多消耗120积分。
js
// 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积分。仅获取商务邮箱——是否执行?」
js
// 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封)、线程设置(跟进邮件在原线程中回复)、以及开启「收到回复即停止」功能。
  • 可送达性指南:包含在规范中,如使用已养熟的域名、首次触达最多包含一个链接、优先使用纯文本而非HTML、立即执行取消订阅请求。

Rules

规则

  • The hook comes first, and it is real or it is absent. Never fabricate a post, a quote, a round, a mutual connection, or a case study. "I couldn't find a recent signal for this person, here's a role-level angle instead" is a valid, honest answer.
  • Date every reference in the draft and in your notes to the rep, so they can check it in five seconds.
  • One hook, one idea, one ask per touch. Shorter beats clever.
  • Never auto-send anything. Email drafts stay drafts. This skill never writes to a CRM; any log entry is yours to make before writing. Sequencer setup is a spec plus a CSV that the rep loads and starts themselves.
  • Respect opt-outs completely and immediately. Never volume your way past a compliance limit; if the user wants that, it's theirs to own explicitly.
  • No-slop rule on every deliverable (full list above): no em dashes, no "delve"/"leverage"/"streamline", no filler, nothing that survives a find-and-replace of the company name.
  • Costs are real: state expected spend before post pulls, list fan-outs, or contact enrichment. Every
    execute
    response carries
    credits
    and
    credits_remaining
    ;
    account_credits
    (free) reports the balance.
  • Every deliverable ends with the handoff question: copy in chat, a CSV plus campaign spec for your sequencer, or a rendered doc.
  • Adapt the layout to the content — never let it hide anything. The brand system is fixed; the layout is not. If real content doesn't fit — a long company or person name, a 12-word title, 200 rows — change the layout, not the content: let the card grow, wrap instead of truncating, drop to one column, widen the column, raise the cap, or give the wide thing its own scroll container. Never solve a fit problem by clipping a card, ellipsing a name, or silently dropping rows. Where a cap really is unavoidable, say so in the UI ("showing the top 50 of 214"). Look at the rendered output and fix what's cut off before you hand it over.
  • Icons in rendered output: Lucide, the dashboard's icon set, inlined as SVG with a
    currentColor
    stroke. No emojis in artifact UI.
  • Photos and logos are free — use them in rendered output.
    basic_profile.profile_picture_permalink
    (person) rides in the
    basic_profile
    group of any person record handed to you;
    basic_info.logo_permalink
    (company) comes free from
    company_identify
    and from
    company_enrich
    's
    basic_info
    . Neither costs an extra credit. Base64-inline both as
    data:image/jpeg;base64,...
    URIs — the media CDN serves them as
    binary/octet-stream
    , so a remote
    <img src>
    renders blank. Monogram fallback when an image is missing.
  • Artifact branding: copy is chat-native by default, and the CSV stays a plain data file — never render an artifact just to render one. But IF a deliverable is rendered as a page or document (an objection playbook, a sequence spec, a campaign one-pager), it carries the Crustdata brand lockup in the header or footer: a small uppercase "Powered by" eyebrow plus the official Crustdata wordmark, linking to crustdata.com. The wordmark pair ships in this skill's
    assets/
    crustdata-logo-light.png
    (dark text, for light backgrounds) and
    crustdata-logo-dark.png
    (white text, for dark backgrounds). Base64-inline the theme-appropriate variant at ~17px height — never hotlink; rendered artifacts cannot fetch remote images. Brand accent:
    #5547E2
    (
    #8387FF
    on dark grounds). Body font: Geist when embeddable, else the system stack.
  • 钩子优先,真实存在或直接说明。绝不要编造帖子、引用、融资轮次、共同联系人或案例研究。「我无法找到该用户的近期信号,这里提供一个基于岗位层级的切入角度」是有效且诚实的回答。
  • 在草稿和给销售代表的备注中,为所有参考内容标注日期,以便他们能在5秒内验证。
  • 每个触达内容包含一个钩子、一个核心观点、一个请求。简短胜过花哨。
  • 绝不自动发送任何内容。邮件草稿始终为草稿状态。本技能绝不会写入CRM;任何日志条目需在撰写前自行记录。序列工具的设置仅提供规范和CSV文件,由销售代表自行加载并启动。
  • 完全且立即尊重退订请求。绝不要通过批量发送绕过合规限制;如果用户要求这样做,由他们自行承担责任。
  • 所有交付内容必须遵守零冗余规则(完整列表见上文):无破折号、无「delve」/「leverage」/「streamline」这类浮夸词汇、无填充内容、无替换公司名称后仍通用的句子。
  • 成本真实:在提取帖子、批量处理列表或补充联系人信息前,说明预期消耗。每个
    execute
    响应都会包含
    credits
    credits_remaining
    account_credits
    (免费工具)可查询余额。
  • 每个交付内容结尾需包含交付方式问题:文案发送到聊天窗口、CSV+营销活动规范用于序列工具、或渲染为文档。
  • 根据内容调整布局——绝不隐藏任何信息。品牌系统固定,但布局可调整。如果真实内容无法适配布局(比如过长的公司或个人名称、12词标题、200行数据),请调整布局,而非修改内容:允许卡片扩展、换行而非截断、改为单列、加宽列、提高上限、或为宽内容提供独立滚动容器。绝不要通过裁剪卡片、省略名称或静默删除行来解决适配问题。如果确实存在不可避免的上限,请在UI中说明(比如「显示前50条,共214条」)。在交付前查看渲染结果,修复被截断的内容。
  • 渲染输出中的图标:使用Lucide(仪表盘图标集),以内联SVG形式呈现,
    stroke
    属性设为
    currentColor
    。成品UI中不要使用表情符号。
  • 照片和Logo免费——在渲染输出中使用
    basic_profile.profile_picture_permalink
    (个人头像)包含在任何传入的个人记录的
    basic_profile
    分组中;
    basic_info.logo_permalink
    (公司Logo)可从
    company_identify
    company_enrich
    basic_info
    分组免费获取。两者均无需额外积分。将它们以
    data:image/jpeg;base64,...
    的Base64内联形式使用——媒体CDN以
    binary/octet-stream
    格式提供,因此远程
    <img src>
    会显示空白。如果缺少图片,使用字母组合作为 fallback。
  • 成品品牌标识:默认文案为聊天原生格式,CSV保持纯数据文件——绝不只是为了渲染而渲染成品。但如果交付内容需要渲染为页面或文档(比如异议手册、序列规范、营销活动单页),需在页眉或页脚添加Crustdata品牌标识:一个小型大写字母的「Powered by」前缀加上官方Crustdata文字标志,链接到crustdata.com。文字标志文件包含在本技能的
    assets/
    目录中——
    crustdata-logo-light.png
    (深色文字,适用于浅色背景)和
    crustdata-logo-dark.png
    (白色文字,适用于深色背景)。将适配主题的变体以约17px高度进行Base64内联——绝不使用热链接;渲染后的成品无法获取远程图片。品牌强调色:
    #5547E2
    (深色背景下为
    #8387FF
    )。正文字体:优先使用Geist(若可嵌入),否则使用系统字体栈。

Error handling

错误处理

  • A failed call is the dangerous case, not the obvious one.
    r.ok === false
    on a post pull looks identical to "this person doesn't post". Branch on it, report it as an error, and fall back to Hook 2 or Hook 3 — never let it become a generic first line dressed up as personalization.
  • 403 naming a field = a plan-gated projection. Drop that field from
    fields
    and re-run. 403 naming the endpoint (contact enrichment is the common one) = the plan doesn't include it; say so plainly and hand off the list without emails rather than guessing address patterns.
  • Empty posts, empty news, no open roles is a normal outcome, not a failure. Report which sources came back empty and take the no-hook path above.
  • company_identify
    returns several matches
    for one domain — that's expected, it's fuzzy. Take the top
    confidence_score
    ; if two are close, name both and ask.
  • Unmatched rows in a list run are reported by name, never dropped and never silently swapped for a template row.
  • 调用失败是危险情况,而非明显错误。帖子提取时
    r.ok === false
    看起来和「该用户无帖子」完全一样。请进行分支处理,将其报告为错误,并回退到钩子2或钩子3——绝不要让其变成伪装成个性化内容的通用开场话术。
  • 403错误(字段名称):该字段属于付费计划专属。从
    fields
    中移除该字段并重新运行。403错误(端点名称)(常见于联系人信息补充):当前计划不包含该功能;直接说明情况,交付不含邮箱的列表,而非猜测邮箱格式。
  • 无帖子、无新闻、无招聘岗位是正常结果,而非错误。报告哪些来源返回为空,并按照上述无钩子流程处理。
  • company_identify
    为一个域名返回多个匹配结果
    :这是正常的,因为该工具是模糊匹配。选择
    confidence_score
    最高的结果;如果有两个结果得分接近,请列出两者并询问用户。
  • 批量处理中的未匹配条目:按名称报告,绝不删除,也绝不静默替换为模板条目。

Cost cheat sheet

成本速查表

CallCost
company_identify
, autocomplete,
get_schema
,
account_credits
Free
social_post_list_live
1 cr per post
limit
is the spend dial
company_enrich
by id +
exact_match: true
2 cr for one match
job_search
~0.03 cr/result;
limit: 1
+
total_count
≈ 0.03 cr
person_contact_enrich
no base charge, billed per contact type returned per matched person (business email 1, personal 2, phone 2), capped at 5 per person. Narrowing
fields
sets the worst case but is not a guaranteed cap — a single-tier request has been observed billing the full 5-credit cap and returning all three tiers, so quote 5/person as the ceiling and read
credits_remaining
for the actual spend
Writing, classifying, sequencingFree — it's all model work
A single well-hooked cold email typically costs 3-5 credits. A 40-person sequence with hooks and business emails lands around 150-200.
调用成本
company_identify
、自动补全、
get_schema
account_credits
免费
social_post_list_live
每篇帖子1积分——
limit
是成本控制关键
company_enrich
(通过ID +
exact_match: true
每个匹配结果2积分
job_search
约0.03积分/结果;
limit: 1
+
total_count
≈0.03积分
person_contact_enrich
无基础费用,按匹配人员返回的联系人类型计费(商务邮箱1积分,个人邮箱2积分,电话2积分),每人最高5积分。缩小
fields
范围可设置最坏情况成本,但无法保证上限——曾出现过单层级请求仍收取最高5积分并返回所有三个层级的情况,因此请按每人5积分作为上限报价,并查看
credits_remaining
了解实际消耗
撰写、分类、序列构建免费——均为模型处理
一封优质的带钩子冷邮件通常消耗3-5积分。一个包含钩子和商务邮箱的40人触达序列,成本约为150-200积分。

Works with

协同工具

  • sales-prospecting — builds the list and fires the signals this skill writes on. Champion-tracker rows are the highest-converting input here.
  • account-research — deep-dive an account before a big-ticket touch; its account plan gives you the pain map the bridge line needs.
  • icp-builder — writes
    config/persona-profile.md
    (voice) and
    config/gtm-config.md
    (what you sell) from one LinkedIn URL, so drafts sound like the rep from run one.
  • warm-path-workspace — when there's a warm route in, use it: a referral opener beats the best cold email you'll ever write.
  • sales-prospecting——生成列表并触发本技能所需的信号。冠军追踪器的信号行是转化率最高的输入。
  • account-research——在大额触达前深入研究客户账户;其账户计划可提供衔接话术所需的痛点地图。
  • icp-builder——通过一个LinkedIn URL生成
    config/persona-profile.md
    (语气风格)和
    config/gtm-config.md
    (销售产品),让草稿从第一次运行就听起来像销售代表本人撰写。
  • warm-path-workspace——如果有暖场渠道,请使用:引荐开场胜过任何优质冷邮件。

Tool dependencies

工具依赖

This skill requires:
  • Crustdata MCP server (install.crustdata.com/mcp): a single Code Mode MCP exposing
    list_tools
    ,
    get_schema
    , and
    execute
    . All Crustdata data tools are reached inside an
    execute({ code })
    plain-JavaScript script via
    await callTool(name, params)
    — author against the typed surface from
    get_schema
    , but the script body carries zero type annotations (a type annotation is a parse error that fails the whole run). Tools used here:
    social_post_list_live
    ,
    company_identify
    ,
    company_enrich
    ,
    job_search
    ,
    person_contact_enrich
    (opt-in, cost-confirmed),
    account_credits
    .
  • Nothing else. No sequencer credentials, no email-sending access, no CRM write access. Outbound leaves this skill as copy, a CSV, and a written campaign spec — the rep loads and starts it.
本技能需要:
  • Crustdata MCP服务器install.crustdata.com/mcp):一个Code Mode MCP,提供
    list_tools
    get_schema
    execute
    接口。所有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和书面营销活动规范的形式离开本技能——由销售代表自行加载并启动。