mcpField
D
deal-management

deal-management

github.com/hubspot营销与增长281.7k 次安装今天更新
代码仓库

关于 deal-management

这套技能指导 CRM 操作人员使用 HubSpot CLI 管理交易管道、将 MQL 转为交易、批量更新阶段、查找停滞交易和关闭记录,并提供预览与确认流程。

主要功能

  1. 01发现门户专属的管道与阶段
  2. 02将 MQL 联系人转为交易
  3. 03批量推进或重新分配交易
  4. 04查找并更新停滞交易
  5. 05通过保护流程关闭交易

适用场景

  1. 01筛选尚无交易的已连接 MQL
  2. 02批量将交易移至另一阶段
  3. 03查找近期无活动的未关闭交易
  4. 04设置关闭日期并关闭交易

安装

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

$npx skills add https://github.com/hubspot/agent-cli-skills --skill deal-management

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

附带文件resources/lifecycle-stage-progression.mdresources/stalled-deal-queries.md

详细介绍

资源

文件使用场景
resources/lifecycle-stage-progression.md生命周期阶段 API 值,以及与交易阶段变更配套的联系人侧更新。
resources/stalled-deal-queries.md用于筛选停滞、无活动或已过预计成交日期的交易的查询指南,支持动态日期。

基础知识

先阅读 bulk-operations/SKILL.md——其中介绍了 JSONL 管道传递、批量读取、分页,以及 dry-run/digest/confirm 流程。数据重塑示例见 bulk-operations/resources/json-patterns.md。hubspot <command> --help 是权威信息来源。对象类型使用复数形式(contacts、deals、companies)。查询属性参考:hubspot properties list --type deals——不要硬编码属性表。

1. 发现管道和阶段

管道和阶段 ID 因门户而异。务必在运行时查询,切勿跨门户硬编码。

hubspot pipelines list --type deals --format jsonl
# {"id":"default","label":"Sales Pipeline","displayOrder":0,"stages":[...]}
# {"id":"a1b2c3d4-0000-0000-0000-000000000000","label":"Enterprise Pipeline","displayOrder":1,"stages":[...]}

hubspot pipelines stages --type deals --pipeline default --format jsonl
# {"id":"appointmentscheduled","label":"Appointment Scheduled","displayOrder":0,"metadata":{"isClosed":"false","probability":"0.2"}}
# {"id":"qualifiedtobuy","label":"Qualified To Buy","displayOrder":1,"metadata":{"isClosed":"false","probability":"0.4"}}
# ...
# {"id":"closedwon","label":"Closed Won","displayOrder":5,"metadata":{"isClosed":"true","probability":"1.0"}}
# {"id":"closedlost","label":"Closed Lost","displayOrder":6,"metadata":{"isClosed":"true","probability":"0.0"}}

pipelines list/get 会嵌入每个管道的 stages,因此只需调用一次,就能获取将交易的 dealstage GUID 转换为阶段 ID -> 标签所需的映射:

hubspot pipelines get --type deals default --format jsonl \
  | jq -r '.stages[] | "\(.id)\t\(.label)"'

按标签获取特定阶段 ID:

QUALIFIED=$(hubspot pipelines stages --type deals --pipeline default --format jsonl \
  | jq -r 'select(.label=="Qualified To Buy") | .id')

上面显示的 ID(appointmentscheduled、closedwon 等)是 HubSpot 标准 default 交易管道阶段,但每次运行都要查询实际阶段,因为门户可能会重命名或移除阶段。

2. 将 MQL 转化为交易

查找已关联但尚无交易的 MQL,然后为每个 MQL 创建交易、关联联系人和公司,并提升生命周期阶段。

# 1. find ready MQLs
hubspot objects search --type contacts \
  --filter "lifecyclestage=marketingqualifiedlead AND hs_lead_status=CONNECTED AND num_associated_deals=0" \
  --properties email,firstname,lastname,company,hubspot_owner_id

# 2. for one contact: company lookup, deal create, associate, promote
hubspot associations list --from contacts:<contact_id> --to companies   # → <company_id>

hubspot objects create --type deals \
  --property "dealname=Acme Corp - Inbound" \
  --property pipeline=default --property dealstage=qualifiedtobuy \
  --property amount=0 --property hubspot_owner_id=<owner_id>
# returns {"id":"<deal_id>","ok":true,...}

hubspot associations create --from deals:<deal_id> --to contacts:<contact_id>
hubspot associations create --from deals:<deal_id> --to companies:<company_id>

# lifecycle promote — objects update is irreversible, so dry-run then confirm with the contact ID
hubspot objects update --type contacts <contact_id> \
  --property lifecyclestage=salesqualifiedlead --property hs_lead_status=OPEN_DEAL --dry-run
hubspot objects update --type contacts <contact_id> \
  --property lifecyclestage=salesqualifiedlead --property hs_lead_status=OPEN_DEAL \
  --digest <hash> --confirm <contact_id>
批量处理模式 — 一次处理多个 MQL

objects create 会按输入顺序为 stdin 中的每一行返回一行结果。捕获两个流,并按行合并结果以建立关联:

# 1. snapshot MQLs to a file (preserves order for the join)
hubspot objects search --type contacts \
  --filter "lifecyclestage=marketingqualifiedlead AND hs_lead_status=CONNECTED AND num_associated_deals=0" \
  --properties email,firstname,lastname,company,hubspot_owner_id \
  > /tmp/mqls.jsonl

# 2. one deal per MQL — output preserves order
jq -c '{properties:{
    dealname: ((.properties.firstname // "") + " " + (.properties.lastname // "") + " - " + (.properties.company // "Unknown")),
    pipeline:"default", dealstage:"qualifiedtobuy", amount:"0", dealtype:"newbusiness",
    hubspot_owner_id:(.properties.hubspot_owner_id // "")
  }}' /tmp/mqls.jsonl \
| hubspot objects create --type deals > /tmp/deals.jsonl

# 3. abort if any create failed — paste would zip null deal IDs onto real contacts
jq -e 'select(.ok==false)' /tmp/deals.jsonl > /dev/null && { echo "Some deal creates failed — inspect /tmp/deals.jsonl" >&2; exit 1; }

# 4. pair contact <-> new deal by line for the association call
paste <(jq -r '.id' /tmp/mqls.jsonl) <(jq -r '.id' /tmp/deals.jsonl) \
| jq -cR 'split("\t") | {from:("deals:" + .[1]), to:("contacts:" + .[0])}' \
| hubspot associations create

# 5. promote lifecycle on every contact — objects update is irreversible, so dry-run then re-pipe with the digest/confirm
jq -c '{id, properties:{lifecyclestage:"salesqualifiedlead", hs_lead_status:"OPEN_DEAL"}}' /tmp/mqls.jsonl \
| hubspot objects update --type contacts --dry-run \
| tee /tmp/promote.preview.jsonl

digest=$(jq -r 'select(.digest != null) | .digest' /tmp/promote.preview.jsonl)
confirm=$(jq -r 'select(.digest != null) | .target.id' /tmp/promote.preview.jsonl)   # batch: row count

jq -c '{id, properties:{lifecyclestage:"salesqualifiedlead", hs_lead_status:"OPEN_DEAL"}}' /tmp/mqls.jsonl \
| hubspot objects update --type contacts --digest "$digest" --confirm "$confirm"

公司关联需要针对每个联系人单独执行:hubspot associations list --from contacts:<id> --to companies——一个联系人可能关联零个或多个公司。

资格预审检查只需在搜索中设置筛选条件:有邮箱、有公司、没有未结交易、有负责人——都已包含在 --filter 中。完整的阶段推进流程和联系人侧更新请参阅 resources/lifecycle-stage-progression.md。

3. 批量推进或重新分配

# move every deal in one stage to the next — 1. preview
hubspot objects search --type deals --filter "dealstage=qualifiedtobuy" \
| jq -c '{id, properties:{dealstage:"presentationscheduled"}}' \
| hubspot objects update --type deals --dry-run \
| tee /tmp/advance.preview.jsonl

# 2. lift the digest + confirm (present at every size)
digest=$(jq -r 'select(.digest != null) | .digest' /tmp/advance.preview.jsonl)
confirm=$(jq -r 'select(.digest != null) | .target.id' /tmp/advance.preview.jsonl)   # batch: row count; single: record ID

# 3. execute — re-pipe the SAME inputs plus --digest/--confirm
hubspot objects search --type deals --filter "dealstage=qualifiedtobuy" \
| jq -c '{id, properties:{dealstage:"presentationscheduled"}}' \
| hubspot objects update --type deals --digest "$digest" --confirm "$confirm"

# reassign open deals from one rep to another — same three steps
OLD=$(hubspot owners list --format jsonl | jq -r 'select(.email=="[email protected]") | .id')
NEW=$(hubspot owners list --format jsonl | jq -r 'select(.email=="[email protected]") | .id')
hubspot objects search --type deals --filter "hubspot_owner_id=$OLD AND hs_is_closed!=true" \
| jq -c "{id, properties:{hubspot_owner_id:\"$NEW\"}}" \
| hubspot objects update --type deals --dry-run \
| tee /tmp/deal-reassign.preview.jsonl
digest=$(jq -r 'select(.digest != null) | .digest' /tmp/deal-reassign.preview.jsonl)
confirm=$(jq -r 'select(.digest != null) | .target.id' /tmp/deal-reassign.preview.jsonl)
hubspot objects search --type deals --filter "hubspot_owner_id=$OLD AND hs_is_closed!=true" \
| jq -c "{id, properties:{hubspot_owner_id:\"$NEW\"}}" \
| hubspot objects update --type deals --digest "$digest" --confirm "$confirm"

无论处理多少条记录,dry-run 都会生成摘要(confirm = 批次的行数;单条记录则为记录 ID);从预览行中获取相应值,再通过 --digest <hash> --confirm <value> 重新传递管道。完整流程见 bulk-operations/SKILL.md。

4. 查找停滞的交易

带动态日期的筛选查询指南见 resources/stalled-deal-queries.md。核心查询:

# open deals with no activity in 30 days (macOS / Linux date examples in resources)
hubspot objects search --type deals \
  --filter "hs_last_activity_date<$(date -v-30d +%Y-%m-%d) AND hs_is_closed!=true" \
  --properties dealname,dealstage,closedate,hubspot_owner_id,hs_last_activity_date

将结果通过管道传递给更新操作(延长成交日期、变更阶段、设置标记)或任务创建操作。针对停滞交易创建跟进任务、通话或备注,请参阅 sales-execution 技能——此处不重复介绍活动对象属性的处理方法。

# extend close dates for everything past due
hubspot objects search --type deals \
  --filter "closedate<$(date +%Y-%m-%d) AND hs_is_closed!=true" \
| jq -c '{id, properties:{closedate:"2026-06-30"}}' \
| hubspot objects update --type deals --dry-run

5. 关闭交易

关闭交易需要更新阶段并设置 closedate(YYYY-MM-DD)。hs_is_closed 和 hs_is_closed_won 为只读属性——HubSpot 会根据阶段自动推导它们。

# single — objects update is irreversible, so dry-run then confirm with the deal ID
hubspot objects update --type deals <deal_id> \
  --property dealstage=closedwon --property closedate=2026-05-15 --dry-run
hubspot objects update --type deals <deal_id> \
  --property dealstage=closedwon --property closedate=2026-05-15 --digest <hash> --confirm <deal_id>

# bulk — preview first, then re-pipe with the digest/confirm from the preview (confirm = row count)
hubspot objects search --type deals --filter "dealstage=contractsent AND hubspot_owner_id=<owner_id>" \
| jq -c '{id, properties:{dealstage:"closedwon", closedate:"2026-05-15"}}' \
| hubspot objects update --type deals --dry-run \
| tee /tmp/close.preview.jsonl

digest=$(jq -r 'select(.digest != null) | .digest' /tmp/close.preview.jsonl)
confirm=$(jq -r 'select(.digest != null) | .target.id' /tmp/close.preview.jsonl)

hubspot objects search --type deals --filter "dealstage=contractsent AND hubspot_owner_id=<owner_id>" \
| jq -c '{id, properties:{dealstage:"closedwon", closedate:"2026-05-15"}}' \
| hubspot objects update --type deals --digest "$digest" --confirm "$confirm"

有关赢单/输单分析(关闭原因、赢单率、ARR 汇总),请参阅 sales-reporting 技能。

已知限制

  • 批量将 MQL 转化为交易需要两遍的 shell 流程:关联必须根据 objects create 的输出构建,不能在同一个管道中完成。
  • 在大多数门户设置中,lifecyclestage 只能向前推进——向后转换可能会被拒绝。
  • closedate 是日期字符串(YYYY-MM-DD)。日期时间活动属性(hs_last_activity_date)在进行 </> 比较时也接受日期字符串。
  • hubspot sequences 可以读取 Sales Hub 序列(list / get / enrollments),但为只读操作——CLI 无法将联系人加入序列,因此请改用 sales-execution 创建跟进任务。sequences enrollments <contact_id> 可用于了解交易相关联系人的赢单/输单背景。

评论

支持 Markdown