Twilio Studio フロー内で Function を使わずに現在日時を取得できるか調べてみた
はじめに
Twilio Studio は、GUI 上で着信や SMS のフローを組み立てられる Twilio の機能です。IVR、コールトラッキング、SMS 自動応答など、ロジックを Twilio 内部に閉じ込めて運用したい場面で重宝します。このときフローの途中で「現在の日時」を取得して自前 API への Webhook 通知に含めたいというニーズがしばしば発生します。
素直に実装するなら Twilio Functions (Node.js を実行できるサーバーレス機能) を 1 つ用意し、new Date().toISOString() を返すだけで終わります。しかし「Function は使わずに Studio で完結させたい」という制約があるとき、Studio 標準のウィジェットだけで現在日時を取得できるかという点についてはどうでしょう。Studio で完結できれば、GUI 上の編集だけでフロー全体を保守できるため、非エンジニアの運用者にとっての負担を下げられます。
本記事では、Set Variables ウィジェットの Liquid テンプレートと、Twilio Studio が提供するコンテキスト変数の両方を網羅的に検証し、Function を使わずに現在日時を取得できる方法とその限界を明らかにします。
結論
結論を先に書くと以下の通りです。
-
現在日時の取得は Function を使わずに可能です。動作する構文は次の 1 つです。
{{ "now" | date: "%Y-%m-%d %H:%M:%S" }}
ただし、返却される時刻のタイムゾーンは PDT/PST (米国太平洋時間) 固定であり、Studio フロー内で UTC への変換やタイムゾーン付きの表記を出力する手段は今回試した範囲では見つかりませんでした。結果として、JST や UTC で時刻を扱いたい場合は、以下のいずれかの対応が必要です。
- 受信側のサーバーで時刻変換する
- 通話開始時刻と通話秒数の組み合わせで再計算する
- 最小限の Function を 1 つだけ許容する
検証環境
- Twilio Studio Flow (Widget 配置のみで構築、Function は未使用)
- Twilio REST API による Flow の作成・実行 (curl で直接呼び出し)
- 受信先: webhook.site の使い捨て URL
- 検証日: 2026 年 5 月
対象読者
- Twilio Studio で IVR やコールトラッキング系のフローを構築している、あるいは検討している方
- Twilio Function を使わずに Studio 単体で完結するフローを設計したい方
- Studio の Liquid テンプレートで取り扱える変数やフィルターの実体に興味がある方
- Webhook 通知に時刻情報を含める際のタイムゾーン処理で困っている方
参考
検証方法
検証は次の構成で実施しました。
Set Variables ウィジェットに複数の Liquid 構文を並べ、Make HTTP Request ウィジェットで webhook.site にまとめて POST します。
Flow 定義 JSON の Set Variables ウィジェット部分は次の形になります。
Set Variables ウィジェット定義 (一部抜粋)
{
"name": "set_now",
"type": "set-variables",
"transitions": [
{ "next": "send_http", "event": "next" }
],
"properties": {
"variables": [
{ "key": "now_a", "value": "{{ \"now\" | date: \"%Y-%m-%d %H:%M:%S\" }}" },
{ "key": "now_d_sanity", "value": "{{ flow.flow_sid }}" }
]
}
}
Make HTTP Request ウィジェットの Body では、各変数を {{flow.variables.now_a}} 形式で参照します。webhook.site で受け取ると、どの構文がどう評価されたかが POST Body の各キーの値として見えます。
Flow 構築後、Twilio REST API を curl で直接叩いて実行しました。
curl -s -X POST "https://studio.twilio.com/v2/Flows/${FLOW_SID}/Executions" \
-u "${SID}:${TOKEN}" \
--data-urlencode "To=+81**********" \
--data-urlencode "From=+1**********"
検証 1: Liquid の date フィルターで現在時刻を取りに行く
最初に試したのは、Liquid で標準的に使われる date フィルターに "now" 文字列を渡すパターンです。Shopify Liquid では {{ "now" | date: "..." }} で現在時刻を整形できることが知られているため、Twilio Studio でも同様に動くかを確認します。
| 変数 | Liquid 構文 | 返却値 | 評価 |
|---|---|---|---|
now_a |
{{ "now" | date: "%Y-%m-%d %H:%M:%S" }} |
2026-05-24 23:31:11 |
動作 |
now_b |
{{ 'now' | date: '%s' }} |
%s |
動作せず |
now_c |
{{ "now" | date_to_rfc3339 }} |
{{ "now" | date_to_rfc3339 }} |
動作せず |
now_d_sanity |
{{ flow.flow_sid }} |
FW... |
サニティチェック |
now_a が動作したことで、Function を使わずに Studio 単体で現在日時を取得できることが確認できました。%Y-%m-%d %H:%M:%S の strftime 書式は Twilio Studio の Liquid 実装でもサポートされていることがわかります。
一方、Unix epoch を得る %s 書式や、Shopify Liquid で利用できる date_to_rfc3339 フィルターは未対応でした。特に now_c は Liquid 全体がパースされずリテラルとしてそのまま返却されており、Twilio Studio の Liquid 実装がフィルター未対応時にフェイルセーフ的にリテラルを返す挙動もあわせてわかりました。
検証 2: タイムゾーン情報を扱う構文を探す
PDT のままでは JST や UTC で扱いたいユースケースで困るため、タイムゾーン情報を取得・変換する方法を探します。候補として次の 3 構文を試しました。
| 変数 | Liquid 構文 | 返却値 | 評価 |
|---|---|---|---|
now_e |
{{ "now" | date: "%Y-%m-%d %H:%M:%S %z" }} |
2026-05-24 23:31:11 %z |
時刻部分は動作するが %z はリテラル |
now_f |
{{ "now" | plus: 32400 | date: "%Y-%m-%d %H:%M:%S" }} |
{{ "now" | plus: 32400 | date: ... }} |
Liquid 全体がパース失敗 |
now_g |
{{ "now" | date: "%FT%T%:z" }} |
%FT%T%:z |
書式が一切解釈されない |
3 構文とも、タイムゾーン関連の試みは失敗しました。now_e では時刻自体は得られるものの、タイムゾーンオフセット (%z) の書式が解釈されずリテラル文字列としてそのまま埋め込まれています。now_f の plus フィルターは数値演算用であり、"now" という文字列に対して秒数加算を試みると Liquid 全体のパースが失敗するようです。now_g で試した %F (年月日) や %T (時分秒) や %:z (オフセット表記) は、いずれも Twilio の strftime 実装に含まれていません。
ここまでで、Liquid の date フィルターでタイムゾーン変換を行う手段はなさそうということがわかりました。
検証 3: Twilio コンテキスト変数に UTC 時刻が含まれていないか調べる
Liquid フィルターが NG なら、Twilio Studio が Flow Execution の文脈として提供しているコンテキスト変数に UTC 時刻が含まれていないかを次に確認します。Twilio Studio では flow.*、trigger.*、widgets.* の名前空間から様々なメタ情報が参照可能になっています。
| 変数 | Liquid 構文 | 返却値 | 評価 |
|---|---|---|---|
ctx_h_flow_sid |
{{ flow.sid }} |
Execution SID (FN...) |
時刻情報ではない |
ctx_i_flow_data |
{{ flow.data }} |
{} 空オブジェクト |
時刻情報を含まない |
ctx_j_trigger_request |
{{ trigger.request }} |
{from=..., parameters={}, to=...} |
時刻情報なし |
ctx_k_trigger_request_headers |
{{ trigger.request.headers }} |
空文字列 | アクセス不可 |
ctx_l_execution_date |
{{ flow.data.start_time }} |
空文字列 | キーが存在しない |
ctx_m_widgets_self |
{{ widgets.set_now }} |
空文字列 | 自分自身の Widget 出力には参照不可 |
flow.sid は Execution SID として正常に返却されるものの、時刻情報そのものではありません。trigger.request は REST API トリガーで渡したパラメータが取れますが、タイムスタンプは含まれません。flow.data は空オブジェクトとして返却され、ドキュメントを探した限りでは Execution 開始時刻に該当するキーは公開されていないようです。
結果として、Twilio コンテキスト変数にも UTC 時刻を取得する経路は存在しなさそうということがわかりました。
なぜタイムゾーン変換ができないのか
検証結果を踏まえて、Twilio Studio で時刻処理の自由度が低い理由を考察します。
Twilio Studio の Liquid 実装は、Shopify Liquid の標準的な機能のうちフィルターのサブセットのみを提供している模様です。date フィルターと strftime 書式の基本パターンはサポートされていますが、オフセット表記用の %z や ISO 8601 のショートカット書式 %F、%T、%:z は実装に含まれていません。また、Liquid の plus フィルターは Shopify では数値型に対する加算用に定義されており、"now" のような文字列に直接適用する用途は想定されていないため、Twilio 側も同じ振る舞いになります。
加えて、Twilio Studio の Flow Execution のコンテキスト変数は、トリガー時のパラメータや Widget の出力結果に閉じています。Flow Execution 全体のメタデータ (作成時刻など) は REST API 経由では date_created として取得できるものの、Flow 内の Liquid からは参照する手段が用意されていません。
これらがあわさり、「Studio フロー内で現在時刻を JST や UTC に変換する」という操作はサーバーサイドで一切処理できない構造になっていると考えられます。
実用上の選択肢
Studio フロー内でタイムゾーン変換ができない以上、時刻処理は Studio の外側で吸収する必要があります。実用上、次の 3 つの選択肢が考えられます。
-
Studio から PDT 表記のまま送信し、受信側サーバーで UTC や JST に変換する
受信側で固定オフセット +16 時間 (PDT 期間) または +17 時間 (PST 期間) を加算すれば JST が得られます。サマータイムを跨ぐ運用では、1 時間分のずれの取り扱いも考慮事項になります。 -
Studio から時刻を送らず、受信側サーバーで受信時刻を採用する
Studio フローから Webhook が発火された瞬間にサーバー側でnow()を取れば、Studio から送られる時刻と数百 ms から数秒の差で記録できます。終話日時の精度として秒単位の厳密さが不要であれば、タイムゾーン問題が完全に消える最も簡素な解決策です。 -
日時取得のためだけに最小限の Function を 1 つ用意する
次のような 3 行の Function を 1 つ置き、Studio フローから Run Function ウィジェット経由で呼ぶだけで UTC ISO 8601 形式の時刻が得られます。exports.handler = function(context, event, callback) { callback(null, { now: new Date().toISOString() }); };「Function を一切使いたくない」という強い要件がない限り、この方法は実装も保守もシンプルで、GUI 上の運用者にとっての負担も小さく抑えられます。業務ロジックを Function に書くことは避けつつ、「日時取得のためだけの極小 Function」は許容する、という線引きが現実的な落とし所になることが多いでしょう。
まとめ
Twilio Studio フロー内で Function を使わずに現在日時を取得できるか検証してみました。結論として、取得自体は {{ "now" | date: "%Y-%m-%d %H:%M:%S" }} で可能ですが、タイムゾーン情報の付与や変換は Studio 単体ではできないことがわかりました。これは Twilio Studio の Liquid 実装がフィルターのサブセットのみを提供しており、Flow Execution のメタデータも Liquid からは参照できない構造に由来すると考えられます。
実用上は、受信側で時刻変換するか、受信側の now() を採用するか、日時取得のための極小 Function を 1 つだけ許容するか、のいずれかを選ぶことになります。Studio フローを設計する際にタイムゾーンの取り扱いを決める参考にしていただければ幸いです。






