Sales Execution

hubspot/agent-cli-skills/sales-execution

作者 hubspota8eea0880838无许可证27 个星标收录于 2026年10月8日更新于 2026年10月8日仓库7天前更新

Log sales activities — calls, notes, meetings, tasks — against contacts and deals, with the mandatory create-then-associate step that makes them visible in the CRM.

仅含说明Marketing & Sales
AI 生成的概览

将 HubSpot 销售活动(通话、备注、会议、任务)记录到联系人和交易上,并包含必需的关联步骤。

功能
提供通过 hubspot 命令行创建 HubSpot 通话、备注、会议和任务记录的命令模式,并将每条新记录关联到相应的联系人或交易,使其在 CRM 中可见。还涵盖查询某联系人及全门户的未完成任务、按任务状态过滤,以及为某阶段的每笔交易批量创建跟进任务。文档说明了时间戳格式、枚举值查询方式和 API 过滤条件上限。
适用场景
适用于需要把销售活动录入 HubSpot 的场景:记录通话、备注或会议,创建跟进任务,或为多笔交易批量生成跟进任务。也适用于按负责人或联系人查询未完成任务。
运行要求
需要可访问 HubSpot CRM 的 hubspot 命令行工具、jq,以及带 date 和 paste 工具的 shell;需要 HubSpot 凭据和网络访问。该技能不附带脚本,只有说明文档和一个属性参考文件,并假定已具备 bulk-operations 技能的批处理与试运行模式。

Resources

FileWhen to use
resources/activity-properties-reference.mdProperty names and enum values for calls/notes/meetings/tasks. Keep open while writing objects create — for live enum values run hubspot properties options-list --type calls <property>, and for call outcomes hubspot activities calls dispositions list; the reference is the shortcut.

Read bulk-operations/SKILL.md first — this skill assumes its batching, pipe, and dry-run patterns.

The two non-obvious rules

1. Activities are invisible until associated. hubspot objects create --type calls ... alone produces a record nobody can see in the CRM UI. Always follow with hubspot associations create --from calls:<id> --to contacts:<id> (and the deal, if relevant) before stopping.

2. Timestamps differ between write and read.

PathFieldFormat
objects create --property hs_timestamp=...hs_timestampUnix ms (13 digits)
objects get --type calls <id> returnsproperties.hs_timestampUnix ms (string)
activities list --contact <id> returnstimestamp (flat, top-level)ISO 8601 (e.g. 2024-01-15T10:00:00Z)

Current Unix ms: $(date +%s)000 (macOS) or $(date +%s%3N) (Linux). activities list rows are {"id","type","timestamp","lastModified","title","body","status","owner_id"} — the cross-type timeline read shape, no raw property names.

Create + associate, by type

bash
# CALLcall_id=$(hubspot objects create --type calls \  --property hs_call_title="Discovery call" \  --property hs_call_body="Confirmed $50K budget, Q2 timeline." \  --property hs_call_direction=OUTBOUND \  --property hs_call_status=COMPLETED \  --property hs_call_duration=1800000 \  --property hs_timestamp=$(date +%s)000 \  --format json | jq -r '.id')hubspot associations create --from calls:$call_id --to contacts:149hubspot associations create --from calls:$call_id --to deals:456
# NOTEnote_id=$(hubspot objects create --type notes \  --property hs_note_body="Sent proposal. Follow-up Friday." \  --property hs_timestamp=$(date +%s)000 \  --format json | jq -r '.id')hubspot associations create --from notes:$note_id --to deals:456
# MEETING — start/end in Unix ms; reuse start as hs_timestampstart=$(date +%s)000; end=$(( ${start%000} + 3600 ))000meeting_id=$(hubspot objects create --type meetings \  --property hs_meeting_title="Demo — Acme" --property hs_meeting_outcome=COMPLETED \  --property hs_meeting_start_time=$start --property hs_meeting_end_time=$end \  --property hs_timestamp=$start --format json | jq -r '.id')hubspot associations create --from meetings:$meeting_id --to contacts:149
# TASK — hs_timestamp is the DUE DATE, not creation timedue=$(( $(date -v+7d +%s) * 1000 ))   # macOS; Linux: date -d '7 days' +%stask_id=$(hubspot objects create --type tasks \  --property hs_task_subject="Confirm proposal received" \  --property hs_task_priority=HIGH \  --property hs_task_status=NOT_STARTED \  --property hs_task_type=CALL \  --property hs_timestamp=$due \  --format json | jq -r '.id')hubspot associations create --from tasks:$task_id --to deals:456

Open tasks for a contact — two CLI calls, no xargs

associations list emits {"id": …} per row (plus label/associationType fields); objects get reads from stdin in one batch call (see bulk-operations/SKILL.md "Read in batch").

bash
hubspot associations list --from contacts:149 --to tasks \| hubspot objects get --type tasks \    --properties hs_task_subject,hs_task_status,hs_task_priority,hs_timestamp \| jq -c 'select(.properties.hs_task_status != "COMPLETED")'

Open tasks portal-wide — exclude statuses server-side with @!=

@!= is NOT_IN: one condition for the whole excluded list. Do not spend one --filter flag per excluded status — the search API caps a request at 5 filter groups, 6 conditions per group, and 18 conditions total.

@!= matches only records that have the property, so replicating a real HubSpot task view's "status is none of … or is empty" needs two groups (OR'd), with the shared conditions repeated in each:

bash
hubspot objects search --type tasks \  --filter "hubspot_owner_id=123 AND hs_task_status@!=COMPLETED,DEFERRED" \  --filter "hubspot_owner_id=123 AND !hs_task_status" \  --properties hs_task_subject,hs_task_status,hs_task_priority,hs_timestamp

Inverse (only these statuses) is @= (IN): --filter "hs_task_status@=NOT_STARTED,IN_PROGRESS,WAITING".

Bulk: follow-up task per deal in a stage

The deal ID and the task ID must travel together. Persist the deal payload to a file, create tasks (output order matches input order — see bulk-operations), then zip the two ID lists line-by-line and stream association pairs in one call.

bash
due=$(( $(date -v+7d +%s) * 1000 ))
# 1. Per-deal payload, deal_id retained alongside the create payload.hubspot objects search --type deals --filter "dealstage=appointmentscheduled" \  --properties dealname \| jq -c --argjson due "$due" '{deal_id: .id, payload: {properties: {    hs_task_subject: ("Follow up: " + .properties.dealname),    hs_task_priority: "HIGH", hs_task_status: "NOT_STARTED", hs_task_type: "CALL",    hs_timestamp: ($due|tostring)  }}}' > /tmp/deal_tasks.jsonl
# 2. Create tasks; one CLI call for the whole batch.jq -c '.payload' /tmp/deal_tasks.jsonl \| hubspot objects create --type tasks > /tmp/created_tasks.jsonl
# 3. Zip and stream association pairs through stdin.paste \  <(jq -r '.deal_id' /tmp/deal_tasks.jsonl) \  <(jq -r '.id'      /tmp/created_tasks.jsonl) \| jq -Rc 'split("\t") | {from:("tasks:"+.[1]), to:("deals:"+.[0])}' \| hubspot associations create

These are objects create calls (Additive) — creates are never digest-gated, so --dry-run is a plain preview and you execute by dropping it (no digest/confirm). The digest flow only applies to the irreversible writes (update/upsert/delete/merge) in bulk-operations/SKILL.md.

Known constraints

Activities must be associated immediately or they're invisible in the CRM UI. For enum option values on activity properties, run hubspot properties options-list --type calls <property> (and for call outcomes, hubspot activities calls dispositions list); the reference is the shortcut. Sales Hub sequences are read-only in the CLI (hubspot sequences list / get / enrollments, automation.sequences.read scope) — the CLI cannot enroll a contact in a sequence, so drive outreach via tasks/activities above. This surface grows; recheck hubspot --help / CHANGELOG.md before assuming an API is missing.

来源与署名

来源:hubspot/agent-cli-skills位于sales-execution提交a8eea08

许可证: 无许可证

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架