mcpField
M
meeting-prep

meeting-prep

github.com/crustdata营销与增长11298 次安装2 周前更新
代码仓库

关于 meeting-prep

meeting-prep 是面向销售代表的准备技能,涵盖入站线索筛选、会前简报及发现或演示通话规划。它以注明日期的证据和透明评分组织研究,并避免用虚构内容填补空白。

主要功能

  1. 01按评分规则筛选入站线索
  2. 02单屏会前简报
  3. 03发现式通话与演示计划
  4. 04注明日期并展示依据
  5. 05可选只读 CRM 和邮件背景

适用场景

  1. 01为一批新提交的线索排序
  2. 02通话前查看公司与联系人的背景
  3. 03根据已说明的客户痛点拟定发现问题

MCP 相关

该技能通过 Crustdata MCP 服务的 `execute` 工具调用 Crustdata。它规定了线索筛选和会前准备中的数据查询与字段投影方式。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/crustdata/skills --skill meeting-prep

安装后在 Claude Code 中输入/meeting-prep确认已加载。

附带文件evals/evals.jsonREADME.md

详细介绍

会议准备

只有一项工作:你今天要参加的电话会议和跟进的潜在客户。 销售代表会在会议间隙打开这份材料,因此每项交付内容都只占一屏,每个判断都标注日期,绝不编造内容来填满某个部分。

三种模式:

  1. 入站线索分流 — 有人填写了表单或发来了邮件。值得花时间跟进吗?
  2. 会前简报 — 日常主力。你可以在通话前的两分钟内读完的一屏内容。
  3. 通话计划 — 发现问题清单,或仅根据明确提出的痛点设计的演示流程。

如果需求中看不出要用哪种模式,就询问对方。“帮我准备下午 2 点的会议”属于模式 2。“评估这个潜在客户”属于模式 1。“帮我制定一份发现问题计划”属于模式 3。


第 0 步 — 背景信息(不会阻碍执行)

  • 如果工作目录中存在 config/gtm-config.md 或 config/persona-profile.md,请读取:ICP、你销售的产品、买家职位、客户名单、竞争对手名单、语气风格。这些信息将用于制定评分标准和确定开场白的语气。
  • 如果这些文件不存在,请在对话中询问 1–2 个问题(“你向哪些客户销售产品——行业、规模、地区?哪些职位的人会购买?”),或提示对方使用 icp-builder skill 来正确构建配置。缺少配置不会阻碍执行。
  • 可选的只读信息补充: 如果已连接 CRM、通话录音工具或电子邮件,可只读检索与同一域名相关的过往邮件往来、备注和通话记录,让简报更加准确——例如过往异议、已经与对方沟通过的人,以及上一笔交易停滞的原因。仅限读取,绝不写入,也绝不以这些信息为交付内容的基础:简报必须仅凭公开数据也能成立。
  • 如果对方说“帮我准备下午 2 点的会议”,但未连接日历,只需询问是哪场会议:公司名称以及要见的人。

Code Mode 基本规则(阅读一次,处处适用)

所有 Crustdata 调用都在 Crustdata MCP 服务的 execute 工具中,以纯 JavaScript 脚本运行(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(list, 25) 分批。绝不要并行处理游标分页或有依赖关系的阶段——identify → enrich 必须按顺序执行,并在每个阶段内部并行处理。
  • company_identify 免费,但匹配较模糊。 一个域名或名称可能匹配多家公司。选择 confidence_score 最高的匹配项。identify 时不要投影 social_profiles——该字段受套餐限制,会导致整个调用返回 403。
  • 受套餐限制的投影会导致整个调用失败并返回 403,错误信息中会指出字段名称。 在 person_search 中绝不要投影 professional_network.followers 或 metadata;在 person_enrich 中绝不要投影 certifications / honors / updated_at。
  • 过滤路径 ≠ 响应路径。 过滤时使用 experience.employment_details.current.company_name;响应键则是 ...current[].name。个人资料 URL 位于 social_handles.professional_network_identifier.profile_url——请使用 profileUrl(p) 访问器。
  • 分类值属于封闭集合。 看似合理但实际错误的值会静默返回零行。按行业、融资轮次类型或资历筛选前,先使用 company_autocomplete / person_autocomplete(免费)解析取值。
  • 结果为零 ≠ 没有信号。 在告知销售代表某个账户没有动静之前,先查看 execute 响应中的 trajectory。

模式 1 — 入站线索初筛

输入:表单或邮件提供的任意信息——姓名、工作邮箱、公司或域名、自报职位,以及通常会有的一段自由文本“你想找什么”。如果运气好,还会有 LinkedIn URL。

步骤 1 — 解析并读取公司信息(成本低,支持批处理)

company_identify 免费,因此先解析每条线索,然后对整批已解析的 ID 只执行一次 company_search,读取规模、行业、融资和增长信息(每行约 0.03 积分)。此处不要使用 company_enrich——每条线索 2 积分,不适合初筛。

// user query: triage today's inbound — 6 form fills
const leads = inputs.leads; // [{ email, name, title, domain }, ...]
const batches = chunk(leads.map(l => l.domain).filter(Boolean), 25);
const identified = await parallelMap(batches, async (batch) => {
  const r = await callTool("company_identify", {
    domains: batch, // ONE identifier type per call
    fields: ["crustdata_company_id", "basic_info"],
  });
  return r.ok ? r.data : batch.map(d => ({ matched_on: d, matches: [], error: r.message }));
});
const rows = identified.flat();
const unresolved = rows.filter(m => !m.matches?.length).map(m => m.matched_on);
const byDomain = {};
for (const m of rows) {
  const top = (m.matches ?? []).slice().sort((a, b) => (b.confidence_score ?? 0) - (a.confidence_score ?? 0))[0];
  const cd = top?.company_data;
  if (cd) byDomain[m.matched_on] = cd.basic_info?.crustdata_company_id ?? cd.crustdata_company_id;
}
const ids = Object.values(byDomain).filter(Boolean);
checkpoint({ ids, unresolved });

const r = await callTool("company_search", {
  filters: in_("crustdata_company_id", ids),
  fields: ["crustdata_company_id", "basic_info", "headcount", "funding", "locations"],
  limit: ids.length,
});
if (!r.ok) return { error: r.message, unresolved };
return {
  unresolved, // personal-email leads and dead domains — surfaced, never silently dropped
  companies: r.data.companies.map(c => ({
    id: c.crustdata_company_id,
    name: c.basic_info?.name,
    domain: c.basic_info?.primary_domain,
    industries: c.basic_info?.industries,
    hc: c.headcount?.total,
    growth12m: c.headcount?.growth_percent?.["12m"],
    lastRound: c.funding?.last_round_type,
    lastRaise: c.funding?.last_fundraise_date,
    country: c.locations?.country,
  })),
};

locations.country 接受 ISO-3(USA)作为筛选值,但返回的是标准化后的全称——不要将响应值与 "USA" 进行比较。

步骤 2 — 时机信号,几乎免费

一次 job_search 聚合调用并将 limit: 0,即可同时获取所有已解析账户的开放职位数量。公司若正在招聘你所销售职能的相关岗位,说明其预算正在流动。

// model query: open-role counts per inbound account (timing signal, counts only)
const r = await callTool("job_search", {
  filters: in_("company.basic_info.company_id", inputs.ids),
  aggregations: [{ type: "group_by", field: "company.basic_info.crustdata_company_id", agg: "count", size: 100 }],
  limit: 0,
});
if (!r.ok) return { error: r.message };
return r.data.aggregations;
第 3 步 — 联系人
  • 提供了 LinkedIn URL → 使用 person_enrich(1 个积分),并设置 fields: ["basic_profile", "experience", "social_handles"]。获取真实职称、真实任职时间和真实雇主信息。对于单个高价值潜在客户,这一步值得做;对于 20 个潜在客户的批次,除非用户提出要求,否则跳过。
  • 没有 URL → 使用自报职称,并在输出中标注为自报信息。表单里的信息可能夸大,也可能低报。
  • 将职称与配置中的 ICP 买家职称进行匹配。规范化的资历级别包含在 person_enrich 和 person_search 都会返回的 experience 组中——读取 cur.seniority_level,不要为此购买搜索。在按此筛选时,取值范围是封闭且优先使用自动补全的集合:Entry Level、Entry Level Manager、Experienced Manager、Senior、Director、Vice President、CXO、Owner / Partner、In Training、Strategic。
第 4 步 — 评分并展示依据

使用满分 7 分的透明评分标准。绝不输出“成交概率 %”——没有历史赢单数据,就没有校准依据;编造百分比还不如不报数字。

项目分值评分依据
公司特征匹配度0-3相对于 ICP 的行业、规模区间和地理位置——每项 1 分
买家职称匹配度0-2明确的买家职称或资历级别 = 2;相邻职称或影响者 = 1;无关职称或资历明显不足 = 0
时机0-2以下每项 1 分,最高 2 分:6 个月内获得融资、12 个月员工人数增长超过 20%、你所售产品对应职能有公开职位、60 天内有相关新闻或帖子

此模式适用于今天主动联系你的潜在客户。要为自己的客户池、销售区域或粘贴的客户 CSV 排序,请改用 sales-prospecting 的“为我的客户排序”方案。

硬性淘汰条件完全凌驾于评分之上。 以下任一情况都意味着拒绝,不论得分多少:竞争对手(如果配置中包含竞争对手名单,则以该名单为准;如果没有,请在应用此淘汰条件前,在询问 ICP 时一并询问竞争对手名单)、现有客户(转给客户负责人处理)、学生或求职者、无法确定所属公司的个人邮箱、你无法服务的地理位置,或员工人数低于最低门槛。

结论等级(聊天输出;在渲染后的内容中显示为彩色标签,绝不用表情符号):

  • 🔥 立即跟进 — 匹配度 ≥ 2、职称 ≥ 1、至少有 1 个时机分,且没有淘汰条件
  • 🟡 培育 — 公司真实存在,但时机或联系人不合适。说明出现什么情况会改变结论
  • ⚪ 拒绝 — 不匹配,或触发了淘汰条件。指出具体原因

每行都要列出理由,并为证据标注日期(“B 轮融资,2026-04-12”“17 个公开职位,其中 4 个属于数据工程”)。没有日期的信号,销售代表就无法使用。

批量模式

用一个表格为当天所有新线索排序:潜在客户 — 公司 — 匹配度 — 职称 — 时机 — 得分 — 结论 — 现在跟进的理由。按得分排序,并按结论分组。将无法解析的域名及其原因(个人邮箱、域名失效、未找到匹配项)单独列在底部,简要说明,确保不遗漏任何线索。然后写:“以下是今天要回拨的 3 位潜在客户。”


模式 2 — 会前简报

日常首选。输入:公司(名称或域名)以及你将会见的对象(姓名,最好附上 LinkedIn URL)。

用一段脚本完成整份简报

先识别(免费、模糊匹配——采用置信度最高的匹配结果),然后并行执行四项互不依赖的查询。人员信息补充不依赖公司信息,人员的发帖历史也不依赖公司信息,因此这两项会在同一阶段运行。

// user query: prep my 2pm with acme.com — meeting their VP Data
const idr = await callTool("company_identify", { domains: ["acme.com"] });
if (!idr.ok) return { error: idr.message };
const top = (idr.data[0]?.matches ?? [])
  .slice().sort((a, b) => (b.confidence_score ?? 0) - (a.confidence_score ?? 0))[0];
if (!top) return { error: "no company match for acme.com" };
const cd0 = top.company_data ?? {};
const companyId = cd0.basic_info?.crustdata_company_id ?? cd0.crustdata_company_id;
const logo = cd0.basic_info?.logo_permalink; // free, use it if the brief gets rendered

const calls = [
  { key: "company", name: "company_enrich", params: {
      crustdata_company_ids: [companyId], exact_match: true,
      fields: ["basic_info", "headcount", "funding", "news"] } },      // 2 cr, exactly one match
  { key: "jobs", name: "job_search", params: {
      filters: { op: "and", conditions: [
        { field: "company.basic_info.primary_domain", type: "=", value: "acme.com" } ]},
      sorts: [{ field: "metadata.date_added", order: "desc" }], limit: 15 } },
  { key: "person", name: "person_enrich", params: {
      professional_network_profile_urls: ["https://www.linkedin.com/in/example"],
      fields: ["basic_profile", "experience", "education", "social_handles"] } }, // 1 cr
  { key: "posts", name: "social_post_list_live", params: {
      professional_network_profile_url: "https://www.linkedin.com/in/example",
      limit: 5 } },                                                    // 1 cr PER POST — cap it
];
const out = await parallelMap(calls, async (c) => ({ key: c.key, r: await callTool(c.name, c.params) }));
checkpoint(out); // ~8-10 credits already spent — bank them before shaping, so a shaping error can't discard them
const get = (k) => out.find(x => x.key === k)?.r;

const ce = get("company");
const cd = ce?.ok ? (ce.data[0]?.matches?.[0]?.company_data ?? {}) : {};
const cutoff = new Date(Date.now() - 60 * 24 * 3600 * 1000).toISOString().slice(0, 10);
const news = (firstArray(cd.news) ?? [])
  .map(n => ({ title: n.article_title, url: n.article_url, date: n.article_publish_date }))
  .filter(n => n.date && n.date >= cutoff)
  .slice(0, 6);

const jr = get("jobs");
const pr = get("person");
const person = pr?.ok ? (pr.data[0]?.matches?.[0]?.person_data ?? {}) : {};
const cur = person.experience?.employment_details?.current?.[0] ?? {};
const posts = get("posts")?.ok
  ? (get("posts").data.posts ?? []).map(p => ({
      date: p.date_posted, text: (p.text ?? "").slice(0, 280),
      reactions: p.engagement?.total_reactions }))
  : [];

return {
  company: {
    name: cd.basic_info?.name,
    what: cd.basic_info?.description,
    hc: cd.headcount?.total,
    growth12m: cd.headcount?.growth_percent?.["12m"],
    lastRound: cd.funding?.last_round_type,
    lastRaise: cd.funding?.last_fundraise_date,
    logo,
  },
  news,
  openRoles: jr?.ok
    ? { total: jr.data.total_count,
        newest: jr.data.job_listings.map(j => ({ title: j.job_details?.title, added: j.metadata?.date_added })) }
    : { error: jr?.message },
  person: {
    name: person.basic_profile?.name,
    title: person.basic_profile?.current_title,
    company: cur.name,
    since: cur.start_date,
    past: (person.experience?.employment_details?.past ?? []).slice(0, 4).map(e => ({ company: e.name, title: e.title })),
    schools: (person.education?.schools ?? []).map(e => e.school).filter(Boolean).slice(0, 3),
    linkedin: profileUrl(person),
    photo: person.basic_profile?.profile_picture_permalink, // free
  },
  posts,
};

关于此脚本的说明:

  • 两个信息补充调用中的 fields 都是白名单——除非主动请求,否则不会返回 news 组;人员的 education 信息则能提供共同的校友话题。
  • social_post_list_live 每篇帖子收费 1 个点数。查看五篇就足以了解对方在谈什么。增加数量前,先说明费用。
  • 如果人员查询没有匹配结果,请确认 URL,然后仅针对公司生成简报。人员信息不完整,坦诚说明即可;编造信息会让销售代表露馅。
  • 想补上 news 组遗漏的最近 60 天信息?执行一次 web_search_live 查询(1 个点数)。只查一次,并丢弃或标注任何超过 60 天的内容。
交付内容——一屏,按以下顺序排列

公司信息 用一句话说明公司业务,然后列出员工人数和过去 12 个月的增长情况、最近一轮融资及其日期、3–5 条带日期的信号(新闻及其 URL、招聘岗位概况、融资事件)。招聘情况比新闻稿更有说服力:20 个数据岗位空缺说明数据工作压力不小;首次招聘安全岗位,则意味着安全预算即将启动。

人员信息 职位和任职时长、一句话概述职业经历、对方最近发布的帖子及日期,以及值得提及的共同点——共同任职过的公司、共同就读过的学校、同一座城市、你们都认识的人。共同点可有可无。牵强附会还不如没有。

销售代表真正会看的部分

  1. 三个谈话要点。 每个要点用一句话表达,并附上依据和日期。不要说“他们增长很快”,而要说“员工人数在 12 个月内增长了 34%,数据团队还有 6 个空缺岗位,因此他们在 2024 年搭建的数据管道可能已经不堪重负。”
  2. 一个开场白。 只写一个完整句子,让你可以直接说出口,并引用 60 天内真实且有日期的事件。如果没有近期信息,就直说,并改为围绕职位背景设计开场白。绝不要为了找开场话题而编造近期事件。
  3. 两个探索性问题。 问题要开放、针对该客户,并根据上述信号提出。
  4. 可能的异议及预先化解方式。 指出此人在该公司规模下担任这一职位时最可能提出的一个异议,并写出一句能提前消除该异议的话。

不要添加其他内容。如果某一部分没有真实信息,就删掉该部分并说明为何为空。

批量生成简报

今天有几通电话?先为所有对象运行识别阶段,然后按日历顺序为每场会议各生成一份简报,每份仍控制在一屏内。开始前说明总点数:每份简报约需 8–10 个点数,因此五场会议大约需要 50 个点数。


模式 3——通话计划

先说明通话类型:需求探索或产品演示。

发现计划
  1. 提出两到三个有依据的痛点假设。 根据模式 2 的信号制定假设——招聘职位、融资、增长率、他们发布的内容。围绕这些假设设计问题之前,先用低成本方式验证:使用 [.] 精确词元运算符统计职位名称和描述中的查询次数。
// model query: which pain themes show up in acme.com job posts
const themes = ["data quality", "observability", "migration"];
const brands = ["Snowflake", "dbt", "Airflow"];
const probes = [
  ...themes.map(t => ({ label: t, cond: { field: "content.description", type: "(.)", value: t } })),
  ...brands.map(b => ({ label: b, cond: exactToken("content.description", b) })), // [.] for brand names
];
const hits = await parallelMap(probes, async (p) => {
  const r = await callTool("job_search", {
    filters: { op: "and", conditions: [
      { field: "company.basic_info.primary_domain", type: "=", value: "acme.com" },
      p.cond,
    ]},
    limit: 1,
  });
  return { probe: p.label, postings: r.ok ? r.data.total_count : null, error: r.ok ? undefined : r.message };
});
return hits;

(.) 可以容忍拼写错误,并匹配相似词——适合描述性的多词主题,但不适合品牌或产品名称。对于这类名称,始终使用 [.](exactToken)。

  1. 问题计划:提出 8-12 个开放式问题,而不是 30 个。 销售代表在首次通话中可能会问八个问题左右。将每个问题对应到资格审核框架中的一个环节——默认使用 MEDDICC;如果用户习惯使用 SPICED,则用 SPICED;如果配置中没有说明,就询问用户。每个问题都包含三项内容:所对应的框架环节、要验证的假设,以及现在提出这个问题的原因。
环节问题验证内容
指标“你们现在如何衡量这方面的成本?”痛点假设 1 已量化
痛点“请跟我说说,当流水线在凌晨 2 点出问题时,会发生什么。”假设 1 确实存在,而非凭空推断
内部支持者“还有谁每周都会受到这件事的影响?”多线拓展路径

提问规则:问题要开放,不要带有诱导性。不要询问公开数据已经回答过的问题——如果员工人数已经列在网页上,还问副总裁团队有多大,就是在浪费你手头唯一的优势。问题要按顺序提出:现状、痛点、影响、流程。

  1. 明确下一步行动。 写出具体的请求,并注明日期和姓名。“下周二安排 30 分钟的工作会议,请你们的数据负责人参加,这样合适吗?”比“我们找时间聊聊”更好。

  2. 检查覆盖范围。 列出这次通话无法覆盖的框架环节,让销售代表知道还有哪些内容要留到第二次通话,而不是等到预测时才发现。

演示流程

只根据潜在客户实际陈述的痛点来设计。 “实际陈述”的来源包括:用户粘贴了发现阶段的笔记;本次会话中,通话计划紧接着发现阶段的通话;或者已连接的录音工具或 CRM 中有笔记(只读)。公开信号只能用于提出假设,不能当作已陈述的痛点——两者要分开并明确标注。

如果发现阶段的信息不足,要在开始制作前说明。 “你目前陈述了一个痛点,另外还有两个假设。这次演示会比较笼统。要不要先安排 15 分钟进行发现?”如果对方仍想继续,就制作较短版本。

结构:

  1. 开场回顾——用潜在客户自己的措辞复述他们的痛点。展示任何内容之前先确认。
  2. 每个已陈述的痛点对应一个环节,按潜在客户优先级排序,而不是按你的功能顺序:说明要展示什么,以及这为什么对他们重要;展示内容;然后确认(“这符合你们团队的使用方式吗?”)。没有已陈述痛点支撑的环节就删掉——这正是该模式的核心准则。
  3. 结束计划——明确下一步行动、还需要谁参与、他们需要决定什么,以及最晚何时决定。

明确列出你不会展示的内容及原因。主动跳过六项功能的演示,会让人觉得你很有信心。


规则

  • 仅依据可靠信息。 简报中的每项陈述都必须能追溯到 Crustdata 的结果、URL 或用户提供的信息。信息不明确时,先询问或省略。绝不编造近期事件、共同联系人或痛点。
  • 所有内容都标注日期。 没有日期的信号不可用。超过 60 天的内容标记为背景信息。
  • 每份交付内容控制在一屏内。 销售代表会快速浏览。宁可删减章节,也不要凑字数。
  • 撰写的每个字都必须严谨。 开场白、问题、回顾都不例外:不用长破折号,绝不使用 “delve”/“leverage”/“streamline”,不写填充句。像做足功课的同事那样写。
  • 区分自述信息与已验证信息。 在 Crustdata 确认之前,表单数据都属于自述信息。请注明。
  • 优先使用免费数据。 联系人信息补全须由用户选择并确认费用。person_contact_enrich 没有基础费用,按每位匹配人员返回的联系人类型计费(工作邮箱 1 个积分,个人邮箱 2 个积分,电话 2 个积分),每人最多 5 个积分。缩小 fields 范围可设定最坏情况下的费用,但不能保证费用上限;已有观察表明,单层级请求也可能收取完整的 5 个积分上限,并返回全部三个层级。因此,应将每人 5 个积分作为最高费用,并读取 credits_remaining 了解实际支出。运行前先报出最高费用(“12 位潜在客户的邮箱 = 最多约 60 个积分,可以吗?”)。
  • 对已连接的系统只读。 如果 CRM、录音工具或电子邮件已连接,可读取其中的信息来完善简报。此技能绝不会写入、记录、发送或安排任何内容。
  • 绝不输出成交概率百分比。 应展示评分细则的分数和评分原因。
  • 根据内容调整布局,绝不能因此隐藏内容。 品牌系统固定,布局不固定。如果实际内容放不下,例如公司名称很长、职位名称有 12 个词,或有 40 条入站记录,就调整布局:让卡片增高、换行而不是截断、改为单栏、提高显示上限,或为宽内容设置独立滚动容器。绝不裁切卡片、用省略号截断名称,或悄悄省略记录。任何无法避免的上限都要在界面中说明(“正在显示 214 条中的前 50 条”),并在交付前检查渲染结果。
  • 渲染输出中的图标:使用 Lucide,并以内联 SVG 形式呈现,描边使用 currentColor。产物界面中不得使用表情符号:🔥/🟡/⚪ 仅限聊天中表示判定等级;在渲染后的简报中应改为彩色标签。
  • 渲染输出中免费使用 Logo 和照片。 免费的 company_identify 会返回 basic_info.logo_permalink;person_enrich 返回的 basic_profile 组中包含 basic_profile.profile_picture_permalink。两者都以内联 Base64 形式转换为 data:image/jpeg;base64,... URI;媒体 CDN 提供的内容类型为 binary/octet-stream,因此远程 <img src> 会显示空白。图片缺失时使用姓名首字母缩写作为备用。
  • 产物品牌标识:简报和分流表默认采用聊天原生形式,不要为了渲染而渲染产物。但如果用户要将简报或分流看板渲染为页面或文档,页眉或页脚必须包含 Crustdata 品牌标识:小号大写的“Powered by”眉题,以及链接到 crustdata.com 的 Crustdata 官方字标。此技能的 assets/ 中提供了成对的字标文件:crustdata-logo-light.png(深色文字,适用于浅色背景)和 crustdata-logo-dark.png(白色文字,适用于深色背景)。将适合主题的版本以内联 Base64 形式嵌入,高度约为 17px;绝不使用远程链接,渲染后的产物无法获取远程图片。品牌强调色:#5547E2(深色背景上使用 #8387FF)。如果可嵌入则使用 Geist 正文字体,否则使用系统字体栈。
  • 交接:需要完整客户账户计划的高意向入站线索 → account-research;寻找更多类似公司 → sales-prospecting;尚未定义 ICP → icp-builder;了解我们在那里已经认识谁 → warm-path-workspace;撰写这份简报所规划的触达内容 → sales-outreach。

错误处理

  • 每个脚本都要根据 r.ok 分支处理。 未检查的失败看起来像是“没有信号”,销售代表会误以为一切正常,直接去参加通话。
  • company_identify 未匹配到结果 → 潜在客户的域名可能是个人域名、停放域名或新域名。说明原因,并将其标记为尚未解决;切勿猜测所属公司。
  • 403 响应中指出某个字段时,表示该字段对应的投影受套餐限制——移除该字段后重新运行。
  • person_enrich 未匹配到结果 → 确认 URL,然后仅基于公司信息生成简报,并说明个人信息部分不完整。
  • 没有帖子或新闻不算错误。说明“过去 60 天内没有公开动态”,并根据职位背景撰写开场白。
  • 每个 execute 响应都包含 credits 和 credits_remaining;可按需免费调用 account_credits 查询余额。

费用速查表

调用费用
company_identify、自动补全、get_schema、account_credits免费
company_search / person_search / job_search约 0.03 cr/条结果
job_search 使用 limit: 0 进行聚合仅计数,约等于免费
person_enrich(仅资料组)1 cr
使用 exact_match: true 按 id 调用 company_enrich单条匹配结果 2 cr
social_post_list_live每条帖子 1 cr——始终设置 limit
web_search_live每次查询 1 cr
person_contact_enrich(选择加入)无基础费用;每人上限 5 cr——缩小 fields 范围不保证能达到该上限

典型费用:对 10 条潜在客户进行分流,费用不到 1 个 credit。完整的会前简报约需 8-10 个 credit。

工具依赖项

此技能需要:

  • Crustdata MCP 服务(install.crustdata.com/mcp):一个 Code Mode MCP,提供 list_tools、get_schema 和 execute。所有 Crustdata 数据工具都通过 execute({ code }) 中的纯 JavaScript 脚本调用,使用 await callTool(name, params)——编写代码时依据 get_schema 提供的类型化接口,但脚本主体中不包含任何类型注解。此处使用的工具:company_identify、company_search、company_enrich、person_search、person_enrich、job_search、social_post_list_live、web_search_live、company_autocomplete、person_autocomplete、person_contact_enrich(选择加入)、account_credits
  • 可选连接器:用户可能已有的 CRM、通话录音工具、日历和电子邮件——均为只读,全部可选。此技能完全依靠公开数据运行,无需使用这些连接器

该技能与 icp-builder(编写此技能读取的配置)、sales-prospecting、account-research 和 warm-path-workspace 一同发布。

评论

支持 Markdown