heb-mcp.skill (TikTok-2-HEB) エージェントスキル
H-E-B のライブカートを管理し、購入履歴から優先家庭用品を解決し、クーポンを適用し、調理動画のURLをスケーリング済み・パントリー確認済みのH-E-B買い物カゴに変換します(在庫切れの場合は決定論的な代替品を提示)。
🎯 起動条件
以下の場合にこのスキルを有効化します:
- ユーザーが H-E-B の検索、カート確認、優先店舗や受け取り方法(Curbside/Delivery)の切り替え、クーポン適用、H-E-B カートへの商品追加・削除を依頼した場合(例:「カートに牛乳とバタートルティーヤを追加して」)。
- 認証済みユーザーが TikTok(
tiktok.com,vm.tiktok.com)、Instagram Reels(instagram.com/reel/)、YouTube Shorts(youtube.com/shorts/)の調理・レシピURLを共有した場合。 - ユーザーがレシピ動画の食材を変換、スケーリング、注文するよう依頼した場合(例:「このレシピの材料をH-E-Bで注文して」、「このTikTokの夕食をカートに入れて」)。
- ユーザーが既存の食料品レビュースレッドに返信し、カート準備後の調整(例:「醤油を追加」、「通常のサーモンを野生紅鮭に変更」、「その変更を永続化」)を依頼した場合。
- ユーザーが
heb-mcp.skill(TikTok-2-HEB)の初回設定を依頼した場合。
🚀 初回セットアップ(エージェント駆動のオンボーディング)
ユーザーがこのプロジェクトのセットアップを依頼した場合、技術的な手順を代行し、簡潔な平易な質問のみを行います:
- 環境とバイナリのインストール:
uv venv --python 3.11 .venv && source .venv/bin/activate && uv pip install -r requirements.txt playwright install chromium cp -n .env.example .env cp -n config/household.example.yaml config/household.yaml cp -n config/pantry_staples.example.json config/pantry_staples.json - ユーザーに簡単な設定質問:
- 優先H-E-B店舗と受け取り方法: どのH-E-B店舗を利用するか尋ねます(
.envのHEB_STORE_IDとconfig/household.yamlのstoreを検索・更新し、必要に応じてアクティブな店舗の切り替えやCurbside Pickup/Home Deliveryの切り替えを支援します)。 - 世帯人数: 何人の大人/子供のために料理をするか尋ねます(
config/household.yamlを更新)。
- 優先H-E-B店舗と受け取り方法: どのH-E-B店舗を利用するか尋ねます(
- セッション収穫と過去注文の同期: ユーザーにSafariまたはChromeで
heb.comにログインしていることを確認してもらい、以下を実行:python scripts/heb_client.py --harvest python scripts/cache_manager.py update-preferred-skus python tests/test_skill_setup.py - 自動デイリートークン更新cronjobの設定: ユーザーに24時間ごとのcronjob(
0 9 * * * cd <REPO_PATH> && .venv/bin/python scripts/heb_client.py --harvest >/dev/null 2>&1)のインストールを強く推奨し、H-E-Bセッションが自動的に維持されるようにします。
🔒 運用上の不変条件と安全ガードレール
- ハードなヒューマンインザループチェックアウトゲート:
- エージェントはカートに商品を追加し、デジタルクーポンを適用します。
- エージェントは決して支払い、配送/受け取り枠の予約、注文の最終確定を行ってはなりません。
- 最終確認とチェックアウトの実行は、常に公式 My H-E-B モバイルアプリ内でユーザーが行います。
- ゼロ認証抽出:
- 常に
scripts/extract_recipe_media.pyを個人のTikTok/Instagramログインやセッションクッキーを必要とせずに呼び出します。
- 常に
- キャッシュポイズニング防止不変条件:
- 在庫切れ代替品(Tier 2/3/4)は、その特定のカート注文に対してのみ厳密に一時的に使用します。
- ユーザーが明示的に「その変更を永続化」または「今後はこのブランドを使って」と指示しない限り、
cache/recipes/<slug>.yamlのprimary_skuを決して上書きしないでください。
- 子ども向け調理分割:
kid_friendly_splitが有効な場合、カプサイシン/辛味成分(シラチャ、チリフレーク、カイエン、ハラペーニョ)をベースの調理鍋から分離します。メインの鍋はマイルドに保ち、最初に子供の取り分を皿に取り、大人の取り分には最後に辛味を加えます。- タンパク質や窒息リスクのある食材は1/2インチの一口大に切るようリマインダーを追加します。
- 自動トークン更新(デイリーcronjob推奨):
- H-E-Bの短期セッションアクセストークン(
sat)は30分ごとにローテーションしますが、heb_graphql.pyが長期セッショントークン(sst)を使用してオンデマンドで自動的に更新します。 - 初期セットアップ時やセッションの収穫/更新後、ユーザーに自動24時間cronjobの設定を積極的に推奨し、H-E-Bセッションとアンチボットトークン(
reese84)をバックグラウンドで検証し続け、買い物のたびに手動ログインする必要がないようにします。
- H-E-Bの短期セッションアクセストークン(
🛠️ ステップバイステップ実行ワークフロー
ステップ 1: 事前キャッシュルックアップ
メディア抽出やAPI呼び出しの前に、動画が既に解析・キャッシュされているか確認:
python scripts/cache_manager.py lookup --query "<動画URL_または_ID>"
- HIT: キャッシュされたレシピYAMLを読み込み、ステップ 4(カート準備) に直接進み、キャッシュされた
primary_sku定義を使用します。 - MISS: ステップ 2(メディア抽出) に進みます。
ステップ 2: ゼロ認証マルチモーダルメディア抽出
3パス抽出パイプラインを実行:
python scripts/extract_recipe_media.py "<動画URL>"
- パス 1: 動画のタイトル、説明、アップローダー、自動字幕を取得。
- パス 2: 字幕キューをクリーンアップし、タイムスタンプを除去し、繰り返しのキャプションを重複排除。
- パス 3: トランスクリプトが少ない(料理測定トークンが3未満)場合、自動的にオーディオストリームまたはキーフレームを抽出。
ステップ 3: レシピ解析、世帯スケーリング、パントリー監査
- 世帯スケーリング: 材料の数量を元の出来上がり量(例:4人前)からターゲット量(デフォルトは大人2人+子供1人で
2.5)にHouseholdScalerを使用してスケーリング。 - パントリー重複排除:
config/pantry_staples.jsonの材料をPantryComparatorで確認。一致するアイテム(塩、コショウ、食用油、醤油、ガーリックパウダー)をpantry_staples_skippedに移動。 - 子供向け調理リマインダー: スパイシーな材料や丸ごとのタンパク質が検出された場合、子供向けの調整案を生成。
ステップ 4: H-E-B カタログマッチングと5段階フォールバックカスケード
ingredients_to_buy 内の各材料(またはアドホックなユーザーリクエスト)に対して、scripts/heb_client.py を使用してローカルのH-E-B店舗カタログとマッチング:
- Tier 0 (優先SKU解決とパッケージサイズスケーリング): 過去の注文や手動ピンから生成された
cache/preferred_skus.json(正規キーとエイリアス配列)とマッチング。整数パッケージ数量を自動計算(例:48オンスのレシピ量 / 32オンスパッケージ → 2パッケージ)。在庫がある場合、直接Tier 0としてカートに追加。在庫切れの場合、スムーズにTier 1にカスケード。 - Tier 1 (完全SKU一致): レシピのプライマリSKUが在庫にあれば追加。
- Tier 2 (ブランド階層): プライマリが在庫切れの場合、
brand_hierarchy(H-E-B→H-E-B Organics→Central Market→Mi Tienda→Hill Country Fare→National Brand)を使用して代替。 - Tier 3 (有機 ↔ 通常の交換): 店舗に一方のみ在庫がある場合、有機と通常を交換。
- Tier 4 (パッケージサイズ調整 / 人によるエスカレーション): 数量を調整するか、カテゴリ全滅を
⚠️ OUT OF STOCK (NEEDS HUMAN CALL)としてフラグ。
ステップ 5: ダイレクトGraphQLカート準備とクーポン適用(スローなUIクリック排除)
収穫されたChrome CDP(127.0.0.1:9222)/ rookiepy セッショントークンを使用し、認証済みGraphQL操作(texas-grocery-mcp からベンダリングされた永続クエリ cartEstimated、cartItemV2、CouponClip)を介してアイテムをカートに追加し、クーポンを適用:
# 1. ライブセッショントークンを収穫または更新
python scripts/heb_client.py --harvest
# 2. 過去の注文と「また買う」から優先SKUを同期
python scripts/cache_manager.py update-preferred-skus
# 3. お気に入り商品を優先SKUとして手動ピン(自動同期から保護)
python scripts/cache_manager.py pin-preferred-sku \
--ingredient "whole milk" \
--sku "4122012345" \
--product "123456" \
--name "H-E-B Organics Whole Milk" \
--package-size "1 gal"
# 4. アドホックな材料を解決、またはパッケージサイズをテスト
python scripts/heb_client.py --resolve-sku "48 oz beef broth"
# 5. 候補アイテムをカートに追加(ヒューマンインザループ確認が必要)
python scripts/heb_client.py --stage-sku "48 oz beef broth" --confirm
# または製品IDで直接:
python scripts/heb_client.py --cart-add <PRODUCT_ID> [--sku <SKU_ID>] [--qty <N>] --confirm
# 6. 現在のライブカートを確認
python scripts/heb_client.py --cart-get
# 7. 交換等でカートからアイテムを削除
python scripts/heb_client.py --cart-remove <PRODUCT_ID> [--sku <SKU_ID>] --confirm
# 8. デジタルクーポンを適用
python scripts/heb_client.py --coupon-clip <COUPON_ID> --confirm
[!IMPORTANT] ヒューマンインザループチェックアウトゲート: AGYは、チェックアウト、支払い、配送/受け取り枠の予約ミューテーションの実行を厳格に禁止されています。カートへの商品追加とデジタルクーポン適用のみ。Carl(ユーザー)が常にMy H-E-Bモバイルアプリで最終確認とチェックアウトを行います。
⏱️ 推奨バックグラウンドcronjob(デイリーセッション更新)
H-E-Bの短期 sat トークンは30分ごとにローテーションし、sst 経由でオンデマンド自動更新されますが、ユーザーに24時間ごとにセッションを更新・検証するデイリーcronjob(macOS/Linux)またはスケジュールタスク(Windows schtasks)を推奨します。crontab へのインストールを提案します:
0 9 * * * cd /path/to/heb-mcp.skill && .venv/bin/python scripts/heb_client.py --harvest >/dev/null 2>&1
(Slack通知が必要な場合は、scripts/cron_refresh_heb_auth.py / scripts/cron_refresh_heb_auth.sh を使用してください。)
ステップ 6: レシピキャッシュの永続化
解析済みレシピを永続化し、将来の実行で高速パスを使用可能に:
python scripts/cache_manager.py save --file <レシピデータYAML>
ステップ 7: モバイルレビューサマリー(iMessage / Slack)
モバイル画面で読みやすい形式でレビューをフォーマット(Markdownテーブルを避け、クリーンな絵文字箇条書きを使用):
🛒 H-E-B カート準備完了: クリスピーハニーガーリックサーモンバイト
大人2人 + 子供1人(約2.5人前)にスケーリング
👶 子供用調理メモ:
• メインの鍋のグレーズに大さじ1のシラチャを加えないでください。最初に子供の取り分を皿に取り、その後で大人の取り分にシラチャを混ぜてください。
• 子供のサーモンは1/2インチの一口大に切ってください。
✅ H-E-B カートに追加(4品目):
• 1x H-E-B 生アトランティックサーモンフィレ(約1.25ポンド) — ¥1,374
• 1x H-E-B ピュアクーローバーはちみつ(12オンス) — ¥448
• 1x フレッシュ青ネギ(1束) — ¥88
• 1x H-E-B ジャスミンライス(32オンス) — ¥274
🔄 自動代替(店舗在庫切れ):
• 2x H-E-B ブロッコリーフローレット(10オンス袋) — ¥456
(1ポンドの有機クラウンズが在庫切れのため、この注文に限り10オンス袋を2つに代替)
🎟️ 適用済みクーポン:
• H-E-B フレッシュシーフードトレイ $1.00オフ
🏠 パントリー在庫確認(スキップ — 返信で追加可能):
• 醤油(大さじ3)、ニンニク(4片)、コーンスターチ(大さじ2)、ごま油(小さじ1)
📱 次のステップ:
パントリーのアイテムを追加したい場合(例:「醤油を追加」)やブランドを変更したい場合は返信してください。準備ができたら、My H-E-Bアプリを開いて確認し、チェックアウトをタップしてください!
🔄 カート準備後の返信コマンド
ユーザーが準備済みレビュースレッドに返信した場合:
- 「[パントリーアイテム]を追加」(例:「醤油が切れたので追加して」):
- Tier-0優先SKUエンジンで解決し、カートに追加:
python scripts/heb_client.py --stage-sku "soy sauce" --confirm - 簡潔な返信で確認:「H-E-B減塩醤油1つをカートに追加しました。」
- Tier-0優先SKUエンジンで解決し、カートに追加:
- 「[アイテム]を[好み]に変更」(例:「通常のサーモンを野生紅鮭に変更」):
- 古いSKUをカートから削除し、優先SKUを追加。
- 確認:「野生紅鮭に変更しました。このレシピの将来の注文でもこの変更を永続化しますか?」
- 「その変更を永続化」:
python scripts/cache_manager.py promote-sku ...を実行し、cache/recipes/<slug>.yamlのprimary_skuを更新し、cache/preferred_skus.jsonにsource: "manual_override"としてピン留め。- 確認:「レシピキャッシュを更新しました:Central Market Wild Sockeye がこのレシピのプライマリSKUとして設定され、優先SKUにピン留めされました。」
- 「優先店舗を[店舗名]に変更」 / 「CurbsideまたはDeliveryに変更」:
.envのHEB_STORE_IDとconfig/household.yamlのstoreを更新するか、H-E-Bセッション上のアクティブな店舗/受け取りモードを更新し、新しい店舗でのカートアイテムの在庫を再確認。