この記事について
この記事の内容は、人間と Claude Code とのセッションで共同開発及び執筆しました。仕様の方針検討や選択は人間が、実装にあたっての技術検証と仕様のまとめを AI が担当しています。

1. はじめに

この記事は 構築編 の続編で、システムの技術的な背景と設計上の判断をまとめている。環境構築の手順については構築編を参照してほしい。

扱う内容は以下のとおり。

  • 2. 構成要素の解説 — 技術スタック・リクエストフロー・ファイル構成・主要な設計ポイント
  • 3. 比較検討したこと — Cloudflare Workers を採用した理由・実装言語の選定・セキュリティ手法の比較
  • 4. 参考 — 参考リンク

2. 構成要素の解説

2-1. 技術スタック

コンポーネント 技術・サービス 役割
音声 I/F Amazon Echo / Alexa Skills Kit 音声入出力・カスタムスキル管理
バックエンド Cloudflare Workers Alexa からのリクエストを受ける HTTPS エンドポイント
実装言語 TypeScript Workers のコード記述(V8 ネイティブ実行)
開発・デプロイ Wrangler CLI ローカル開発・デプロイ・シークレット管理
AI Anthropic API (Claude Haiku) 自然言語での質問応答を生成

2-2. リクエストフロー

Sequence Diagram User Amazon Echo Alexa Skills Kit Cloudflare Workers Anthropic API AI Processing Voice Input Speech Recognition HTTPS POST API Request AI Response JSON Response TTS Conversion Voice Output

図中の TTS Conversion (Text-to-Speech) は、Alexa Skills Kit がテキスト形式のレスポンスを受け取り、Echo デバイスが再生できる音声データに変換するステップ。ユーザーが Echo から聞く読み上げ音声はここで生成される。

2-3. ファイル構成

alexa-claude/
└── worker/
    └── alexa-claude-worker/
        ├── src/
        │   └── index.ts        ← Worker のメインコード
        ├── wrangler.jsonc       ← Wrangler 設定(ALEXA_APP_ID を記入する)
        ├── tsconfig.json
        ├── worker-configuration.d.ts
        ├── package.json
        ├── .dev.vars           ← ローカル用シークレット(git 除外)
        └── .gitignore

2-4. 主要な設計ポイント

Alexa の 8 秒タイムアウト対策

Alexa はエンドポイントから 8 秒以内にレスポンスが返らない場合、タイムアウトエラーをユーザーに返す。Anthropic API の応答は通常 2〜5 秒だが、余裕を持たせるために 6 秒でキャンセルし、残り 2 秒でエラーメッセージを返す設計にしている。

Timeout Timeline Alexa 8-Second Timeout Workers Waiting Error Response Cancel API Call Response Anthropic API Claude Response (2–5s) 0s 2s 4s 6s 8s Waiting for Anthropic API 2s buffer
なぜ 8 秒なのか

Alexa Skills Kit のドキュメントには「8 秒以内に応答しなければならない」と明記されているが、なぜ 8 秒なのかという設計根拠を Amazon が公式に説明した資料は見当たらない。

断片的な情報として、Amazon 自身の開発者向けドキュメントには「ユーザーは 2 秒未満のレスポンスを期待している」という記述がある(参考)。8 秒はあくまで上限であって、Amazon にとっても目標値ではないようだ。

UX 分野では「応答が 10 秒を超えるとユーザーの集中が途切れる」という知見(NN/g)が古くから知られており、8 秒はそのギリギリ内側に収まる数字ではある。しかしこれが Alexa の設計に影響したかどうかは確認できていない。

公式な根拠は見つけられなかったが、現場の開発者からは「IoT 用途では 8 秒では足りない」という要望が継続的に上がっており(UserVoice)、この制限が開発上の実質的な壁になっていることは確かだ。

Cloudflare Workers 無料枠と CPU 時間

Workers の無料枠は 1 リクエストあたり CPU 時間 10ms という制限があるが、fetch() による外部 API 呼び出しの待機時間(I/O)は CPU 時間にカウントされない。このシステムの実質的な CPU 使用は JSON の解析と組み立てのみで、1 リクエストあたり約 1ms 以下に収まる。

セキュリティ

開発者モード(自分のみ利用)かつ URL を公開しない前提で、以下の 2 層を実装している。

検証 内容
アプリケーション ID 検証 ALEXA_APP_ID と一致するか確認
タイムスタンプ検証 150 秒以内のリクエストのみ受け付ける

会話履歴の保持

直近 5 往復(10 メッセージ)を Alexa セッションの属性(SessionAttributes)に保持し、Anthropic API へのリクエストに含めて渡す。セッションを終了すると履歴はリセットされる。

Session History Sliding Window = 1 Q+A exchange (stored in SessionAttributes) Turn 1 1 > Claude API Turn 2 1 2 > Claude API Turn 3 1 2 3 > Claude API Turn 4 1 2 3 4 > Claude API Turn 5 1 2 3 4 5 (full) > Claude API Turn 6 1 Dropped 2 3 4 5 6 > Claude API Session ends → all history cleared

3. 比較検討したこと

3-1. Alexa-hosted ではなく Cloudflare Workers を採用した理由

Alexa カスタムスキルのバックエンドは、Amazon が管理する Alexa-hosted (Node.js) と、自分で用意する カスタムエンドポイント(Lambda・Cloudflare Workers など)の2種類から選べる。Alexa Developer Console では Alexa-hosted の導入が手軽だが、今回はコールドスタートの問題から採用しなかった。以下に比較をまとめる。

Alexa-hosted (Node.js) Cloudflare Workers
動作環境 Amazon 管理の AWS Lambda V8 アイソレート
セットアップ 不要(Console のみ) Wrangler + アカウント設定が必要
コールドスタート 1〜3 秒 約 5ms(概念なし)
個人利用時の起動頻度 低頻度 → アイドル状態になりやすい 常時ウォーム
Claude API 応答(2〜5 秒)との合算 8 秒制限を超えるリスクあり 余裕あり
結果 不採用 採用
AWS Lambda とは
Amazon が提供するサーバーレス実行環境。リクエストがない間はコンテナが停止しており、次のリクエスト時にコンテナを起動するコールドスタートが発生する。個人利用のように低頻度のアクセスが続くと、常にアイドル状態に戻るためほぼ毎回コールドスタートになる。
V8 アイソレートとは
V8 は Google が開発した JavaScript エンジンで、Chrome や Node.js でも使われている。アイソレート (Isolate) はその実行コンテキストの単位。Cloudflare Workers は各スクリプトをアイソレートとして実行するため、コンテナや VM のようなプロセス起動が不要で、起動オーバーヘッドが数 ms 以下に収まる。
Cold Start Comparison: Lambda vs Cloudflare Workers Alexa-hosted AWS Lambda Cold Start 1–3s Claude API 2–5s ⚠ At risk Cloudflare Workers V8 Isolate ~5ms Claude API 2–5s ✓ Safe 8s Timeout 0s 2s 4s 6s 8s 10s ~ 3s headroom (worst case)

3-2. Cloudflare Workers の実装言語の選定

Cloudflare Workers は複数の言語をサポートしているが、TypeScript(JavaScript)を採用した。

言語 実行方式 コールドスタート I/O 処理 評価
TypeScript V8 ネイティブ 約 5ms 最小 採用
Rust / Go / C WASM 5〜50ms 中(マーシャリング) 不適
Python (Pyodide) WASM 1 秒以上 不適

Python は Pyodide の初期化だけで 1 秒以上かかり、Alexa の 8 秒制限に対して現実的でない。Rust・Go などの WASM 言語は V8 環境とのメモリ空間が分離されているため、マーシャリングが発生し、今回のような I/O 中心のワークロードでは逆に遅くなる。

マーシャリング (Marshalling) とは
WASM モジュールは V8 の JavaScript ヒープとは独立したメモリ空間を持つ。JS 側から WASM 関数にデータを渡す際、値をシリアライズして別のメモリ空間にコピーする処理が必要で、これをマーシャリングと呼ぶ。JSON のやり取りが主な処理となる今回のシステムでは、このコピーコストが無視できないオーバーヘッドになる。
Cold Start Time Comparison by Language TypeScript V8 Native ~ 5ms ✓ Adopted Rust / Go / C WASM 5 – 50ms + marshalling overhead Python Pyodide / WASM ≥ 1,000ms * Bar lengths are illustrative. Python cold start (≥1,000ms) is ~200× TypeScript (~5ms).

3-3. セキュリティ手法の比較

今回のスキルの実装では Cloudflare Workers の *.workers.dev ドメインにデプロイしている。

*.workers.dev とは
Cloudflare Workers をデプロイすると、<スクリプト名>.<アカウント名>.workers.dev という形式の URL が自動で割り当てられる。独自ドメインを持っていなくても即座に HTTPS エンドポイントとして使うことができる。ただし、Cloudflare の一部機能は独自ドメインでしか使えない。

今回はドメイン取得・維持費用を発生させずに動作させることを目標としているため、独自ドメインの取得が前提となる手法は除外している。その条件のもとで適用できる追加のセキュリティ手法を検討した。

手法 効果 欠点 結果
Cloudflare WAF(ASN フィルター) URL 漏洩を実質無効化 独自ドメインが必要。*.workers.dev には不可 不採用
Cloudflare Rate Limiting クレジット過剰消費を防止 独自ドメインが必要。*.workers.dev には不可 不採用
Alexa リクエスト署名検証 Amazon からのリクエストを暗号学的に証明 実装コスト高・レイテンシへの影響あり 不採用

いずれも今回の環境・用途には合わず不採用とした。個人・非公開利用であれば、2-4 節で実装したアプリケーション ID + タイムスタンプ検証の2層で十分な防御が得られる。

独自ドメインを Cloudflare で管理している場合は、WAF・Rate Limiting をダッシュボードから追加してセキュリティをさらに強化できる。

4. 参考