data-enrichment について
data-enrichmentは、HubSpot CLIで自然キーを基準にCRMレコードを作成・更新するスキルです。コンタクトや会社データの整形、安全なプレビュー、レコードごとの結果処理を扱います。
主な機能
- 01キーによるコンタクト・会社のUpsert
- 02jqによるCSV・JSONL変換
- 03dry-runとdigestで書き込みを確認
- 04成功・失敗レコードの分離
- 05修正後の失敗行の再試行
活用シーン
- 01メールアドレスをキーにしたコンタクトの取り込み
- 02ドメインをキーにした会社情報の補完
- 03バッチ失敗行の確認と再試行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ hubspot/ agent-cli-skills --skill data-enrichmentインストール後、Claude Code で/data-enrichmentを入力して読み込まれたか確認します。
詳細
前提: まず bulk-operations/SKILL.md を読んでください — JSONL のパイプ処理、ドライラン/ダイジェスト、履歴、レート制限の衛生管理はそこに書かれています。このスキルは、その上に成り立つ自然キーによる upsert ワークフローです。
核心となる操作: 検索してから作成ではなく、upsert
hubspot objects upsert --type X --id-property <natural-key> は標準入力で JSONL を読み取り、1 回の CLI 呼び出しで各行を作成または更新します(CLI は API リクエストごとに 100 行をバッチ処理します)。キーとなるのはプロパティです(連絡先なら email、企業なら domain)。競合の窓はなく、分岐もありません。search → 空? → create をループさせないでください。
入力の各行: {"id":"[email protected]","properties":{"firstname":"Jane","jobtitle":"VP"}}
出力の各行: {"id":"123","ok":true,"data":{...}} または {"ok":false,"error":{...}}。順序は入力と一致します。CLI は独自のフィールドを追加しません — data はバッチ upsert API の生の結果行です。
CSV/JSONL → upsert ストリーム
jq で整形し、--dry-run でプレビューしてから実行します。upsert は不可逆なので、実行ステップでは同じ入力を再パイプし、プレビュー行から --digest/--confirm を持ち上げます(upsert の confirm = 行数、常に)。自然キーは常に小文字にしてください — CRM のマッチは完全一致です。利用可能なプロパティ名は hubspot properties list --type contacts で確認してください。リストをハードコードしないでください。整形のイディオムについては bulk-operations/resources/json-patterns.md を参照してください。
# CSV → JSONL (any tool); example using csvkit
csvjson external.csv | jq -c '.[]' > external.jsonl
# Preview
cat external.jsonl \
| jq -c '{id:(.email|ascii_downcase), properties:{firstname:.first, lastname:.last, jobtitle:.title, company:.company}}' \
| hubspot objects upsert --type contacts --id-property email --dry-run \
| tee /tmp/upsert.preview.jsonl
# Lift the digest + confirm (present at every row count; upsert confirm = the row count)
digest=$(jq -r 'select(.digest != null) | .digest' /tmp/upsert.preview.jsonl)
confirm=$(jq -r 'select(.digest != null) | .target.id' /tmp/upsert.preview.jsonl)
# Execute — same pipeline, plus --digest/--confirm, capture results
cat external.jsonl \
| jq -c '{id:(.email|ascii_downcase), properties:{firstname:.first, lastname:.last, jobtitle:.title, company:.company}}' \
| hubspot objects upsert --type contacts --id-property email --digest "$digest" --confirm "$confirm" \
| tee /tmp/upsert.results.jsonl
企業の場合: --type companies --id-property domain に差し替え、.domain|ascii_downcase を id として整形します。
レコードごとの OK / エラー出力の扱い
jq で分割し、失敗モードを検査し、入力を修正した後に失敗分だけを再試行します:
jq -c 'select(.ok==true)' /tmp/upsert.results.jsonl > /tmp/upsert.ok.jsonl
jq -c 'select(.ok==false)' /tmp/upsert.results.jsonl > /tmp/upsert.failed.jsonl
jq -r '.error.status' /tmp/upsert.failed.jsonl | sort | uniq -c # status → count
CLI は行を作成済みか更新済みかにタグ付けしません。バッチ upsert API の結果行に new ブール値があれば、jq -r '.data.new' /tmp/upsert.ok.jsonl | sort | uniq -c でそれらを分けられます。なければ .data.createdAt と .data.updatedAt を比較してください。
429: 入力を分割してより小さなチャンクで再実行します(bulk-operations のレート制限の注意を参照)。400 は通常、不正なプロパティ名または無効な enum 値を意味します — 整形を修正し、失敗した入力を再実行してください。
破壊的操作の安全性
upsert 自体は非破壊的ですが、書き戻しによって既存のフィールドが上書きされる可能性があります。常に最初に --dry-run してスポットチェックしてください。既存データの一括削除や上書きについては、bulk-operations/SKILL.md のドライラン → ダイジェスト → 確認のフローに従ってください。復旧: hubspot history --since 1h。
upsert なしでマッチ: OR 検索 → 更新
マッチを読むだけの場合(書き戻しなし)、または自然キーが CRM プロパティでない場合は、繰り返しの --filter フラグを使用します — 各フラグが 1 つの OR グループです。
確認済みの上限: 1 呼び出しあたり 5 OR グループ。6 以上は 400 too many filterGroups (count: N, max allowed: 5) を返します。一度に 5 つずつチャンク化します:
# emails.txt: one lowercased email per line
xargs -n5 < emails.txt | while read -r e1 e2 e3 e4 e5; do
args=()
for e in "$e1" "$e2" "$e3" "$e4" "$e5"; do [ -n "$e" ] && args+=(--filter "email=$e"); done
hubspot objects search --type contacts "${args[@]}" --properties email,firstname,company
done > /tmp/matches.jsonl
jq -c '{id, properties:{lifecyclestage:"marketingqualifiedlead"}}' /tmp/matches.jsonl \
| hubspot objects update --type contacts --dry-run
より大規模なキー付きエンリッチメントには、upsert を優先してください — 1 つのパイプラインで、チャンク化の計算は不要です。