Claude CodeでLINE Botの作り方 — Webhook受信からSDK応答まで
Claude Codeを使い、LINE Messaging APIのWebhook受信からSDKでの応答実装まで、LINE Botを一気通貫で作る手順です。
LINE Botのしくみと今回作るもの
LINE Messaging APIのbotは、ユーザーがLINE公式アカウントにメッセージを送ると、LINEプラットフォームがWebhookイベントをbotサーバーのWebhook URLへPOSTし、botサーバーがその内容を確認してLINEプラットフォーム経由でユーザーに応答する、という一方向の流れで動きます。通信はすべてHTTPS上のJSONです。
本記事では、この流れを実装するNode.js製のWebhookサーバーを、Claude Codeにコードを書かせながら組み立てます。完成品は、ユーザーが送ったテキストをそのまま返す最小構成のオウム返しbotです。仕組みが分かれば、返信ロジックだけ差し替えて実用botに発展させられます。
Messaging API自体は無料で始められ、公式アカウントの料金プランに応じた月間の無料メッセージ数の範囲内であれば費用はかかりません。
前提条件
- Node.js 22以上、npm(できれば10以上) — LINE公式のNode.js SDK(
@line/bot-sdk)がES2022を使う実装のため必須 - Claude Codeのセットアップ済み環境
- ローカル開発用のHTTPSトンネル(
ngrokなど) — Webhook URLはHTTPS必須で、LINE公式のWebhookガイドも開発・テスト用途にはngrokを勧めています - LINE公式アカウントとMessaging APIチャンネル(作成手順は次章)
Node.jsのバージョンはnode -vで確認できます。Claude Code自体のインストール方法(ネイティブインストーラーかnpmか)によって必要なNode.jsバージョンが変わる点は、Claude CodeにNode.jsは必要かで扱っている内容とは別軸です。今回必要なのは、あくまで@line/bot-sdkを動かすランタイム側のバージョンです。
手順1: LINE Official AccountとMessaging APIチャンネルを作る
Messaging APIを使うには、まずチャンネルが必要です。チャンネルの作成はLINE Developers Consoleからではなく、次の2段階で行います。
- LINE Official Accountを作る: Business IDに登録し、表示される申込フォームに必要事項を入力すると、LINE Official Accountが作成されます。作成済みのアカウントはLINE Official Account Managerで確認できます。
- Messaging APIを有効化する: LINE Official Account ManagerからMessaging APIの利用を有効化すると、そのアカウントに紐づくMessaging APIチャンネルが作られます。LINE Official Account Managerでのログインに使ったアカウントでLINE Developers Consoleにログインし、プロバイダー配下にチャンネルが作成されていることを確認します。
チャンネルができたら、Developers Consoleのチャンネル設定画面でMessaging APIタブを開き、チャンネルシークレットとチャンネルアクセストークンを控えます。この2つが、この後のコードで使う認証情報です。
手順2: プロジェクトをClaude Codeで初期化する
作業ディレクトリを作り、Claude Codeに「Expressと @line/bot-sdkを使ったLINE Botのプロジェクトを初期化して」と指示すると、package.json の作成からパッケージインストールまで一括で進められます。LINE公式のNode.js SDKはnpmで配布されています。
mkdir claude-line-bot && cd claude-line-bot
npm init -y
npm install express @line/bot-sdk
npm install -D typescript @types/node @types/express tsx.env にチャンネルシークレットとアクセストークンを保存します(Claude Codeに .gitignore へ .env を追記させておくと安全です)。
CHANNEL_SECRET=手順1で控えたチャンネルシークレット
CHANNEL_ACCESS_TOKEN=手順1で控えたチャンネルアクセストークン
PORT=3000手順3: Webhookサーバーの実装をClaude Codeに書かせる
@line/bot-sdk は、署名検証とWebhookイベントのパースをまとめて行うmiddleware()を提供します。Claude Codeに「middleware() を使ったExpressのWebhookエンドポイントを書いて」と依頼すると、次のような実装が得られます。
import "dotenv/config";
import express from "express";
import { middleware, LineBotClient } from "@line/bot-sdk";
const config = {
channelSecret: process.env.CHANNEL_SECRET!,
};
const client = LineBotClient.fromChannelAccessToken({
channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN!,
});
const app = express();
app.post("/webhook", middleware(config), (req, res) => {
Promise.all(req.body.events.map(handleEvent))
.then((result) => res.json(result))
.catch((err) => {
console.error(err);
res.status(500).end();
});
});
function handleEvent(event: any) {
if (event.type !== "message" || event.message.type !== "text") {
return Promise.resolve(null);
}
return client.replyMessage({
replyToken: event.replyToken,
messages: [{ type: "text", text: event.message.text }],
});
}
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`listening on ${port}`);
});ここでのポイントは2つです。
middleware()は/webhookルート専用に登録する。全ルートにapp.use(middleware(config))を適用すると、X-Line-Signatureヘッダーを持たない通常のリクエストで例外が発生します- 他のbody-parserを
middleware()より先に登録しない。署名検証にはリクエストの生のボディが必要で、別のparserが先にボディを消費すると検証に失敗します
Claude Codeにこの2点を制約として伝えておくと、生成されるコードの順序ミスを避けやすくなります。
手順4: ローカルで動作確認する
Webhook URLはHTTPSである必要があります。ローカル開発ではngrokでトンネルを張り、一時的なHTTPS URLを発行するのがLINE公式ガイドの推奨する方法です。
npx tsx src/server.ts別ターミナルで:
ngrok http 3000発行された https://xxxx.ngrok-free.app/webhook を、Developers ConsoleのMessaging APIタブにあるWebhook URL欄に登録し、「Use webhook」を有効にします。この設定はWebhookの再送(redelivery)を有効化する際の操作としても公式ガイドに記載されている、チャンネル設定画面 → Messaging APIタブ上の項目です。
LINEアプリから公式アカウントにテキストを送り、同じ文言がオウム返しで返ってくれば疎通は成功です。
手順5: エラーハンドリングを仕上げる
middleware() は2種類のエラーを投げます。署名が無い、または一致しない場合の SignatureValidationFailed と、リクエストボディがJSONとしてパースできない場合の JSONParseError です。Expressのエラーハンドリングミドルウェアで、この2つを区別して処理します。
import { middleware, JSONParseError, SignatureValidationFailed } from "@line/bot-sdk";
app.use(
(err: unknown, req: express.Request, res: express.Response, next: express.NextFunction) => {
if (err instanceof SignatureValidationFailed) {
res.status(401).send(err.signature);
return;
}
if (err instanceof JSONParseError) {
res.status(400).send(err.raw);
return;
}
next(err);
}
);送信側(client.replyMessage() / client.pushMessage())のエラーは HTTPFetchError としてスローされ、status / headers / body を持ちます。Claude Codeに「LINE APIのエラーレスポンスをログに残すcatch節を追加して」と頼めば、このプロパティを使ったログ出力を足してくれます。
reply messageとpush messageの使い分け
LINE Messaging APIには複数のメッセージ送信方法がありますが、bot開発でまず使うのはこの2つです。
| 送信方法 | 使うタイミング | 制約 |
|---|---|---|
| reply message | 使うタイミングユーザーのメッセージやアクションへの応答 | 制約WebhookイベントのreplyTokenが必要。1リクエストで最大5件 |
| push message | 使うタイミングユーザーの操作を起点としない、任意タイミングの送信(通知など) | 制約ユーザーIDをtoに指定。1リクエストで最大5件 |
オウム返しbotのようにユーザー発話への即時応答だけならreply messageで足ります。バッチ処理の結果通知など、ユーザーのアクションを起点としない配信にはpush messageを使います。
よくあるつまずき
SignatureValidationFailed が発生する
middleware() より前に express.json() などのbody-parserを挟んでいないか確認します。署名検証は生のリクエストボディを必要とするため、先にパースされると検証に失敗します。
Webhookからの応答が来ない
Webhook URLがHTTPSになっているか、Developers ConsoleでUse webhookが有効になっているかを確認します。ngrokの無料URLはセッションごとに変わるため、再起動時は登録し直す必要があります。
replyToken を使ったのに送れない
reply tokenには有効期限があり、既に使用済みのtokenやWebhook受信から時間が経ったtokenでは送信に失敗します。再送が必要な場合はpush messageに切り替えます。
Node.jsのバージョンが合わずSDKが動かない
@line/bot-sdk はNode.js 22以上を前提にしています。Claude Codeで開発環境を新規構築する際は、先にNode.jsのバージョンを確認しておくと手戻りを避けられます。
署名検証を自前実装しようとして詰まる
middleware() を使わずに validateSignature() を手動で呼ぶ構成は、Firebase Cloud Functionsのようにリクエストボディが事前にパースされる環境向けの例外的な選択肢です。通常のExpress構成では middleware() に任せるほうがシンプルです。
まとめ
LINE Botの実装は、チャンネル作成(LINE Official Account Manager経由)、Webhook受信(middleware()による署名検証)、応答送信(LineBotClientのreplyMessage/pushMessage)の3段階に分けると見通しが立てやすくなります。Claude Codeには各段階のコードを個別に指示しながら、署名検証の順序やHTTPS化といった制約を伝えることで、公式ドキュメントの実装パターンに沿ったコードを組み立てられます。
Slack向けに同じ発想でbotを作る場合は、Anthropic Agent SDKでSlack常駐botを作る記事も参考になります。