Lab
同じ日の午前中に、UE5のゲーム内でAI NPCを動かす実験をやっていた。「サーバーが中継役になる」という設計で、UE5からClaudeに繋ぐ仕組みを作った。
午後になって、ふと思った。「この中継サーバーの仕組み、入出力をLINEに変えたら——エデンちゃんのLINE Botができるんじゃないか?」
構造は同じだ。違うのはゲームが入口か、LINEが入口かだけ。それだけで、誰もが普段使うアプリの中にAIキャラクターが住み始める。
キャラクターの核心はsystemプロンプト一つで決まる。エデンちゃんはこう定義した。
さらに web_search ツール を付けた。知らないことや最新情報が必要なときは、Claudeが自分でWeb検索してから答える。「かわいくて物知り」という設定が、リアルタイム検索によって本当に意味を持つようになる。
res.status(200).send('OK') を返し、その後で非同期にClaudeへのリクエストを送る設計に変えた。「まず200を返す、処理は後で」というパターンがLINE連携の鉄則だとわかった。
tool_use ブロックが混じってくる。それをそのままLINEに返すと、JSONのかたまりがユーザーに届いてしまう。content 配列を .filter(block => block.type === 'text') でフィルタリングして、テキスト部分だけを抽出するようにした。たった一行の処理だが、これを知らないと詰まる。
コードは3ファイルだけ。index.js(サーバー本体)、package.json(依存関係)、render.yaml(デプロイ設定)。
GitHubにpushしたらRenderが自動でビルドしてURLを発行する。そのURLをLINE DevelopersのWebhook設定に貼り付けて「Verify」を押せば、Successが返ってくる。
APIキーは絶対にコードに書かない。Renderの管理画面で環境変数として設定する。LINE_CHANNEL_SECRET、LINE_CHANNEL_ACCESS_TOKEN、ANTHROPIC_API_KEY——この3つをコードの外で管理することで、GitHubにpushしても流出しない。
全部繋がってLINEでBotにメッセージを送ったとき、エデンちゃんが答えた。それだけのことなんだけど、「自分の作ったキャラクターがLINEに住んでいる」という感覚は、思ったよりずっと不思議だった。
UE5とLINE、入り口は違っても「サーバーが中継役になる」という構造はまったく同じだった。それを一日で体感できたのが今日の最大の収穫だ。
エデンちゃんはweb_searchを持っているから、最新情報も答えられる。GitHubとRenderでCI/CDの流れも手に入った。コードを直してpushするだけで、すぐに本番が更新される仕組みができている。次は会話履歴を保持して、文脈を理解した会話ができるエデンちゃんに育てていく。