AIが商談内容を理解して勝手にマッチング:Google Meet録画とn8nで作る「自走する営業アシスタント」

目次

はじめに

「会議のあとに議事録をまとめる」「CRMに入力する」「依頼内容に合いそうなパートナーを探す」──こうした作業は、付加価値を生む本来の業務ではありません。しかし現実には毎日多くの時間を消費しています。

この記事では、Google Meet の録画ファイルから自動で文字起こしテキストを取得し、AIで内容を理解させ、CRMへの登録、そしてパートナーマッチングまで 完全自動化する n8n ワークフローの作り方を解説します。

ノーコード初心者でも理解できるように、処理の流れを図解しながら丁寧に説明します。最後には、記事内で紹介したワークフローを“そのまま使える JSON”として貼り付けているので、読み終わった直後からあなたの環境で自動化を再現できます。

完成イメージ

こんなシーンでの活用に適しています

  • 商談やMTGの内容を「議事録+CRM入力+マッチング準備」まで自動化したいとき
  • Google Meet を使っていて、自動的に会議内容を要約して整理したいとき
  • パートナー情報・案件情報を一元管理し、AIにマッチング判定させたい企業

方法:Google Meet録画からCRM登録までを自動化する

メリット ・完全自動化:Google Meet録画→要約→CRM登録→マッチング→Slack通知まで一連処理
・高精度AI解析:Geminiが会議内容を要約し、GPT-4o-miniが会議タイプを識別
・構造化データ抽出:顧客要件やパートナー情報をJSON化してSheetsに保存
・レコメンドAI:マッチングスコアを算出し、TOP3を自動提示
・情報共有:Slackにレポート形式で即時通知
デメリット ・認証設定:Google API/Slack/OpenAI/Gemini の事前設定が必要
・AIコスト:要約・分類・抽出・マッチングのAPI利用分が従量課金
・安定化調整:AIのJSONエラーを防ぐためプロンプト設計が必須
難易度・面倒さ 難易度:★★★☆☆(中級)
所要時間:90〜120分
必要スキル:n8nノード接続/Google API権限設定/AIモデルの基本操作
特徴 ・会議録の解析からマッチングまで完全ノーコードで実行
・Google Drive/Sheets/Slack だけで完結
・Gemini 2.5 Flash+GPT-4o-mini のハイブリッドAI処理
・「自走する営業アシスタント」構造をそのまま実現
価格n8n:セルフホスト無料/クラウド版 €20〜
OpenAI(GPT-4o-mini):従量課金(非常に低コスト)
Gemini:従量課金(無料枠あり)
Google Workspace:有料プラン(Google Meetの文字起こし用)
Slack:無料〜
合計:月数百円〜数千円で運用可能

事前準備

ワークフロー全体像

このワークフローは、Google Meet の録画から自動生成される文字起こしファイル(docx)を起点に、AI が会議内容を理解して必要な情報を抽出し、CRM 登録とパートナーマッチングまでを連続して処理するよう設計されています。Google Drive が新しい docx を検知すると、n8n がファイルを取り込みテキスト化し、Gemini が商談内容を要約、GPT-4o-mini が会議タイプの判別と顧客・パートナー情報の構造化抽出を行います。抽出されたデータは Google Sheets へ保存され、それを元に AI がスキル・予算・実績など複数の観点でパートナー候補をスコアリングし、最適な上位3社を自動選定します。最終的に、結果は Slack へレポート形式で通知されるため、会議後の「議事録整理」「CRM入力」「候補選定」といった作業がすべて一連の流れで完結する仕組みになっています。

設定手順

Step 1:ワークフローの作成

1-1. 以下のコードをコピーし、JSONファイル形式(.json)で保存

{
  "name": "AI Meeting CRM with Matching",
  "nodes": [
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyHour"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "value": "1jdSuBwH89becG2vV3vEHLpZTn35k6Gr5",
          "mode": "list",
          "cachedResultName": "Meet Recordings",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1jdSuBwH89becG2vV3vEHLpZTn35k6Gr5"
        },
        "event": "fileCreated",
        "options": {}
      },
      "type": "n8n-nodes-base.googleDriveTrigger",
      "typeVersion": 1,
      "position": [
        0,
        -832
      ],
      "id": "ed70383e-b0d4-4da0-9e89-a88f5903b550",
      "name": "Google Drive Trigger",
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "Obnq4dVqkZhLFtHO",
          "name": "Google Drive account"
        }
      }
    },
    {
      "parameters": {
        "operation": "download",
        "fileId": {
          "__rl": true,
          "value": "={{ $json.id }}",
          "mode": "id"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        448,
        -832
      ],
      "id": "c5ec51d4-bbfc-4411-88a7-6356ce8a38d7",
      "name": "Download file",
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "Obnq4dVqkZhLFtHO",
          "name": "Google Drive account"
        }
      }
    },
    {
      "parameters": {},
      "type": "n8n-nodes-docx-converter.docxToText",
      "typeVersion": 1,
      "position": [
        672,
        -832
      ],
      "id": "f16fd5aa-5f29-46e1-8e48-1d04ecb0802d",
      "name": "DOCX to Text"
    },
    {
      "parameters": {
        "jsCode": "// シンプル版 - formattedForAIのみを出力\n// 文字起こしセクションを抽出してAI用に整形するだけ\n\n// 入力データを取得\nconst inputData = $input.all()[0].json;\nconst fullText = inputData.text;\n\ntry {\n  // 「文字起こし」セクション以下を抽出\n  let transcriptionStart = fullText.indexOf('📖 文字起こし');\n  \n  if (transcriptionStart === -1) {\n    transcriptionStart = fullText.indexOf('文字起こし');\n  }\n  \n  if (transcriptionStart === -1) {\n    return [{\n      json: {\n        error: \"文字起こしセクションが見つかりませんでした\",\n        formattedForAI: \"\"\n      }\n    }];\n  }\n  \n  // 文字起こしセクション以下のテキストを取得\n  const transcriptionText = fullText.substring(transcriptionStart);\n  \n  // シンプルなクリーンアップ\n  const cleanedText = transcriptionText\n    .replace(/📖 文字起こし/g, '') // タイトル除去\n    .replace(/\\\\+$/gm, '') // 行末のバックスラッシュ除去\n    .replace(/^\\s*###?\\s*/gm, '') // 行頭の###除去  \n    .replace(/\\*\\*/g, '') // **マークダウン除去\n    .split('\\n')\n    .filter(line => {\n      const trimmed = line.trim();\n      // 空行、日付行、終了メッセージなどを除外\n      return trimmed.length > 0 && \n             !trimmed.match(/^\\d{4}年\\d{1,2}月\\d{1,2}日/) &&\n             !trimmed.includes('より後に文字起こしが終了') &&\n             !trimmed.includes('編集可能な文字起こし') &&\n             !trimmed.includes('コンピュータが生成');\n    })\n    .join('\\n')\n    .trim();\n  \n  // 結果を返す\n  return [{\n    json: {\n      formattedForAI: cleanedText\n    }\n  }];\n  \n} catch (error) {\n  return [{\n    json: {\n      error: error.message,\n      formattedForAI: \"\"\n    }\n  }];\n}"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        896,
        -832
      ],
      "id": "99ecb532-5fc7-47b9-af46-153ae784259d",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "d803c964-ead7-4020-ae48-851d6be757bb",
              "leftValue": "={{ $json.name }}",
              "rightValue": "ai on",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            },
            {
              "id": "265cfeca-8783-4b10-aaba-56937a98a579",
              "leftValue": "={{ $json.mimeType }}",
              "rightValue": ".document",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        224,
        -832
      ],
      "id": "4cc0c8e4-e98f-424d-9f61-91574bca1008",
      "name": "If"
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "models/gemini-2.5-flash",
          "mode": "list",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "messages": {
          "values": [
            {
              "content": "=prompt:\n  role: \"会議記録の要点抽出アシスタント\"\n\n  purpose: >\n    会議の文字起こしデータから、重要な要点を日本語で簡潔に抽出する。\n    出力は5〜10項目の箇条書きとし、余計な文や前置きは不要とする。\n\n  output_format:\n    - 形式: \"日本語の箇条書き(5〜10項目)\"\n    - 固有名詞: \"そのまま保持\"\n    - 個人情報: \"役割(例:営業担当、顧客担当など)で表現\"\n    - 内容優先度:\n        1: \"会議目的\"\n        2: \"参加者の立場\"\n        3: \"要望・課題\"\n        4: \"説明されたサービス\"\n        5: \"条件(人数・時期・単価・場所・稼働)\"\n\n  input_format:\n    description: >\n      入力は「名前: 会話内容」という形式の会議文字起こし。\n      タイムスタンプや改行欠落があるため、下記ルールに従って解釈する。\n\n    rules:\n      - \"各発話は『話者名 + コロン + 会話文』の形式。\"\n      - \"例: Reizi: まずは簡単な自己紹介お願いできますか?\"\n      - >\n        話者が切り替わる際、改行がない場合がある。\n        例: 「お願いいたします川下清彦: あ、はい。」\n        → 「川下清彦:」の前に改行がなくても、新しい話者の発話として認識する。\n      - \"タイムスタンプ(例: 00:00:00)は無視する。\"\n      - \"出力では、話者ごとに発話を分離・整理して扱う。\"\n      - \"複数人が登場する場合、各話者を一意に扱う(例: Reizi, 川下清彦 など)。\"\n      - >\n        発話切り替えが曖昧な場合、コロン(:)を基準に\n        「人名 + :」が出現したら新しい話者ブロックとみなして分離する。\n\n  instructions:\n    - \"上記ルールに基づき、入力全体を分析して要点を抽出する。\"\n    - \"不要な前置き文、冗長な説明、推測的な内容は出力しない。\"\n    - \"出力は要約箇条書きのみとし、他の形式や装飾を含めない。\"\n\n  example_input: |\n    Reizi: まずは簡単な自己紹介お願いできますか?\n    川下清彦: はい。ありがとうございます。株式会社の川下と申します。\n    Reizi: ありがとうございます。ではサービス内容を教えてください。\n    川下清彦: はい、弊社はWebマーケティング支援を中心に〜\n\n  expected_output: |\n    - 会議の目的は、パートナー企業(川下氏)のサービス内容を確認すること。\n    - 川下氏は株式会社〇〇の代表で、Webマーケティング支援を行っている。\n    - 対象顧客は年商1〜10億円規模の企業。\n    - 主な課題は経営者の業務多忙による成長施策の停滞。\n    - 提供サービスはWeb広告運用とマーケティング戦略支援。\n    - Reizi側は自社顧客へのマッチング可能性を検討している。\n",
              "role": "model"
            },
            {
              "content": "=以下は会議文字起こしの一部です。要点を抽出してください。\n\n---\n{{ $json.formattedForAI }}\n"
            }
          ]
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1,
      "position": [
        1120,
        -832
      ],
      "id": "4b814c27-2b3f-4d8c-ab6c-fe4ab4660867",
      "name": "Message a model",
      "credentials": {
        "googlePalmApi": {
          "id": "AYw1Zg4Lbctb0W9U",
          "name": "Google Gemini(PaLM) Api account"
        }
      }
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "gpt-4o-mini",
          "mode": "list",
          "cachedResultName": "GPT-4O-MINI"
        },
        "messages": {
          "values": [
            {
              "content": "あなたは人材マッチング用の会議分類器。出力は必ず JSON のみ。\nkeys:\n- meeting_type: \"client_need\" | \"partner_pitch\" | \"unknown\"\n- confidence: 0.00〜1.00\n- rationale: 日本語で3行以内(根拠)\n- key_signals: 日本語配列(検知パターン 3〜8)\n\n判定基準:\n- 「課題/要件ヒアリング(人数・開始時期・単価・勤務地・稼働形態)」中心 → client_need\n- 「自社サービス説明・機能・料金・導入事例」中心 → partner_pitch\n- 判別不能 →unknown\n\n禁止:JSON以外の出力、前置き文。\n",
              "role": "system"
            },
            {
              "content": "=以下のJSONL文字起こしの会議タイプを出力してください。\n---\n{{ $json.content.parts[0].text }}\n#実行結果"
            }
          ]
        },
        "jsonOutput": true,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.8,
      "position": [
        1472,
        -832
      ],
      "id": "4453f8a1-97e8-4d13-9213-935be513bddd",
      "name": "Message a model2",
      "credentials": {
        "openAiApi": {
          "id": "wOf6eji4BL8Mxsfq",
          "name": "OpenAi account"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.message.content.meeting_type }}",
                    "rightValue": "client_need",
                    "operator": {
                      "type": "string",
                      "operation": "contains"
                    },
                    "id": "24749452-6103-495d-a2f9-8a6c37e989e4"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "23f61553-702c-49f9-bea6-30eb04845db3",
                    "leftValue": "={{ $json.message.content.meeting_type }}",
                    "rightValue": "partner_pitch",
                    "operator": {
                      "type": "string",
                      "operation": "contains"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "2a0ef08c-1067-4e74-b8cd-1a877710b2b0",
                    "leftValue": "={{ $json.message.content.meeting_type }}",
                    "rightValue": "unknown",
                    "operator": {
                      "type": "string",
                      "operation": "contains"
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.3,
      "position": [
        1824,
        -848
      ],
      "id": "4951b21e-84db-4617-bf0d-2ab1ebc32d41",
      "name": "Switch"
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "12kqWJWwmzTI2gHAPhqsjgKPX6e-FONQ31KNM11fslJk",
          "mode": "list",
          "cachedResultName": "CRMリスト",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12kqWJWwmzTI2gHAPhqsjgKPX6e-FONQ31KNM11fslJk/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "partner",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12kqWJWwmzTI2gHAPhqsjgKPX6e-FONQ31KNM11fslJk/edit#gid=0"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "timestamp": "={{ $('Google Drive Trigger').item.json.createdTime }}",
            "services": "={{ $json.message.content.services }}",
            "partner_name": "={{ $json.message.content.partner_name }}",
            "speaker_name": "={{ $json.message.content.speaker_name }}",
            "skills": "={{ $json.message.content.skills }}",
            "coverage_area": "={{ $json.message.content.coverage_area }}",
            "price_model": "={{ $json.message.content.price_model }}",
            "scale": "={{ $json.message.content.scale }}",
            "price_range": "={{ $json.message.content.price_range }}",
            "lead_time": "={{ $json.message.content.lead_time }}",
            "track_records": "={{ $json.message.content.track_records }}",
            "differentiators": "={{ $json.message.content.differentiators }}",
            "constraints": "={{ $json.message.content.constraints }}",
            "rationale": "={{ $json.message.content.rationale }}",
            "confidence": "={{ $json.message.content.confidence }}",
            "meeting_doc_url": "={{ $('Google Drive Trigger').item.json.webViewLink }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "timestamp",
              "displayName": "timestamp",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "partner_name",
              "displayName": "partner_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "speaker_name",
              "displayName": "speaker_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "services",
              "displayName": "services",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "skills",
              "displayName": "skills",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "coverage_area",
              "displayName": "coverage_area",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "scale",
              "displayName": "scale",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "price_model",
              "displayName": "price_model",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "price_range",
              "displayName": "price_range",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "lead_time",
              "displayName": "lead_time",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "track_records",
              "displayName": "track_records",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "differentiators",
              "displayName": "differentiators",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "constraints",
              "displayName": "constraints",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "rationale",
              "displayName": "rationale",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "confidence",
              "displayName": "confidence",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "meeting_doc_url",
              "displayName": "meeting_doc_url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        2400,
        -640
      ],
      "id": "9a67aac6-aeb9-462c-b56c-3137cfa2a626",
      "name": "Append row in sheet",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "VDmxGDWzxa9mgOwx",
          "name": "Google Sheets account"
        }
      }
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "value": "C08FS79B3NG",
          "mode": "list",
          "cachedResultName": "test"
        },
        "text": "=パートナー企業の登録を完了しました。\n{{ $('Google Drive Trigger').item.json.webViewLink }}",
        "otherOptions": {}
      },
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        2624,
        -640
      ],
      "id": "18a5d854-37ee-4c29-9047-6e71165b1978",
      "name": "Send a message",
      "webhookId": "d8f8ab17-ecbe-4d65-bf82-04c712bb4fdd",
      "credentials": {
        "slackApi": {
          "id": "KyHQfIGnYhJNhWhg",
          "name": "Slack account"
        }
      }
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "12kqWJWwmzTI2gHAPhqsjgKPX6e-FONQ31KNM11fslJk",
          "mode": "list",
          "cachedResultName": "CRMリスト",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12kqWJWwmzTI2gHAPhqsjgKPX6e-FONQ31KNM11fslJk/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": 1601174527,
          "mode": "list",
          "cachedResultName": "client",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12kqWJWwmzTI2gHAPhqsjgKPX6e-FONQ31KNM11fslJk/edit#gid=1601174527"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "company_name": "={{ $json.message.content.company_name }}",
            "industry": "={{ $json.message.content.industry }}",
            "role_titles": "={{ $json.message.content.role_titles }}",
            "must_skills": "={{ $json.message.content.must_skills }}",
            "nice_to_have": "={{ $json.message.content.nice_to_have }}",
            "headcount": "={{ $json.message.content.headcount }}",
            "work_style": "={{ $json.message.content.work_style }}",
            "location": "={{ $json.message.content.location }}",
            "start_timing": "={{ $json.message.content.start_timing }}",
            "period": "={{ $json.message.content.period }}",
            "budget_range": "={{ $json.message.content.budget_range }}",
            "language": "={{ $json.message.content.language }}",
            "constraints": "={{ $json.message.content.constraints }}",
            "priority": "={{ $json.message.content.priority }}",
            "rationale": "={{ $json.message.content.rationale }}",
            "confidence": "={{ $json.message.content.confidence }}",
            "meeting_doc_url": "={{ $('Google Drive Trigger').item.json.webViewLink }}",
            "timestamp": "={{ $('Google Drive Trigger').item.json.createdTime }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "timestamp",
              "displayName": "timestamp",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "company_name",
              "displayName": "company_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "industry",
              "displayName": "industry",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "role_titles",
              "displayName": "role_titles",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "must_skills",
              "displayName": "must_skills",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "nice_to_have",
              "displayName": "nice_to_have",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "headcount",
              "displayName": "headcount",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "work_style",
              "displayName": "work_style",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "location",
              "displayName": "location",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "start_timing",
              "displayName": "start_timing",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "period",
              "displayName": "period",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "budget_range",
              "displayName": "budget_range",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "language",
              "displayName": "language",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "constraints",
              "displayName": "constraints",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "priority",
              "displayName": "priority",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "rationale",
              "displayName": "rationale",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "confidence",
              "displayName": "confidence",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "meeting_doc_url",
              "displayName": "meeting_doc_url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        2400,
        -1024
      ],
      "id": "6122731a-a8e4-45fb-a587-fdfaafcb15e7",
      "name": "Append row in sheet1",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "VDmxGDWzxa9mgOwx",
          "name": "Google Sheets account"
        }
      }
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "12kqWJWwmzTI2gHAPhqsjgKPX6e-FONQ31KNM11fslJk",
          "mode": "list",
          "cachedResultName": "CRMリスト",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12kqWJWwmzTI2gHAPhqsjgKPX6e-FONQ31KNM11fslJk/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "partner",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12kqWJWwmzTI2gHAPhqsjgKPX6e-FONQ31KNM11fslJk/edit#gid=0"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        2624,
        -832
      ],
      "id": "32be8afb-731e-4a58-bae1-b170ce997b78",
      "name": "Get row(s) in sheet",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "VDmxGDWzxa9mgOwx",
          "name": "Google Sheets account"
        }
      }
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "models/gemini-2.5-flash",
          "mode": "list",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "messages": {
          "values": [
            {
              "content": "あなたは人材マッチング評価の専門AIです。\n顧客要件とパートナー企業情報を詳細に分析し、スコアリングを行います。\n\n## 評価基準と重み\n{{ $('Matching Config').item.json.weights }}\n\n## 評価プロセス\n1. 各カテゴリで0-1のスコアを算出\n2. 重み付けして総合スコアを計算\n3. 優先度ボーナスを加算\n\n## 出力フォーマット(JSON必須)\n{\n  \"partner_id\": \"パートナーID\",\n  \"partner_name\": \"企業名\",\n  \"scores\": {\n    \"skills\": 0.0,\n    \"budget\": 0.0,\n    \"location\": 0.0,\n    \"experience\": 0.0\n  },\n  \"total_score\": 0.0,\n  \"match_points\": [\"強み1\", \"強み2\", \"強み3\"],\n  \"gap_points\": [\"課題1\", \"課題2\"],\n  \"recommendation\": \"strong_match | good_match | consider | not_recommended\",\n  \"summary\": \"1-2文の評価サマリー\"\n}",
              "role": "model"
            },
            {
              "content": "=## 顧客要件\n{{ JSON.stringify($('Client_Problem Extraction').item.json.message.content) }}\n\n## パートナー情報\n{{ JSON.stringify($json) }}\n\n## 重み設定\n{{ JSON.stringify($('Matching Config').item.json.weights) }}\n\n上記情報を基に、詳細なマッチング評価を実施してください。"
            }
          ]
        },
        "jsonOutput": true,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1,
      "position": [
        3072,
        -832
      ],
      "id": "bf402234-5054-44b7-a212-d2159b207488",
      "name": "Message a model4",
      "credentials": {
        "googlePalmApi": {
          "id": "AYw1Zg4Lbctb0W9U",
          "name": "Google Gemini(PaLM) Api account"
        }
      }
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "gpt-4o-mini",
          "mode": "list",
          "cachedResultName": "GPT-4O-MINI"
        },
        "messages": {
          "values": [
            {
              "content": "あなたは人材マッチング用の顧客要件抽出アシスタントです。\n入力は顧客とのヒアリング会議の文字起こしです。\n出力は必ずJSONのみとし、以下のフィールドを含めてください。\n\n{\n  \"company_name\": \"\",\n  \"industry\": \"\",\n  \"role_titles\": [],\n  \"must_skills\": [],\n  \"nice_to_have\": [],\n  \"headcount\": \"\",\n  \"work_style\": \"\",\n  \"location\": [],\n  \"start_timing\": \"\",\n  \"period\": \"\",\n  \"budget_range\": \"\",\n  \"language\": \"\",\n  \"constraints\": [],\n  \"priority\": \"\",\n  \"rationale\": \"\",\n  \"confidence\": \"\",\n  \"meeting_doc_url\": \"\"\n}\n\n出力条件:\n- JSON以外の出力は禁止。\n- 該当情報がない場合は空文字(\"\")。\n- 数値や単価は日本語のまま(例:60〜70万円/月)。\n- 「会社名」や「勤務地」が不明な場合は空で構わない。\n",
              "role": "system"
            },
            {
              "content": "=以下は顧客企業とのヒアリング会議の文字起こしです。\n内容を解析して、上記のJSON形式で出力してください。\n---\n{{ $('Code in JavaScript').item.json.formattedForAI }}"
            }
          ]
        },
        "jsonOutput": true,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.8,
      "position": [
        2048,
        -928
      ],
      "id": "9fb6b523-dca8-4e12-98be-e6d8bb658cd6",
      "name": "Client_Problem Extraction",
      "credentials": {
        "openAiApi": {
          "id": "wOf6eji4BL8Mxsfq",
          "name": "OpenAi account"
        }
      }
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "gpt-4o-mini",
          "mode": "list",
          "cachedResultName": "GPT-4O-MINI"
        },
        "messages": {
          "values": [
            {
              "content": "あなたは人材マッチング用のパートナー情報抽出アシスタントです。\n入力はパートナー企業との会話の文字起こしです。\n出力は必ずJSONのみとし、以下の項目を含めてください。\n\n{\n  \"partner_name\": \"会社名\",\n  \"speaker_name\": \"話者名(わかる場合)\",\n  \"services\": [\"提供サービス1\", \"提供サービス2\"],\n  \"skills\": [\"技術スキル1\", \"技術スキル2\"],\n  \"coverage_area\": [\"対応エリア\"],\n  \"scale\": \"動員可能人数・規模\",\n  \"price_model\": \"料金体系(例:固定/成果報酬)\",\n  \"price_range\": \"単価帯(例:30〜50万円/月)\",\n  \"lead_time\": \"対応までの期間\",\n  \"track_records\": [\"実績・導入事例\"],\n  \"differentiators\": [\"強み・差別化ポイント\"],\n  \"constraints\": [\"契約条件や制約\"],\n  \"rationale\": \"分類理由や背景(任意)\",\n  \"confidence\": \"分類時の信頼度\",\n  \"meeting_doc_url\": \"元のGoogleドキュメントURL\"\n}\n\n注意:\n- JSON以外の出力は禁止。\n- 文字起こしから得られない項目は空文字 \"\" としてください。\n",
              "role": "system"
            },
            {
              "content": "=以下はパートナー企業との会話の文字起こしです。\nこの内容から上記フォーマットに従って情報を抽出してください。\n---\n{{ $('Code in JavaScript').item.json.formattedForAI }}"
            }
          ]
        },
        "jsonOutput": true,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.8,
      "position": [
        2048,
        -640
      ],
      "id": "9b2d2bdb-439b-498a-a799-ef403e9ae6ba",
      "name": "Partner Company Information Extraction",
      "credentials": {
        "openAiApi": {
          "id": "wOf6eji4BL8Mxsfq",
          "name": "OpenAi account"
        }
      }
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        2848,
        -832
      ],
      "id": "ec4ca5d3-e6de-4736-9805-05b89481c1eb",
      "name": "Loop Over Items"
    },
    {
      "parameters": {
        "jsCode": "// マッチング評価の重み付け設定(カスタマイズ可能)\nconst MATCHING_WEIGHTS = {\n  skills: 0.40,        // 技術・スキルマッチ度\n  budget: 0.25,        // 予算・期間の適合性\n  location: 0.20,      // 地域・稼働スタイル\n  experience: 0.15     // 実績・強み\n};\n\n// 重要度調整係数\nconst PRIORITY_BONUS = {\n  'High': 0.05,\n  'Medium': 0.02,\n  'Low': 0\n};\n\nreturn [{\n  json: {\n    weights: MATCHING_WEIGHTS,\n    priorityBonus: PRIORITY_BONUS,\n    timestamp: new Date().toISOString()\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2400,
        -832
      ],
      "id": "7b35f361-5608-41ab-9213-bfaab216ba77",
      "name": "Matching Config"
    },
    {
      "parameters": {
        "jsCode": "// 全パートナーのマッチング結果を集約\nconst allResults = [];\nconst memoryData = [];\n\n// 入力データを処理\nfor (const item of $input.all()) {\n  const result = item.json;\n  \n  // メモリ用データ作成\n  memoryData.push({\n    partner: result.partner_name,\n    score: result.total_score,\n    timestamp: new Date().toISOString()\n  });\n  \n  // 結果を蓄積\n  allResults.push(result);\n}\n\n// スコアで降順ソート\nallResults.sort((a, b) => b.total_score - a.total_score);\n\n// TOP3を抽出\nconst top3 = allResults.slice(0, 3);\n\n// 推奨レベルでグループ分け\nconst grouped = {\n  strong_match: allResults.filter(r => r.recommendation === 'strong_match'),\n  good_match: allResults.filter(r => r.recommendation === 'good_match'),\n  consider: allResults.filter(r => r.recommendation === 'consider'),\n  not_recommended: allResults.filter(r => r.recommendation === 'not_recommended')\n};\n\n// 統計情報\nconst stats = {\n  total_partners: allResults.length,\n  average_score: allResults.reduce((sum, r) => sum + r.total_score, 0) / allResults.length,\n  strong_matches: grouped.strong_match.length,\n  good_matches: grouped.good_match.length\n};\n\nreturn [{\n  json: {\n    client_info: $('Client_Problem Extraction').item.json.message.content,\n    all_results: allResults,\n    top3_recommendations: top3,\n    grouped_results: grouped,\n    statistics: stats,\n    memory_log: memoryData,\n    processing_timestamp: new Date().toISOString()\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3136,
        -1024
      ],
      "id": "7181179e-2b34-4359-b3c7-279d5068ed42",
      "name": "Aggregate Results"
    },
    {
      "parameters": {
        "jsCode": "// Slack通知用のリッチメッセージを生成(完全修正版)\nconst data = $json;\nconst client = data.client_info;\n\n// データ構造を解析して実際のパートナー情報を取得\nconst parsePartnerData = (item) => {\n  try {\n    // content.parts[0].text にJSON文字列として格納されている場合\n    if (item?.content?.parts?.[0]?.text) {\n      return JSON.parse(item.content.parts[0].text);\n    }\n    // 既にパースされたオブジェクトの場合\n    return item;\n  } catch (error) {\n    console.error('パートナーデータのパースに失敗:', error);\n    return null;\n  }\n};\n\n// all_resultsとtop3をパース\nconst allResults = data.all_results.map(parsePartnerData).filter(p => p !== null);\nconst top3Raw = data.top3_recommendations.map(parsePartnerData).filter(p => p !== null);\n\n// スコアでソートしてTOP3を取得(変数をグローバルスコープで定義)\nconst sortedTop3 = top3Raw.sort((a, b) => (b.total_score || 0) - (a.total_score || 0)).slice(0, 3);\n\n// 統計情報を再計算\nconst stats = {\n  total_partners: allResults.length,\n  average_score: allResults.length > 0 \n    ? allResults.reduce((sum, r) => sum + (r.total_score || 0), 0) / allResults.length \n    : 0,\n  strong_matches: allResults.filter(r => r.recommendation === 'strong_match').length,\n  good_matches: allResults.filter(r => r.recommendation === 'good_match').length\n};\n\n// 絵文字マッピング\nconst getEmoji = (score) => {\n  if (score >= 0.8) return '🌟';\n  if (score >= 0.6) return '✨';\n  if (score >= 0.4) return '👍';\n  return '📊';\n};\n\n// メダル絵文字\nconst medals = ['🥇', '🥈', '🥉'];\n\n// Slack Blocks形式のメッセージ構築\nconst blocks = [\n  {\n    type: 'header',\n    text: {\n      type: 'plain_text',\n      text: `🎯 パートナーマッチング完了: ${client.company_name || '新規顧客'}`,\n      emoji: true\n    }\n  },\n  {\n    type: 'context',\n    elements: [\n      {\n        type: 'mrkdwn',\n        text: `*処理時刻:* ${new Date().toLocaleString('ja-JP')} | *評価対象:* ${stats.total_partners}社`\n      }\n    ]\n  },\n  {\n    type: 'divider'\n  },\n  {\n    type: 'section',\n    text: {\n      type: 'mrkdwn',\n      text: `*📋 顧客要件サマリー*\\n` +\n            `• *必須スキル:* ${Array.isArray(client.must_skills) ? client.must_skills.join(', ') : (client.must_skills || 'N/A')}\\n` +\n            `• *予算:* ${client.budget_range || 'N/A'}\\n` +\n            `• *人数:* ${client.headcount || 'N/A'}\\n` +\n            `• *開始時期:* ${client.start_timing || 'N/A'}\\n` +\n            `• *優先度:* ${client.priority || 'Medium'}`\n    }\n  },\n  {\n    type: 'divider'\n  },\n  {\n    type: 'section',\n    text: {\n      type: 'mrkdwn',\n      text: '*🏆 TOP 3 推奨パートナー*'\n    }\n  }\n];\n\n// TOP3の詳細を追加\nif (sortedTop3.length === 0) {\n  blocks.push({\n    type: 'section',\n    text: {\n      type: 'mrkdwn',\n      text: '_適切なパートナーが見つかりませんでした。要件の見直しをご検討ください。_'\n    }\n  });\n} else {\n  sortedTop3.forEach((partner, index) => {\n    const medal = medals[index];\n    const emoji = getEmoji(partner.total_score || 0);\n    \n    // match_pointsとgap_pointsの処理\n    let matchPoints = 'N/A';\n    let gapPoints = 'なし';\n    \n    if (Array.isArray(partner.match_points)) {\n      matchPoints = partner.match_points.slice(0, 3).join(', ');\n      if (partner.match_points.length > 3) {\n        matchPoints += ` 他${partner.match_points.length - 3}項目`;\n      }\n    } else if (partner.match_points) {\n      matchPoints = String(partner.match_points);\n    }\n    \n    if (Array.isArray(partner.gap_points) && partner.gap_points.length > 0) {\n      gapPoints = partner.gap_points.slice(0, 2).join(', ');\n      if (partner.gap_points.length > 2) {\n        gapPoints += ` 他${partner.gap_points.length - 2}項目`;\n      }\n    } else if (partner.gap_points) {\n      gapPoints = String(partner.gap_points);\n    }\n    \n    // 推奨レベルを日本語に変換\n    const recommendationText = {\n      'strong_match': '強く推奨',\n      'good_match': '推奨',\n      'consider': '検討可',\n      'not_recommended': '非推奨'\n    }[partner.recommendation] || partner.recommendation;\n    \n    blocks.push({\n      type: 'section',\n      text: {\n        type: 'mrkdwn',\n        text: `${medal} *${partner.partner_name || 'Unknown'}* (${recommendationText})\\n` +\n              `${emoji} スコア: *${((partner.total_score || 0) * 100).toFixed(1)}点*\\n` +\n              `✅ *強み:* ${matchPoints}\\n` +\n              `⚠️ *課題:* ${gapPoints}\\n` +\n              `💬 _${partner.summary || 'サマリーなし'}_`\n      }\n    });\n    \n    if (index < sortedTop3.length - 1) {\n      blocks.push({ type: 'divider' });\n    }\n  });\n}\n\n// 統計情報セクション\nblocks.push(\n  {\n    type: 'divider'\n  },\n  {\n    type: 'context',\n    elements: [\n      {\n        type: 'mrkdwn',\n        text: `📊 *マッチング統計:* 強い一致 ${stats.strong_matches}社 | 良い一致 ${stats.good_matches}社 | 平均スコア ${(stats.average_score * 100).toFixed(1)}点`\n      }\n    ]\n  }\n);\n\n// ボタンセクション(適切なマッチがある場合のみ)\nif (sortedTop3.length > 0 && sortedTop3[0].recommendation !== 'not_recommended') {\n  blocks.push({\n    type: 'actions',\n    elements: [\n      {\n        type: 'button',\n        text: {\n          type: 'plain_text',\n          text: '詳細を確認',\n          emoji: true\n        },\n        value: 'view_details',\n        action_id: 'view_details',\n        style: 'primary'\n      },\n      {\n        type: 'button',\n        text: {\n          type: 'plain_text',\n          text: 'CRMシートを開く',\n          emoji: true\n        },\n        url: 'https://docs.google.com/spreadsheets/d/12kqWJWwmzTI2gHAPhqsjgKPX6e-FONQ31KNM11fslJk',\n        action_id: 'open_sheet'\n      }\n    ]\n  });\n}\n\n// 結果を返す\nconst top1 = sortedTop3?.[0];\nlet resultText = '';\n\nif (!top1) {\n  resultText = `マッチング完了: ${client.company_name || '新規顧客'} - 適切なパートナーが見つかりませんでした`;\n} else if (top1.recommendation === 'not_recommended') {\n  resultText = `マッチング完了: ${client.company_name || '新規顧客'} - 推奨可能なパートナーがありません(最高スコア: ${((top1.total_score || 0) * 100).toFixed(1)}点)`;\n} else {\n  resultText = `マッチング完了: ${client.company_name || '新規顧客'} - TOP1: ${top1.partner_name || 'N/A'} (${((top1.total_score || 0) * 100).toFixed(1)}点)`;\n}\n\nreturn [{\n  json: {\n    blocks: blocks,\n    text: resultText,\n    // サマリー情報(Slack以外での利用用)\n    summary: {\n      client: client.company_name || '新規顧客',\n      top_partner: top1?.partner_name || null,\n      top_score: top1?.total_score || 0,\n      total_evaluated: stats.total_partners,\n      matching_quality: stats.strong_matches > 0 ? 'high' : stats.good_matches > 0 ? 'medium' : 'low'\n    }\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3424,
        -1024
      ],
      "id": "9b1e0242-7d90-45bc-8efb-a5002ce516d3",
      "name": "Format Slack Message"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "name": "Replace Me",
      "typeVersion": 1,
      "position": [
        3424,
        -768
      ],
      "id": "6ce6ffb6-e637-4469-b7b0-3bb15701baad"
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "value": "C09G8RU6RPC",
          "mode": "list",
          "cachedResultName": "n8n-test"
        },
        "text": "={{ $json.text }}\n\n{{ $json.blocks[3].text.text }}\n\n{{ $json.blocks[6].text.text }}\n\n{{ $json.blocks[8].text.text }}\n\n{{ $json.blocks[10].text.text }}\n",
        "otherOptions": {}
      },
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        3648,
        -1024
      ],
      "id": "816313ad-44ca-4fb9-acc0-33a42df0a41c",
      "name": "Send a message1",
      "webhookId": "d8f8ab17-ecbe-4d65-bf82-04c712bb4fdd",
      "credentials": {
        "slackApi": {
          "id": "KyHQfIGnYhJNhWhg",
          "name": "Slack account"
        }
      }
    }
  ],
  "pinData": {},
  "connections": {
    "Google Drive Trigger": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Message a model",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If": {
      "main": [
        [
          {
            "node": "Download file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Message a model": {
      "main": [
        [
          {
            "node": "Message a model2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Message a model2": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch": {
      "main": [
        [
          {
            "node": "Client_Problem Extraction",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Partner Company Information Extraction",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download file": {
      "main": [
        [
          {
            "node": "DOCX to Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DOCX to Text": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append row in sheet": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append row in sheet1": {
      "main": [
        []
      ]
    },
    "Client_Problem Extraction": {
      "main": [
        [
          {
            "node": "Append row in sheet1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Matching Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Partner Company Information Extraction": {
      "main": [
        [
          {
            "node": "Append row in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Aggregate Results",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Message a model4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Matching Config": {
      "main": [
        [
          {
            "node": "Get row(s) in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Results": {
      "main": [
        [
          {
            "node": "Format Slack Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Slack Message": {
      "main": [
        [
          {
            "node": "Send a message1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Message a model4": {
      "main": [
        [
          {
            "node": "Replace Me",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Replace Me": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "d4d3ac82-a2e3-4f4a-86cc-b0fb2f776346",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "0e4c8345464db5f08b169b9a7e9adf77796f822ef350a06e35dc240f03930888"
  },
  "id": "0pMdiR7EIHw4Z98p",
  "tags": []
}

1-2. n8nで新規ワークフローを作成し、右上の「・・・」から、Import from Fileを選択し、保存したJSONファイルを選択

1-3. 右上の「+」から開けるノード検索で「docx」と入力し、 DOCX to Textノードをインストール(n8nのCommunity Nodesとして提供されている)

1-4. 全体のフロー接続が完成していることを確認

Step 2:トリガーと初期フィルタリング

2-1. トリガーと初期フィルタリングにかかわるノード設定を確認する。

2-1. Google Drive Triggerの設定を確認する。まずPoll Timesで任意に実行頻度を設定(提供したフローでは、一時間ごとに設定)。次に、FolderにGoogle Meetのレコーディング結果が保存されるフォルダであるマイドライブ直下のMeet Recordingsに設定。Watch forでFile Createdに設定。こうすることで、Google Meetの会議終了後にレコーディング結果が保存された際に、このワークフローが実行される。

2-2. Ifの設定が以下のようになっていることを確認する。
会議名に「ai on」というキーワードが入っていて、かつそのトランスクリプトファイルである「.document」形式のファイルが生成されたときのみ、次のステップに移行する。

Step 3:会議内容の分析

3-1. 会議内容の分析に関するノード設定を確認する。

3-2. Google Driveノード設定が以下の設定になっていることを確認する。この設定により、トリガーで検出されたトランスクリプトファイルそのものがダウンロードされる。

3-3. DOCX to Textノードが以下の設定になっていることを確認する。このノードによりダウンロードされたDOCX形式のファイルが処理のしやすいテキストファイルに変換される。

3-4. Code in JavaScriptノードが以下の設定になっていることを確認する。このノードにより変換されたテキストデータの中で文字起こしに関する文章のみを抽出する。

3-5. Message a modelノードが以下の設定になっていることを確認する。このノードでは、入力となる会議の文字起こしテキストから、後段で必要となる情報を含んだ会議の要点を抽出して出力する。比較的長い文章を処理する必要があるので、長文処理が得意なGemini 2.5 Flashのモデルを使用。プロンプトは、システムプロンプトとして要点抽出アシスタントの役割を与え、ユーザープロンプトとして前段で抽出された文字起こしのテキストデータを入力。

3-6. Message a modelノードが以下の設定になっていることを確認する。このノードでは前段の出力である会議の要点のテキストデータを入力として、その会議がどのような会議タイプを判別し、JSONデータとして出力する。会議タイプは3種類で判別する。具体的には、クライアントの課題をヒアリングしている会議「client_need」とパートナー企業との打ち合わせの会議である「partner_pitch」、前述の2つのどちらにも該当しないような会議である「unknown」の3パターン。
ここでは高度な判断をする必要があるため、論理的思考が得意なChatGPT-4o miniのモデルを使用。システムプロンプトは会議の分類機としての役割を与え、ユーザープロンプトとして会議の要点抽出結果のテキストデータを入力する。また、後段で処理しやすいように、JSON形式のファイルとして出力するようにプロンプトに指示するとともに、Output Content as JSONの設定を有効にする。

3-7. Switchノードが以下の設定になっていることを確認する。このノードでは前段の ChatGPT の会議タイプの判断結果を入力として、その会議に応じてワークフローを分岐させる。

Step 4:CRMシートの登録と通知

4-1. CRMシートへの登録と通知に関するノード設定を確認する。これらの一連のノードはパートナー企業との打ち合わせの会議の場合に実行される。

4-2. Google DriveでCRMのリストのスプレッドシートを作成する。作成したシートの1行目に、パートナー企業の特徴を格納するためのヘッダーを入力する。

【ヘッダー】

timestamp	partner_name	speaker_name	services	skills	coverage_area	scale	price_model	price_range	lead_time	track_records	differentiators	constraints	rationale	confidence	meeting_doc_url

4-3. Message a modelノードが以下の設定になっていることを確認する。このノードでは会議の文字起こしデータを分析して、パートナー企業の特徴をヘッダー内容として抽出する。ここでは高度な判断をする必要があるため、論理的思考が得意なChatGPT-4o miniのモデルを使用。システムプロンプトは会議の情報抽出アシスタントとしての役割を与え、ユーザープロンプトとして会議の文字起こしのテキストデータを入力する。また、後段で処理しやすいように、JSON形式のファイルとして出力するようにプロンプトに指示するとともに、Output Content as JSONの設定を有効にする。

4-4. Append row in sheetノードが以下の設定になっていることを確認する。このノードでは前段の ChatGPT のパートナー企業の特徴の抽出結果をCRMリストに記載する。Documentは作成したCRMリストを選択し、Sheetはヘッダーを記載したシートを選択する。Mapping Column ModはMap Each Column Manuallyを選択。

4-5. 続いてスプレッドシートを読み込むと、Value to Sendの部分にヘッダーが表示される。各ヘッダーに対応する変数(ファイルの作成日時や、パートナー企業の特徴)を割り当てる。

4-6. Slackノードが以下の設定になっていることを確認する。このノードでは、スプレッドシートへの入力が完了したことをSlackでユーザーに通知する。Channelは通知をしたいチャネルに設定し、Message TextはにスプレッドシートのURLを記載して送付する。

Step 5:パートナーマッチングと通知

5-1. パートナーマッチングと通知を実施するノード設定を確認する。これらの一連のノードは顧客企業との打ち合わせの会議の場合に実行される。

5-2. 4-2で作成したCRMリストに新たなシートを作成。シートの1行目に、顧客企業の要件を格納するためのヘッダーを入力する。

【ヘッダ】

timestamp	company_name	industry	role_titles	must_skills	nice_to_have	headcount	work_style	location	start_timing	period	budget_range	language	constraints	priority	rationale	confidence	meeting_doc_url

5-3. Message a modelノードが以下の設定になっていることを確認する。このノードでは会議の文字起こしデータを分析して、顧客企業の要件をヘッダー内容として抽出する。ここでは高度な判断をする必要があるため、論理的思考が得意なChatGPT-4o miniのモデルを使用。システムプロンプトは顧客要件抽出アシスタントとしての役割を与え、ユーザープロンプトとして会議の文字起こしのテキストデータを入力する。また、後段で処理しやすいように、JSON形式のファイルとして出力するようにプロンプトに指示するとともに、Output Content as JSONの設定を有効にする。

5-4.Append row in sheetノードが以下の設定になっていることを確認する。このノードでは前段の ChatGPT の顧客企業の要件の抽出結果をCRMリストに記載する。Documentは作成したCRMリストを選択し、Sheetはヘッダーを記載したシートを選択する。Mapping Column ModはMap Each Column Manuallyを選択。
また4-5と同様に、スプレッドシートを読み込むとValue to Sendの部分にヘッダーが表示される。各ヘッダーに対応する変数(ファイルの作成日時や、顧客企業の要件など)を割り当てる。

5-5. Matching Configノードが以下の設定になっていることを確認する。このノードでは、マッチングする際の重要視する項目の重み付けを変更する。具体的にはスキル、予算・期間、地域、実績の項目を設定。

5-6. Get row(s) in sheetノードが以下の設定になっていることを確認する。このノードでは、CRMリストに登録されたパートナー企業の一覧とその特徴を取得する。Documentは作成したCRMリストとし、Sheetはパートナー企業の特徴が入力されたシートを選択。

5-7. Loop Over Itemsノードが以下の設定になっていることを確認する。このノードでは、前段で取得したパートナー企業一覧から、一つ一つの企業を取り出してマッチングの処理を行うための繰り返し処理を実施。、すべてのパートナー企業との処理が完了したら通知用の経路に分岐する。

5-8. Message a modelノードが以下の設定になっていることを確認する。このノードでは、顧客とパートナーのマッチングを行いスコアリングをする。繰り返し処理する必要があるので、コストパフォーマンスのよいGemini 2.5 Flashのモデルを使用。プロンプトは、システムプロンプトとして人材マッチング評価AIの役割を与え、評価基準と、前段で定義したスコアリングの重み付けの変数を設定する。ユーザープロンプトでは、前段で抽出された顧客要件とスプレッドシートから取り出されたパートナー企業の特徴を入力する。最終的にスコアリング結果と評価のサマリーを出力する。また、後段で処理しやすいように、JSON形式のファイルとして出力するようにプロンプトに指示するとともに、Output Content as JSONの設定を有効にする。

5-9. Aggregate Resultsノードが以下の設定になっていることを確認する。このノードでは、全パートナー企業のマッチングのスコアリング結果をソートして集約する。さらに、企業の中で上位3社を抽出して出力する。

5-10. Format Slack Messageノードが以下の設定になっていることを確認する。このノードでは、マッチング結果のSlack通知用メッセージを作成する。抽出した上位3社のパートナー企業についての評価結果をSlack投稿ように整形する。

5-11. Slackノードが以下の設定になっていることを確認する。このノードでは、マッチング結果をSlackでユーザーに通知する。Channelは通知をしたいチャネルに設定する。

よくある質問

Google Meet の 文字起こし結果(docx) が出力されないのですが?

Google Workspace アカウントで録画を行い、文字起こしを「自動生成ON」にしておく必要があります。

文字起こし結果(docx) が処理されません。

会議名に「ai on」というキーワードを設定する必要があります。

AI の回答がJSON形式になりません。

プロンプトに「必ず JSON で返す」指示を追加し、構造の例を提示することで改善します。

つまずきやすいポイント

  • Google Drive の権限設定不足で、録画ファイルが取得できない。
  • AI出力がJSONとして壊れ、後続ノードがエラーになる。
  • Google Sheets の列構造が記事内サンプルと異なり、値が正しく入らない。

なかなかうまくいかないときは?

Slack通知が来ない、docxがうまく処理されない、AI出力が安定しない──そんなトラブルはよくあります。

そこで、おすすめしたいのが「ジドウカ」です。

ジドウカは、これまで合計800タスク以上の業務の自動化をしてきた実績のある法人専用の自動化サービスです。

業務の一部を“タスク単位”で自動化し、【月額1万円から】安定運用できるサブスクリプション型のサービスです。技術のことが分からなくても「こういう作業をラクにしたい」と伝えるだけで自動化することが可能です。

「自分のやりたい自動化って本当に実現できるのかな…」という方には、少額・短期間での「お試し開発」があるので、お気軽にご活用ください。

まとめ

今回は「Google Meet録画 → AI要約 → CRM入力 → パートナーマッチング → Slack通知」という一連の自動化を紹介しました。

AI × ノーコードツールの組み合わせは、あなたの業務を「自走する仕組み」に変える強力な武器になります。ぜひこの記事を参考に、自社の自動化を前に進めてください。

目次