Next.js で Nylas Webhook を処理する
AIエージェントにメールが届きました。返信までの猶予はわずか10秒です。
Nylas Agent Accounts を使用している場合、message.created ウェブフックが即座にサーバーに送信されます。Next.js では、1つのルートファイルでこれを処理できます。
正しい実装方法を以下に示します。
チャレンジ・ハンドシェイク
ウェブフックを作成すると、Nylas は challenge パラメータを含む GET リクエストを送信します。レスポンスボディには、その値を正確に返す必要があります。
JSON は使用しないでください。引用符も追加しないでください。生のレスポンス(bare response)を返してください。これに失敗すると、ウェブフックは失敗します。
GET ハンドラーの例:
export async function GET(req: NextRequest) {
const challenge = req.nextUrl.searchParams.get("challenge");
return new Response(challenge ?? "", { status: 200 });
}
POST 通知
メッセージが届くと、Nylas は POST リクエストを送信します。エラーを避けるために、次の 3 つのルールに従ってください。
- 即座にレスポンスを返す。重いロジックを実行する前に、ステータス 200 を返してください。LLM の処理に時間がかかりすぎると、ウェブフックがタイムアウトしてしまいます。
- シグネチャを検証する。
X-Nylas-Signatureヘッダーとウェブフックのシークレットを使用してください。これにより、権限のないユーザーがエージェントを起動することを防げます。 - 生のボディ(raw body)を使用する。HMAC シグネチャを検証するには、生のテキストが必要です。まずテキストを読み込んで検証し、その後に JSON をパースしてください。
POST ハンドラーの例:
export async function POST(req: NextRequest) {
const raw = await req.text();
const signature = req.headers.get("x-nylas-signature") ?? "";
const expected = crypto
.createHmac("sha256", process.env.NYLAS_WEBHOOK_SECRET!)
.update(raw, "utf8")
.digest("hex");
const valid =
signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
if (!valid) {
return new Response("invalid signature", { status: 401 });
}
const payload = JSON.parse(raw);
const { object } = payload.data;
processMessage(object.grant_id, object.id).catch(console.error);
return NextResponse.json({ ok: true }, { status: 200 });
}
本番環境でのヒント
• メッセージの重複排除。Webhookは「少なくとも1回(at-least-once)」の配信を保証します。同じメッセージを二度処理しないよう、データベースの制約またはRedisを使用してください。
• 切り詰められたペイロードの処理。メッセージが1 MBを超える場合、ボディは切り詰められます。完全なコンテンツを取得するには、常にAPI経由でメッセージを再取得してください。
• クリーニング済みのコンテンツを使用する。煩雑なHTMLの代わりに message.created.cleaned を使用してMarkdownを取得してください。これにより、LLMにとってより扱いやすくなります。
Webhookハンドラーでの重複排除はどのように行っていますか?Redisを使用していますか、それともデータベースの制約を使用していますか?
出典: https://dev.to/qasim157/handle-messagecreated-webhooks-in-nextjs-4e80