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 つのルールに従ってください。

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