Twilio Functionsで作る：SMS放置→自動電話催促の動作イメージデモ

## はじめに
こんにちは。
今回は **「SMS通知の無視を検知して自動で電話催促を行う」** というユースケースをデモで表現するために作ったコードをご紹介します。

システムからメールを送ってもユーザーが反応してくれないので、SMSを送ってますが
それでも反応してもらえないという嘆きの声をよく聞きます。
そのような方のために、このデモでは、次のような流れをイメージしてTwilioの有用性を示しています。

1. **SMSで通知を送信**  
2. **一定時間、相手が対応しなければ**  
3. **自動で電話をかけ、内容を音声で再通知**  

**放置 → 電話催促** という行動トリガーを視覚化し、  
サーバーレス（Twilio Functions & Assets）で構築したシンプルな例です。
あくまでもデモ用なので、「通知の無視を検知して自動で」の部分は実装されていません。
実装方法は色々ありますが、TwilioのSMSとVoiceの機能を見て頂くためのデモプログラムになっています。
私がお客様に対してデモを行うときに使用するツールという立ち位置なので、自動化せず手動でSMS・Voiceの発信を行うような仕様に敢えてしています。

完成したコードはこちら：  
[GitHubリポジトリ：sms-to-call-demo](https://github.com/MitsuharuNakamura/sms-to-call-demo)

### このデモコードの目指したポイント
- 視覚的なわかりやすさ
- Twilio APIの容易さ
- ユースケースのイメージが持ちやすい
- Twilioで完結できる（画面・バックエンド）

---

## アーキテクチャの概要

### 動作の流れ

1. **管理者（またはシステム）からユーザーにSMS通知を送信**  
2. **ユーザーにSMSが届く**  
    - ※ 今回のデモでは、**ユーザーが対応したかどうかに関わらず「未対応」とみなして次に進みます**。
3. **一定時間後、Twilio Functionsがトリガーされ自動で電話を発信**  
    - ※ 今回のデモでは、ボタンでコールボタンを押す形式にしています。 
4. **Twilioの音声通話でメッセージを読み上げ、ユーザーに催促**

### ポイント

「SMS → 無視 → 自動通話」の流れを**シンプルなロジック**で再現し、  
本番環境では「対応検知（例：返信SMSやリンククリック）」などを加えることでさらに高度化できます。

---

## コードと構成

今回のデモは **Twilio Functions & Assets** だけで構築しています。  
外部サーバーやデータベースは使用せず、**サーバーレスで完結**するシンプルな構成です。

### Functionsの構成

| Function名 | 役割 |
|------------|------|
| `/send_sms` | ユーザーにSMSを送信 |
| `/make_call` | 自動で電話を発信し、TTSでメッセージを読み上げ |

### 主なコードの抜粋と解説

#### 1. SMS送信（/send_sms）

```javascript
exports.handler = async function(context, event, callback) {
    const client = require('twilio')(context.ACCOUNT_SID, context.AUTH_TOKEN);
  
    const { to, smsBody } = event;
  
    try {
      const message = await client.messages.create({
        to: to,
        from: "TWILIODEMO",
        body: smsBody,
      });
      return callback(null, { sid: message.sid });
    } catch (error) {
      return callback(error);
    }
};  
```

**ポイント**：
- `event.to` と `event.smsBody` を受け取り、指定の宛先にSMSを送信。

#### 2. 自動通話（/make_call）

```javascript
exports.handler = async function(context, event, callback) {
    const client = require('twilio')(context.ACCOUNT_SID, context.AUTH_TOKEN);
    const { to, voiceMessage } = event;
    const twiml = `
      <Response>
        <Say language="ja-JP" voice="alice">
          ${voiceMessage}
        </Say>
      </Response>
    `;
    try {
      const call = await client.calls.create({
        to: to,
        from: context.CALLER_ID,
        twiml: twiml
      });
      return callback(null, { callSid: call.sid });
    } catch (error) {
      return callback(error);
    }
  };
```

**ポイント**：
- 指定の宛先に音声通話を発信。
- **TTS（Text to Speech）**で`voiceMessage`の内容を読み上げ。
- TwiMLをコード内に直接埋め込んでいるため、**別途TwiML BinやURLの用意が不要**。

### 環境変数（Environment Variables）

| 環境変数 | 説明 |
|----------|------|
| TWILIO_PHONE_NUMBER | 発信元のTwilio電話番号 |

---

## 開発時の工夫とポイント

### 1. Functionsだけで完結

私は、Twilioのプリセールスエンジニアなので、最大限Twilioの機能だけで実装することが最適です。
通常、SMSや通話のトリガー処理はバックエンドサーバーやデータベースと連携するケースが多いですが、  
今回は **Twilio Functions & Assetsだけ** で完結させました。

これにより：

- 外部サーバーの準備や運用が不要
- コストが最小限（Twilioの利用料のみ）
- デプロイや修正が圧倒的にシンプル

### 2. TwiMLをコード内に直接記述

```javascript
twiml: `<Response><Say language="ja-JP" voice="alice">${voiceMessage}</Say>`
```

**TwiML Bin** や **外部Webhook** の準備が不要になり、構成がシンプルになりました。

### 3. 今後の拡張も容易

今回は「必ず電話催促に進む」という簡易ロジックですが、  
次のような拡張も想定しています：

- SMS内に「URLリンク」を含め、クリックを検知して通話をスキップ
- 送信されたSMSに対して返信されなかったものに対してオートコールする
- 音声合成（TTS）の音声や言語をカスタマイズ

**最低限の構成**でスタートし、必要に応じて機能を追加できるのがサーバーレス設計の強みです。

---

## ユースケース例

今回の仕組みは、さまざまなシーンで活用できます。

- **ビジネスアラート通知**：重要な業務アラートをSMS＋自動電話で確実に伝達
- **家族見守り通知**：SMSでの注意喚起に反応がない場合に音声で再通知
- **業務リマインダー**：タスクや予定のリマインダーをSMSと音声の両方で送信
- **督促通知**：支払いリマインダーや契約更新の通知をフォローアップ


---
## 誰におすすめ？
### このデモはこんな方におすすめ
- 顧客対応やリマインダーの自動化を考えているエンジニア
- TwilioのSMS・Voice機能をこれから学びたい方
- サーバーレス開発を実践したい方
---

## まとめ

今回は **「SMS通知→無視→自動通話」** という行動トリガーの自動化を、  
**Twilio Functions & Assetsだけ** で実現する方法を紹介しました。

コード全文とデプロイ手順はGitHubにて公開しています：  
[GitHubリポジトリ：sms-to-call-demo](https://github.com/MitsuharuNakamura/sms-to-call-demo)

**今後の発展**として、ユーザー対応の検知や、応答に応じた柔軟なフロー設計など、さらに高度なユースケースに応用可能です。

ぜひ皆さんもTwilio APIを使った開発を楽しんでみてください！