conversation-history-brief について
conversation-history-briefは、HubSpot Conversationsの受信トレイのスレッドから顧客向けブリーフを作成するスキルです。CRMや営業の業務向けに、全ページの取得、チャネル種別の解決、履歴の要約方法を案内します。
主な機能
- 01受信トレイとチャネルの列挙
- 02コンタクトに関連するスレッドの検索
- 03全件取得のためのページ処理
- 04メッセージの取得と要約
- 05構造化された顧客ブリーフの生成
活用シーン
- 01通話前のコンタクトブリーフ作成
- 02コンタクトの受信トレイ履歴の確認
- 03受信トレイのスレッドとCRM活動履歴の統合
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ hubspot/ agent-cli-skills --skill conversation-history-briefインストール後、Claude Code で/conversation-history-briefを入力して読み込まれたか確認します。
詳細
hub-cli PR #251 の conversations コマンドグループが必要です。hubspot conversations --help が正式な情報源です。また、CRM のアクティビティ履歴(通話、メール、メモ)については communication-history/SKILL.md も参照してください。このスキルは Conversations 受信トレイの範囲のみを扱います。
スレッドがコンタクトにどのように関連付けられるか
conversations threads list は --associated-contact-id を受け付けます。さらに --inbox-id も指定する必要があります。受信トレイを知らなければ、ポータル全体のコンタクトスレッド検索は存在しません。すべての受信トレイをカバーするには、まずそれらを列挙し(ステップ 1)、その後で受信トレイごとにクエリを実行します。
ページング: --format jsonl で結果セット全体を収集しないこと
すべての conversations の list コマンドはデフォルトで --limit 100 となり、次のページ用のカーソルを返します。--format jsonl はデータ行のみを出力します — カーソルは --format json でのみ、.meta.next に現れます。 したがって、--format jsonl をファイルにパイプすると、最初の 100 行で暗黙的に切り捨てられます。また、--limit を増やしても修正にはなりません。エンドポイントがページサイズに上限を設けているためです。
すべての行を確認する必要があるものには、このヘルパーを使用してください:
# conv_page <output-file> <conversations list args...>
# Pages a conversations list endpoint to exhaustion, writing one JSON object
# per line to <output-file>.
conv_page() {
out=$1; shift
after=""
: > "$out"
while :; do
if [ -n "$after" ]; then
page=$(hubspot "$@" --format json --after "$after") || return 1
else
page=$(hubspot "$@" --format json) || return 1
fi
printf '%s' "$page" | jq -c '.data[]' >> "$out"
after=$(printf '%s' "$page" | jq -r '.meta.next // empty')
[ -n "$after" ] || break
done
}
最初のページを対話的にざっと見るだけなら、素の --format jsonl でも問題ありません。
1. 受信トレイを列挙する
conv_page /tmp/inboxes.jsonl conversations inboxes list
# {"id":"123","name":"Support Inbox","createdAt":"...","updatedAt":"..."}
# {"id":"124","name":"Sales Chat","createdAt":"...","updatedAt":"..."}
2. コンタクトのすべてのスレッドを検索する
受信トレイ ID をループし、コンタクトに関連付けられたスレッドを収集します:
CONTACT_ID=73235
: > /tmp/contact_threads.jsonl # truncate output file
while IFS= read -r inbox; do
inbox_id=$(echo "$inbox" | jq -r '.id')
conv_page /tmp/inbox_threads.jsonl conversations threads list \
--inbox-id "$inbox_id" \
--associated-contact-id "$CONTACT_ID"
cat /tmp/inbox_threads.jsonl >> /tmp/contact_threads.jsonl
done < /tmp/inboxes.jsonl
echo "Total threads found: $(wc -l < /tmp/contact_threads.jsonl)"
スレッドの出力形状:
{"id":"111","status":"OPEN","createdAt":"2026-07-28T10:02:00Z","latestMessageTimestamp":"2026-07-30T14:22:00Z","assignedTo":"A-78901","inboxId":"123","originalChannelId":"1000","originalChannelAccountId":"148662","associatedContactId":"73235","spam":false,"archived":false}
スレッドには存在しないと想定しがちな 2 つのフィールドがあります:
channelTypeはありません。 スレッドは発信元チャネルをoriginalChannelIdに ID のみで記載します。conversations channels listと結合して人間が読めるタイプに解決してください。これは{"id":"1000","name":"Support Email","type":"EMAIL","inboxId":"123"}を返します(以下のステップ 3)。subjectは保証されません。 信頼できるフィールドはstatus(OPEN/CLOSED)、タイムスタンプ、assignedTo、およびチャネル ID です。subject は常に// "(no subject)"のフォールバックを経由して読み取ってください。
3. チャネル ID をチャネルタイプに解決する
: > /tmp/channels.jsonl
while IFS= read -r inbox; do
inbox_id=$(echo "$inbox" | jq -r '.id')
conv_page /tmp/inbox_channels.jsonl conversations channels list --inbox-id "$inbox_id"
cat /tmp/inbox_channels.jsonl >> /tmp/channels.jsonl
done < /tmp/inboxes.jsonl
# {"1000":"EMAIL","1001":"LIVE_CHAT"}
jq -s 'map({key: (.id|tostring), value: .type}) | from_entries' \
/tmp/channels.jsonl > /tmp/channel_types.json
以下のステップでスレッドにラベルを付けるために使用するヘルパー:
CHANNEL_TYPES=$(cat /tmp/channel_types.json)
4. 各スレッドのメッセージを取得する
messages list は他のすべての list エンドポイントと同様にページングするため、最初の 100 件を取得するのではなくページングしてください:
: > /tmp/all_messages.jsonl
while IFS= read -r thread; do
tid=$(echo "$thread" | jq -r '.id')
conv_page /tmp/thread_messages.jsonl conversations messages list --thread-id "$tid"
jq -c --argjson thread "$thread" --argjson types "$CHANNEL_TYPES" \
'. + {
_threadId: $thread.id,
_subject: ($thread.subject // "(no subject)"),
_channelType: ($types[($thread.originalChannelId | tostring)] // "UNKNOWN")
}' /tmp/thread_messages.jsonl \
>> /tmp/all_messages.jsonl
done < /tmp/contact_threads.jsonl
メッセージの出力形状:
{"id":"222","type":"MESSAGE","text":"Hello, I have a billing question.","sender":{"actorId":"A-456","name":"Jane Doe"},"createdAt":"2026-07-30T14:20:00Z"}
単一のメッセージを完全な詳細で取得するには:
hubspot conversations messages get --thread-id 111 --message-id 222 --format jsonl
5. アカウントブリーフ用のコンパクトなタイムライン
最新のアクティビティ順に並べた、人間が読めるスレッドサマリーを生成します。-s に注意してください: ファイルは JSONL であるため、slurp しないと sort_by に一度に 1 つのオブジェクトが渡され、タイムラインを出力する代わりに jq が Cannot index string with string で終了コード 5 で終了します。
echo "=== Conversation History for Contact $CONTACT_ID ==="
jq -sr --argjson types "$CHANNEL_TYPES" \
'sort_by(.latestMessageTimestamp) | reverse[] |
"\(.latestMessageTimestamp[0:10]) \($types[(.originalChannelId | tostring)] // "?") [\(.status)] \(.subject // "(no subject)")"' \
/tmp/contact_threads.jsonl
主要なメッセージの抜粋(スレッドごとの最初のメッセージ):
echo ""
echo "=== First message per thread ==="
while IFS= read -r thread; do
tid=$(echo "$thread" | jq -r '.id')
subject=$(echo "$thread" | jq -r '.subject // "(no subject)"')
first_msg=$(hubspot conversations messages list --thread-id "$tid" --limit 1 --format jsonl \
| jq -r '.text // .richText // "(no text)" | .[0:200]')
echo "[$tid] $subject: $first_msg"
done < /tmp/contact_threads.jsonl
6. 構造化されたアカウントブリーフのセクション
より大きなアカウントブリーフに埋め込むのに適した JSON ブロックを出力します:
jq -n \
--argjson threads "$(jq -s '.' /tmp/contact_threads.jsonl)" \
--argjson types "$CHANNEL_TYPES" \
--arg contact_id "$CONTACT_ID" \
'{
conversations: {
contact_id: $contact_id,
total_threads: ($threads | length),
open_threads: ($threads | map(select(.status=="OPEN")) | length),
channels: ($threads | map($types[(.originalChannelId | tostring)] // "UNKNOWN") | unique),
latest_activity: ($threads | sort_by(.latestMessageTimestamp) | last | .latestMessageTimestamp),
threads: ($threads | map({
id: .id,
subject: (.subject // "(no subject)"),
status: .status,
channel: ($types[(.originalChannelId | tostring)] // "UNKNOWN"),
last_activity: .latestMessageTimestamp,
assigned_to: (.assignedTo // null)
}))
}
}'
CRM アクティビティ履歴との組み合わせ
通話前の完全なブリーフを作成するには、このスキルを communication-history/SKILL.md と組み合わせてください:
CONTACT_ID=73235
echo "=== CRM Activity (calls, emails, notes) ==="
hubspot activities list --contact $CONTACT_ID --limit 10 \
| jq -r '"\(.timestamp[0:10]) \(.type) \(.title)"'
echo ""
echo "=== Conversations Inbox Threads ==="
# ... run the thread loop from step 2 above ...
既知の制約
threads listには--inbox-idが必要です — 全体像を把握するにはすべての受信トレイをループする必要があります。- 日付範囲のサーバーサイドフィルターはありません —
latestMessageTimestampを使用してjqでクライアントサイドでフィルタリングしてください。 - すべての
listコマンドは 100 行でページングし、カーソル(.meta.next)を公開するのは--format jsonのみです。完全である必要があるものにはconv_pageを使用してください。素の--format jsonlのリダイレクトは暗黙的に切り捨てられます。 - スレッドは
channelTypeを持ちません —originalChannelIdをconversations channels listと結合してタイプを取得してください。スレッドは会話の途中でチャネルを切り替えることもあるため、originalChannelIdはスレッドが開始した場所を表すのであり、使用したすべてのチャネルを表すわけではありません。 subjectはスレッドの保証されたフィールドではありません。常に// "(no subject)"のフォールバックを使用してください。textとrichText: 一部のメッセージタイプはtextではなくrichTextにフォーマットされたコンテンツを含みます。抜粋を抽出する際は両方のフィールドを確認してください。