关于 deal-management
这套技能指导 CRM 操作人员使用 HubSpot CLI 管理交易管道、将 MQL 转为交易、批量更新阶段、查找停滞交易和关闭记录,并提供预览与确认流程。
主要功能
- 01发现门户专属的管道与阶段
- 02将 MQL 联系人转为交易
- 03批量推进或重新分配交易
- 04查找并更新停滞交易
- 05通过保护流程关闭交易
适用场景
- 01筛选尚无交易的已连接 MQL
- 02批量将交易移至另一阶段
- 03查找近期无活动的未关闭交易
- 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>可用于了解交易相关联系人的赢单/输单背景。