Voiceflow Captureブロック(聴話)→APIブロックでTranscriptをLambdaに送り→SESメール送信

1.SESでメール(ID)登録

SESで「IDの作成」にて「Eメールアドレス」でIDを1個作成します。

2.Lambda関数作成

以下のようなVPCの外のLambdaでVoiceflowからのトランスクリプトを受け取ってSESでメールします。

ランタイム:Node.js 22.x

import { SESClient, SendEmailCommand } from "@aws-sdk/client-ses";

// SESクライアント初期化
const ses = new SESClient({ region: "ap-northeast-1" });

// メール設定
const SENDER = "SESで登録したメアド";      // ID登録検証済み送信者
const RECIPIENT = "SESで登録したメアド";      // 受信者

export const handler = async (event) => {
  try {
    // API Gateway プロキシ統合の場合、bodyは文字列
    const body = JSON.parse(event.body || '{}');
    const transcript01 = body.transcript01 || "トランスクリプト未取得";
    
    // Voiceflow Dev/APIブロックに持たせた APIキーの確認
    const apiKey = event.headers['x-api-key'] || event.headers['X-API-Key'];
    console.log('API Key received:', apiKey ? 'Yes' : 'No');
    
    // メールパラメータ
    const emailParams = {
      Destination: {
        ToAddresses: [RECIPIENT]
      },
      Message: {
        Subject: {
          Data: "Voiceflowから新しいトランスクリプトを受信"
        },
        Body: {
          Text: {
            Data: `以下のトランスクリプトをVoiceflowから受信しました:\n\n${transcript01}\n\n受信時刻: ${new Date().toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' })}`
          },
          Html: {
            Data: `
              <h3>Voiceflowトランスクリプト</h3>
              <p><strong>内容:</strong></p>
              <p>${transcript01}</p>
              <hr>
              <p><small>受信時刻: ${new Date().toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' })}</small></p>
            `
          }
        }
      },
      Source: SENDER
    };
    
    // SESでメール送信
    const command = new SendEmailCommand(emailParams);
    await ses.send(command);
    
    // 成功レスポンス
    return {
      statusCode: 200,
      headers: {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      },
      body: JSON.stringify({
        message: "トランスクリプトを正常に受信し、メールを送信しました",
        transcript01: transcript01
      })
    };
    
  } catch (error) {
    console.error("Error:", error);
    
    // エラーレスポンス
    return {
      statusCode: 500,
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        error: "処理中にエラーが発生しました",
        message: error.message
      })
    };
  }
};

LambdaのIAMロールに追加したSES向けIAMポリシー

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "voiceflowcapturatest",
            "Effect": "Allow",
            "Action": [
                "ses:SendRawEmail",
                "ses:SendEmail"
            ],
            "Resource": "arn:aws:ses:ap-northeast-1:<AWSアカウントID>:identity/<ID登録したメールアドレス>"
        }
    ]
}

3.API Gateway 作成

  1. APIキー作成
  2. 使用料プラン作成(念のため、絞っておきます)
    • スロットリング (オン)
      • レート : 5
      • バースト:10
    • クォータ
      • リクエスト:100 
        • 1日あたり
  3. 関連付けられたAPIキーで 1. のAPIキーを追加する
  4. REST API→新しいAPI→API名(voiceflow-capture-test-apigt)→APIを作成
  5. POSTリクエスト送信先となるリソースを作成する
    • リソースを作成→リソース名(test-resource)
    • 作られた「/test-resouce」が選択されている状態で、「メソッドを作成」→メソッドタイプ「POST」→統合タイプ「Lambda関数」→2.で作ったLambdaを選択→「API キーは必須です」にチェックを入れる→「メソッドを作成」
    • 「POST」→統合リクエスト→Lambda プロキシ統合→「True」に変える
    • CORS対応。「/test-resouce」が選択されている状態で、「メソッドを作成」→メソッドタイプ「OPTIONS」→統合タイプ「Mock」→2.で作ったLambdaを選択→「メソッドを作成」
      • 「OPTIONS」が選択されている状態で、「メソッドレスポンス」の「編集」→レスポンスヘッダーに以下3種のヘッダーを追加→保存
        • Access-Control-Allow-Origin
        • Access-Control-Allow-Methods
        • Access-Control-Allow-Headers
      • 「統合レスポンス」の「編集」→「ヘッダーのマッピング」の「レスポンスヘッダー
        」で以下のように、マッピング値を設定
        • Access-Control-Allow-Headers→'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'
        • Access-Control-Allow-Methods→'OPTIONS,POST'
        • Access-Control-Allow-Origin→'*'
  6. APIをデプロイ→新しいステージ(ステージ名:dev)→「デプロイ」
  7. 使用料プラン→3-2.で作成した使用料プランを選択→APIステージを追加→API(voiceflow-capture-test-apigt を選択)→ステージ(dev を選択)→「使用料プランに追加」
    (API gatewayとAPIキーがここで紐付きます)

4.VoiceflowでProjectを作成

  1. Messageブロックで何か質問しておく
  2. Listen/Captureブロックを設置→「Save entire reply to...」で「Create variable」にて発話を格納する変数名を任意で入力 EX)reply_capture
    • MessageブロックからListen/Captureブロックまで矢印でつなぐ
  3. reply_capture 変数をAPI GatewayにPOSTリクエストするため、Dev/APIブロックを設置
    • 「POST」を選び、API Gatewayで「ステージ」のPOSTにて「URLを呼び出す」に記載されているURLを選んだPOSTの下に貼り付け
    • Listen/CaptureブロックからDev/APIブロックまで矢印で結ぶ
  4. Headersへ次の二点を入力
    • Header:Content-Type、Value:application/json
    • Header:x-api-key、Value:「3-1で作ったAPIキー」
  5. Bodyへの入力
    • Raw
    • JSON
    • {"transcript01": "{reply_capture}"}

5.Voiceflowで会話開始

4-1のMessageブロックの質問に返事をした発声が、SESメールで届きます。

音声会話は、Voiceflowのproject作成フローキャンバス画面で音声確認する にてやり方を確認できます

参考 API GatewayへのCURLのPOST

うまくいかない場合、下記のcurlによる検証が可能です。

curl -X POST <「URLを呼び出す」に記載されているURL> -H "Content-Type: application/json" -H "x-api-key: <3-1で作ったAPIキー>" -d '{"transcript01": "test message2"}'