关于 candidate-sourcing
Candidate Sourcing Pipeline 是一项技能,可根据招聘需求为候选人生成 Gmail 草稿。它依次完成候选人发现、个人资料链接核验、邮箱查找和个性化联系内容撰写,最终由人工审核并发送。
主要功能
- 01明确招聘需求和候选人条件
- 02按技术成果寻找候选人
- 03通过搜索核验个人资料链接
- 04查找商务或个人邮箱
- 05创建个性化 Gmail 草稿
适用场景
- 01为明确的岗位搜寻候选人
- 02联系前核验候选人资料
- 03准备供审核的定制招聘邮件
MCP 相关
该技能通过 Code Mode `execute` 使用 Crustdata MCP 工具,包括 `person_search`、`person_enrich` 和 `web_search_live`,用于发现候选人、核验资料和补充联系信息。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ crustdata/ skills --skill candidate-sourcing安装后在 Claude Code 中输入/candidate-sourcing确认已加载。
附带文件evals/evals.jsonREADME.md
详细介绍
候选人寻访流程
一项端到端技能:输入招聘岗位,为优秀候选人生成可直接发送的 Gmail 草稿——在一个连续工作流中完成候选人发现、个人资料 URL 验证、邮箱信息补全、个性化文案撰写和草稿创建。
该流程分为五个阶段。每个阶段的结果都会传递给下一个阶段;此技能旨在按顺序执行这些阶段,尽可能减少人工干预。用户审核最终的 Gmail 草稿并点击发送。
阶段 1:定义搜索条件并寻找候选人
确认岗位和公司信息
搜索之前,先从用户处提取或确认以下信息。不要自行假设任何信息——如果用户未提供,务必询问:
招聘公司信息(阶段 4 外联时需要):
- 公司名称
- 公司业务(1–2 句话)
- 公司发展阶段/业绩表现(例如,“A 轮融资,融资额达 $10M”或“拥有 500 名员工的上市公司”)
- 地点/远程办公政策
- 发件人的姓名和职位(用于邮件签名)
岗位和理想候选人信息:
- 岗位名称(例如,“创始团队机器学习工程师”)
- 岗位涉及的 2–3 个核心技术问题
- 目标公司、研究实验室或要搜索的社区
- 优先考虑的学校/校友关系(例如,“IIIT Hyderabad 校友”)
- 地点偏好或限制
- 用户希望本批次包含多少名候选人
理想候选人画像:
- 职级(例如,“3–7 年经验”、“高级”、“Staff 及以上”)
- 必备技术技能或领域专业知识
- 加分项(开源贡献、发表论文、特定框架)
- 排除条件或筛选标准(例如,“不考虑长期在 FAANG 工作的人”、“必须有初创公司经验”)
利用公司和岗位信息,调查这家公司对候选人的吸引力所在——通过 Crustdata MCP 的 web_search_live 工具查看公司网站、近期融资、产品发布或媒体报道。这项调查将为阶段 4 的公司简介提供信息。
根据技术成果搜索,而非职位名称
以下三项信号比工作年限或公司声望更重要:
工作成果——他们撰写的论文、实际有人使用的工具/代码仓库、具有技术深度的博客文章、开源贡献、发布的演示或基准测试。
进取心——公开发表的技术观点、博客文章和新闻通讯、会议演讲、被他人引用,以及持续参与开源项目,而不只是提交代码。
相关性——他们的具体工作与岗位中的实际问题相对应,而不只是涉及相邻领域。
搜索来源和模式
Crustdata person_search(通过 Code Mode 的 execute 工具)进行结构化搜索:
// model query: find ML engineers at Company Name
const r = await callTool("person_search", {
filters: { op: "and", conditions: [
{ field: "experience.employment_details.current.title", type: "(.)", value: "ML Engineer" },
{ field: "experience.employment_details.current.company_name", type: "[.]", value: "Company Name" },
]},
limit: 20,
});
if (!r.ok) return { error: r.message };
return r.data.profiles.map(p => ({
name: p.basic_profile?.name,
title: p.basic_profile?.current_title,
url: p.social_handles?.professional_network_identifier?.profile_url,
}));
研究论文——围绕核心技术问题搜索学术论文和预印本。关注第一作者和第二作者,尤其是那些不在顶尖 5 家实验室的人。
开源代码仓库——按主题/关键词搜索代码仓库,关注有实质贡献的参与者(而不只是维护者)。
Crustdata 网页搜索(web_search_live)——"[technical problem]" site:arxiv.org、"[name]" "[company]" github、"[community]" alumni engineer ML。
阶段 1 的输出
候选人名单,每位候选人包含:全名、当前职位、当前公司、学校/社区关联信息,以及一项体现其相关性的具体工作成果(论文、代码仓库、工具或帖子)。这条“工作成果”备注至关重要——它将成为阶段 4 外联邮件开场白的依据。
阶段 2:验证个人资料 URL
绝不要猜测或拼接个人资料 URL。 这是外联中最常见的错误来源。猜测的 URL(例如 firstname-lastname 或 firstname-lastname-school)经常返回 404,或指向错误的人。真实的 slug(即 linkedin.com/in/ 后面的部分)由系统自动生成,形式类似 david-park-086833264 或 hongjunchoi92——无法根据一个人的姓名推测。
瀑布式流程
严格按照以下优先级顺序操作。获得有把握的匹配后立即停止。
步骤 1:person_search(始终首先尝试)
// model query: verify the profile URL for Person Name at Company Name
const r = await callTool("person_search", {
filters: { op: "and", conditions: [
{ field: "basic_profile.name", type: "[.]", value: "Person Name" },
{ field: "experience.employment_details.current.company_name", type: "[.]", value: "Company Name" },
]},
limit: 3,
});
if (!r.ok) return { error: r.message };
return r.data.profiles.map(p => ({
name: p.basic_profile?.name,
headline: p.basic_profile?.headline,
url: p.social_handles?.professional_network_identifier?.profile_url,
}));
提取 social_handles.professional_network_identifier.profile_url — 这是经过验证的规范个人资料 URL。
提示:
- 公司名称可能有不同写法(“Google DeepMind” 与 “DeepMind” 与 “Google”)— 先尝试较短的名称,再尝试其他写法
- 如果结果为 0,尝试过往雇主(
experience.employment_details.past.company_name),或使用姓名并扩大筛选范围 - 如果有多个结果,请根据头衔、所在地或教育经历进行匹配
- 为提高效率,将这些操作作为单个
execute脚本运行:使用parallelMap并行执行独立查询(先对候选列表分批,再进行映射)
步骤 2:web_search_live(步骤 1 返回 0 条结果时的备用方案)
// model query: find the profile URL for Person Name at Company
const r = await callTool("web_search_live", {
query: "Person Name Company distinctive-keyword",
site: "linkedin.com",
});
if (!r.ok) return { error: r.message };
return r.data.results;
查看摘要,核对雇主和职位是否匹配,以验证结果。不要直接使用第一个个人资料 URL。
步骤 3:标记为未经验证(两种方法均失败时)
保留现有 URL(如有),但添加备注:“LinkedIn URL unverified.” 切勿捏造 URL。
Slug 对比
验证现有 URL 时,提取 slug(linkedin.com/in/ 后面的部分),去除末尾斜杠,并忽略大小写进行比较。Slug 不同表示 URL 错误,请改用 social_handles.professional_network_identifier.profile_url 中经过验证的 URL。
此流程可避免的真实错误
以下是生产推广活动中出现过的实际错误:
| 猜测的 slug | 实际 slug | 结果 |
|---|---|---|
david-park-princeton | david-park-086833264 | 404 — slug 是编造的 |
vincent-chen-mit | vincent-chen-662a031b5 | 404 — 学校后缀无效 |
benoit-rostykus | benoitrostykus | 找错人 — 是另一个人的个人资料 |
hongjun-choi | hongjunchoi92 | 找错人 — 是另一个人的个人资料 |
abhay-gupta-cmu | gupta-abhay | 找错人 — slug 格式完全不同 |
benedict-arockiaraj | benedictflorance | 找错人 — 此人在 LinkedIn 上使用了不同的姓名 |
initeshmethani | nitesh-methani-7554b3121 | 找错人 — 猜测的 slug 中有拼写错误 |
URL 格式
始终使用 https://www.linkedin.com/in/{slug} — 不要使用缺少协议的裸 linkedin.com/in/。像 ü 这样的字符需要进行 URL 编码(%C3%BC)。
第 3 阶段:查找电子邮件地址
每位候选人都需要一个电子邮件地址,用于 Gmail 草稿。请按以下优先顺序查找。
3A:通过 Crustdata 补充获取工作邮箱
使用 person_enrich(通过 Code Mode execute 工具)。该工具在 professional_network_profile_urls 中接受 LinkedIn URL 数组(每次调用 ≤25 个 — 使用 chunk(urls, 25) 分块,然后通过 parallelMap 并行处理),并在 fields 中接受字段组(而非叶子字段名)。contact 组会返回电子邮件和电话号码:
// model query: enrich business emails for a batch of candidate LinkedIn URLs
const urls = ["url1", "url2", "url3"]; // from Phase 2
const batches = chunk(urls, 25);
const results = await parallelMap(batches, async (batch) => {
const r = await callTool("person_enrich", {
professional_network_profile_urls: batch,
fields: ["basic_profile", "contact"],
});
return r.ok ? r.data : [];
});
// each match: matches[0].person_data.contact.business_emails[].email
return results.flat();
contact 字段组至关重要 — 默认响应(仅包含 basic_profile)不包含电子邮件。请通过 matched_on 将每条结果映射回对应的输入 URL。
**预期命中率:**知名公司的专业人士约为 70-80%,独立从业者约为 40-50%,处于职业过渡期的人士约为 20-30%。
3B:通过 Crustdata 联系人丰富获取个人邮箱
如果只需要联系人数据,出于成本考虑,优先使用 person_contact_enrich,而不是 person_enrich。 person_enrich 可以通过其 contact 组返回个人邮箱(+2)和电话(+2),但也会收取基础资料费用(基础 1 + 联系人层级费用,封顶 7)。person_contact_enrich 是仅处理联系人的工具——它不收取基础资料费用(封顶 5),因此只需要联系人数据时更便宜。在回退到提交记录查询(3C)之前,请先尝试此工具。
person_contact_enrich 接受相同的 professional_network_profile_urls 数组(每次调用 ≤25 个),并返回一个包含 business_emails、personal_emails 和 phone_numbers 的 contact 对象。通过带点号的 fields 选择层级:
// model query: enrich personal emails + phone for candidate LinkedIn URLs
const r = await callTool("person_contact_enrich", {
professional_network_profile_urls: chunk(urls, 25)[0],
fields: ["contact.personal_emails", "contact.phone_numbers"],
});
if (!r.ok) return { error: r.message };
// per match: matches[0].person_data.contact.personal_emails[].email (objects), .phone_numbers[] (bare strings)
return r.data;
响应中的 person_data.contact 对象包含一个 personal_emails 对象数组({ email, status } — 读取 .email,与 business_emails 相同;包括 Gmail、ProtonMail 等)和一个由纯字符串构成的 phone_numbers 数组。
积分费用: person_contact_enrich 不收取基础费用,按联系人层级计价——大致为 +1 个商务邮箱、+2 个个人邮箱、+2 个电话号码,每个档案最高 5 积分。这些单项层级数值是边际费用/上限估算,并非保证的封顶费用:请求单个带点号的层级并不能可靠地将账单限制在该层级的增量内——据观察,fields: ["contact.personal_emails"] 调用会按完整的 5 积分封顶费用计费,并返回全部三个层级。由于省去了基础资料费用,获取联系人数据时它仍比 person_enrich 便宜,但不要假设单个带点号的字段会将费用限制在封顶值以下。
批次限制: 每次调用最多 25 个 LinkedIn URL。
推荐做法: person_contact_enrich 一次调用即可返回商务邮箱、个人邮箱和电话——同时请求所需层级,以减少往返调用。person_enrich(阶段 3A)也可以通过其 contact 组返回全部三个联系人层级,但它会额外收取基础资料费用,因此只需要联系人数据时优先使用 person_contact_enrich。
如果找到了个人邮箱,冷邮件联系时优先使用个人邮箱,而非商务邮箱(回复率更高,也不太容易被企业垃圾邮件过滤器拦截)。如果此工具未能为候选人找到个人邮箱,请继续使用下面的提交记录查询。
3C:通过公开提交历史获取个人邮箱(3B 无结果时的后备方案)
这是针对技术候选人最有力的技巧。Git 会在每次提交中记录作者的邮箱。
步骤 1:查找 GitHub 用户名
- 优先使用原生方式:在
fields中使用social_handles调用person_enrich,可返回dev_platform_identifier(开发者账号);添加dev_platform_profiles(开发者附加项,+1 积分)则可返回完整的开发者档案——仓库、组织成员身份,有时还包括公开的email。如果该email存在且不是 noreply 地址,就使用它并直接跳到步骤 5 - 对已解析的人员调用
dev_platform_enrich({ crustdata_person_id }),可独立获取相同信息 - 网页搜索:
"[Name] [Company] GitHub site:github.com" - 查看其个人网站或社交资料简介
步骤 2:确认 GitHub 档案属于此人 以下条件至少确认 2 项:简介提及已知公司/职位、档案名称匹配、仓库主题与已知专业领域一致、网页搜索确认两者关联。
步骤 3:查找最早的非派生仓库
如果步骤 1 执行了开发者丰富查询,其 dev_platform_profiles[].repos 条目已包含 full_name、is_fork 和 github_created_at——直接选择最早的非派生仓库,无需额外调用。否则,通过 GitHub API 列出仓库:
// model query: list oldest repos for GitHub user {username}
const r = await callTool("web_enrich_live", {
urls: ["https://api.github.com/users/{username}/repos?sort=created&direction=asc&per_page=5"],
});
if (!r.ok) return { error: r.message };
return r.data; // [{ success, url, title, content }]
选择第一个 "fork": false 的仓库。
步骤 4:从提交中提取邮箱
方法 A — Commits API:
// model query: read first commit of {owner}/{repo}
const r = await callTool("web_enrich_live", {
urls: ["https://api.github.com/repos/{owner}/{repo}/commits?per_page=1"],
});
在获取的 content 中查找 [0].commit.author.email。
方法 B — .patch 端点:
// model query: read commit patch for {owner}/{repo}@{sha}
const r = await callTool("web_enrich_live", {
urls: ["https://github.com/{owner}/{repo}/commit/{sha}.patch"],
});
从获取的 content 中提取 From: Name <email> 标头行。
步骤 5:验证 — 丢弃 *@users.noreply.github.com、[email protected],以及任何包含 noreply 的邮箱。
3D:网页搜索备选方案
如果 Crustdata 个人邮箱补全和提交记录查找都不起作用,请按以下顺序尝试:
- 代码仓库(问题、README):
"[name]" "@gmail.com" site:github.com - 竞赛编程:
"[name]" site:codeforces.com - 个人网站:
"[name]" "[company]" email contact - 会议演讲者页面:
"[name]" "[company]" speaker email - 学术档案:
"[name]" site:scholar.google.com
3E:GitHub API 速率限制
GitHub REST API 有速率限制。如果请求返回速率限制消息(“API rate limit exceeded”),请停止本批次剩余候选人的提交记录查找。将这些候选人转到 3D,或将其记录为 no_contact,在限制重置前不要重试。
邮箱优先级
如果某位候选人有多个邮箱,请按以下顺序优先选择:
- 个人 Gmail/ProtonMail——冷启动外联的回复率最高
- 大学邮箱——如果他们仍在学术界
- 工作邮箱——冷启动外联的最后选择(通常会被企业垃圾邮件过滤器拦截)
第 4 阶段:撰写个性化外联邮件
唯一重要的规则
赞扬具体作品,而不是职位或暗示的能力。
“在 Mistral 领导应用科学工作,说明你知道如何将机器学习从研究推向生产”读起来就像是“我看了你的 LinkedIn 职位,然后套用了模板”。相反,要找到他们实际做过的一件事,并真诚地谈谈。
邮件结构
每封邮件都遵循以下固定模板:
Hi {first_name},
[1-sentence opener: say what impressed you — casual, no analysis]
[1-sentence pitch: role + company + location]
[3-line company blurb]
{sender_name},
{sender_title}
简短即可。不要加标题、项目符号或多段解释。如果用户尚未提供,请向用户询问姓名、职位、公司名称,以及 2-3 行的公司简介。
撰写开场白
使用第 1 阶段的“成果证明”记录——在发现候选人时找到的具体论文、仓库、工具或帖子。
好的开场白示例:
- “读了你关于[具体论文/项目]的作品——[真诚的感想]。”
- “你的[具体工具/仓库]很[具体且诚恳的评价]。”
- “从[具体经历节点 A]到[B]的历程令人印象深刻。”
糟糕的开场白示例(切勿使用):
- [他们的作品] + [与我们也做 X 相关]——把赞美变成推销
- [在公司的职位] + [因此具备 X 技能]——依据职位而非作品
- [他们的研究] + [正是我们需要的思维方式]——替对方评价自己
- 过长的括号补充说明——破坏轻松自然的行文节奏
推介内容
“我们正在[地点]为[公司]招聘一名[职位]。你有兴趣吗?”
直接明了即可。开场白已经起到了作用。
公司简介
如果用户尚未提供,请向用户索要 2-3 行的公司简介。内容应突出业务进展、使命以及当前时机的重要性。在一批邮件中略微变换措辞,避免邮件完全相同。
主题行
默认:"[Role] @ [Company]"
第 5 阶段:创建 Gmail 草稿并记录到跟踪表
创建 Gmail 草稿
对于每位有已验证邮箱的候选人,使用 gmail_create_draft:
to:候选人的邮箱地址subject:主题行body:完整邮件(开场白 + 推介内容 + 公司简介 + 签名)
这是最后一步。Gmail 的 MCP 会创建草稿,但无法发送——用户需要检查后手动点击发送。
记录到外联跟踪表
创建每份草稿后,将一行追加到该职位专用的 CSV 跟踪表:
/sessions/{session}/mnt/outputs/outreach_tracker_{role_slug}.csv
其中,role_slug 为小写并以连字符连接(例如,“Founding ML Engineer” → founding_ml_engineer)。
CSV 标题行:
date,role_hiring_for,candidate_name,current_role,company,school_connection,linkedin_url,email,channel,subject,message_opener,status,notes,message_body
import csv, datetime, os
tracker_path = "outreach_tracker_{role_slug}.csv"
fields = ["date","role_hiring_for","candidate_name","current_role","company",
"school_connection","linkedin_url","email","channel","subject",
"message_opener","status","notes","message_body"]
row = {
"date": datetime.date.today().isoformat(),
"role_hiring_for": "<role name>",
"candidate_name": "<full name>",
"current_role": "<title>",
"company": "<company>",
"school_connection": "<school or empty>",
"linkedin_url": "<verified linkedin url>",
"email": "<email address>",
"channel": "email",
"subject": "<subject line>",
"message_opener": "<first sentence of email body>",
"status": "drafted",
"notes": "<email type + source: e.g. Personal Gmail via commit history>",
"message_body": "<full email body>"
}
file_exists = os.path.isfile(tracker_path)
with open(tracker_path, "a", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=fields)
if not file_exists:
writer.writeheader()
writer.writerow(row)
状态值: drafted(已创建 Gmail 草稿)、sent(用户已点击发送)、replied(已回复)、no_contact(未找到邮箱)。
渠道值: email
没有邮箱的候选人
如果完成整个信息补全流程后仍未找到邮箱,请将候选人记录到跟踪表中,设置 status: "no_contact",并添加说明,解释尝试过哪些方法。用户可以决定是否手动通过其他渠道跟进。
提高效率的批量工作流
处理大量候选人(>5)时,按以下顺序操作以尽量节省时间:
- 搜索并收集候选人(第 1 阶段)——先建立完整名单
- 批量验证个人资料 URL(第 2 阶段)——在一个
execute脚本中,使用parallelMap并行调用person_search查找;失败时回退到网页搜索(web_search_live) - 批量补充邮箱信息(第 3A + 3B 阶段)——先调用
person_enrich(fields: ["basic_profile", "contact"])获取个人资料和工作邮箱,再调用person_contact_enrich(fields: ["contact.personal_emails", "contact.phone_numbers"])获取个人邮箱和电话号码(仅补充联系方式时成本更低——跳过基础个人资料费用)。每次调用最多批量处理 25 个 LinkedIn URL(chunk(urls, 25),再使用parallelMap) - 筛选需查找提交记录的候选人(第 3C 阶段)——找出仍缺少邮箱、且作为工程师很可能拥有 GitHub 个人资料的候选人;优先通过提交记录提取邮箱
- 批量查找提交记录(第 3C 阶段)——每次调用
web_enrich_live时传入多个 GitHub URL(urls: [...]) - 网页搜索回退(第 3D 阶段)——适用于 Crustdata 信息补充和提交记录查找均失败的候选人
- 撰写所有邮件文案(第 4 阶段)——一次性拟好所有开场白,并使用第 1 阶段的工作成果证明记录
- 创建所有 Gmail 草稿(第 5 阶段)——创建草稿并记录到跟踪表
处理大型 API 响应
Crustdata 信息补充和 person_search 调用可能会返回大型负载。在 Code Mode 中,应在 execute 脚本内部缩减响应后再返回——只有 return 的内容才会传递给模型。使用 project/pick/compact 仅保留所需字段,以免后续再次解析完整负载:
// model query: search candidates and return a slim projection
const r = await callTool("person_search", { filters, limit: 25 });
if (!r.ok) return { error: r.message };
return r.data.profiles.map(p => ({
name: p.basic_profile?.name,
url: p.social_handles?.professional_network_identifier?.profile_url,
}));
始终在脚本内部缩减响应(返回 ID/URL/邮箱,而不是完整个人资料),不要直接返回原始响应。
工具依赖项
此技能需要:
- Crustdata MCP 服务(install.crustdata.com/mcp):一个提供
list_tools、get_schema和execute的 Code Mode MCP。所有 Crustdata 数据工具都通过execute({ code })中的纯 JavaScript 脚本调用:await callTool(name, params)——根据get_schema提供的 TypeScript 类型接口编写代码,但不要在代码主体中添加类型注解。此处使用的工具:person_search、person_enrich(个人资料 + 工作邮箱)、person_contact_enrich(个人邮箱 + 电话号码)、company_enrich、dev_platform_enrich(Dev Platform:开发者个人资料 + 仓库)、web_search_live、web_enrich_live - Gmail MCP:
gmail_create_draft - Python(搭配用于电子表格 I/O 的
openpyxl和用于跟踪表的csv) - 网页搜索(Crustdata
web_search_live):用于回退式邮箱查找
创始人排除规则
不要联系现任创始人、联合创始人、CEO 或 CTO——这些人正在运营自己的公司。他们不太可能离职,联系他们既浪费名额,也可能显得不合时宜。
如何识别创始人
在第 1 阶段查看候选人的当前职位。若职位包含以下任一字样,请将其标记:Founder、Co-Founder、Co-founder、CEO、CTO,或同时包含 “Chief” 和 “Officer”(例如 Chief Technology Officer)。
公司规模收缩例外
唯一值得联系现任创始人的情况,是他们的公司正明显走向失败。以下三个条件必须全部满足:
-
员工人数正在减少 — 使用
company_enrich和公司的域名:// model query: check headcount trend for example.com const r = await callTool("company_enrich", { domains: ["example.com"], fields: ["basic_info", "headcount", "web_traffic"], }); if (!r.ok) return { error: r.message }; // per match: matches[0].company_data.headcount.{ total, growth_percent } return r.data;检查
headcount.growth_percent(键为mom、qoq、six_months、yoy、two_years)——关注月环比(mom)和季环比(qoq)增长为负的情况。 -
网站流量正在下降 — 检查月访客量是否呈下降趋势。
从
company_enrich中读取web_traffic.domain_traffic(请求fields: ["web_traffic"]),查看月访客量趋势;seo和news分组也可用相同方式获取。 -
员工离职速度超过公司可承受的程度 — 过去 3 个月离职的前员工人数超过当前员工人数。这表明公司正在流失员工,而不只是停滞不前。
如果三个条件全部满足,创始人可能愿意考虑新的机会。如果任一条件不满足(例如,公司规模较小但正在增长),就跳过该候选人,并在跟踪表中将其标记为 status: "skipped",附上类似 "Excluded — active founder (company not shrinking)" 的备注。
处理增强数据响应
company_enrich 会返回一个 { matched_on, match_type, matches: [{ confidence_score, company_data }] } 数组。在 execute 脚本中对其进行精简,只返回所需的员工人数信号:
// model query: project headcount growth signals for founder-company check
const r = await callTool("company_enrich", { domains: ["example.com"], fields: ["basic_info", "headcount"] });
if (!r.ok) return { error: r.message };
return r.data.map(m => {
const cd = m.matches?.[0]?.company_data;
const hc = cd?.headcount ?? {};
const g = hc.growth_percent ?? {};
return { name: cd?.basic_info?.name, total: hc.total, mom: g.mom ?? 0, qoq: g.qoq ?? 0 };
});
实际示例
| 候选人 | 公司 | 结果 |
|---|---|---|
| Di Jin(联合创始人) | Eigen AI(12 名员工,月环比 -7.7%) | 略有下降,但离职的前员工人数不足 → 跳过 |
| Sai Surbehera(联合创始人/CTO) | Lapis Labs(5 名员工,月环比 +25%) | 公司正在增长 → 跳过 |
| Aayush Anand(联合创始人) | Level.game(9 名员工,稳定) | 公司运营正常 → 跳过 |
不要这样做
- 切勿猜测个人资料 URL — 始终通过 Crustdata 验证。猜测的 URL 曾在一场仅有 91 人的活动中导致 12 次错误。
- 切勿发送电子邮件 — Gmail MCP 只会创建草稿。用户会审核并手动发送。
- 切勿使用基于职位头衔的开场白 — 始终提及候选人做过的具体工作。
- 切勿跳过电子邮件验证 — 丢弃 noreply 地址,并确认 GitHub 个人资料属于正确的人。
- 切勿重复使用同一条开场白 — 根据每位候选人做过的具体工作,为其撰写独特的开场白。
- 切勿联系活跃的创始人 — 跳过现任创始人/联合创始人/CEO/CTO,除非其公司明显走向失败(员工人数下降、流量下降,且员工离职速度超过公司可承受的程度)。参见上文“创始人排除规则”一节。