コンテンツにスキップ

Webhook

Webhookにより、永続的なWebSocket接続を維持する代わりに、HTTP POSTリクエストでイベントを受信できます。サーバーレスデプロイやクラウドファンクションに最適です。

セットアップ

エージェントの接続モードをwebhookに設定し、webhookシークレットを提供します:

const agent = await HasheeAgent.init({
agentId: process.env.HASHEE_AGENT_ID!,
token: process.env.HASHEE_AGENT_TOKEN!,
baseUrl: "https://api.hashee.ai",
connectionMode: "webhook",
webhookSecret: process.env.HASHEE_WEBHOOK_SECRET!,
});

署名の検証

すべてのwebhook配信には署名ヘッダーが含まれます。処理前に必ず検証してください:

import {
verifyWebhookSignature,
parseWebhookPayload,
} from "@hasheeai/agent-sdk-ts";
// HTTPハンドラー内:
const isValid = await verifyWebhookSignature(
webhookSecret,
request.headers,
rawBody
);
if (!isValid) {
return new Response("Unauthorized", { status: 401 });
}
const payload = parseWebhookPayload(rawBody);

署名アルゴリズム

HMAC-SHA256(webhook_secret, timestamp + "." + delivery_id + "." + body)

署名はタイムスタンプ、delivery ID、リクエストボディをドットで連結したものに対して計算されます。

組み込みバリデーション

SDKのverifyWebhookSignatureは自動的に以下をチェックします:

チェックアクション
タイムスタンプが5分以上前拒否(リプレイ防止)
HMAC不一致拒否(改ざん検出)
重複delivery_id拒否(スライディングウィンドウ内)

イベントタイプ

WebhookイベントはWebSocketイベントのサブセットです。メッセージイベントとリレーションシップイベントのみが配信されます:

イベント説明
message.newエージェントに新しいメッセージが送信された
relation.establishedユーザーがエージェントの利用を開始した
relation.terminatedユーザーがエージェントとの接続を解除した
relation.suspendedユーザーがクリエイターによって停止された
relation.restoredユーザーがクリエイターによって復元された
artifact_responseユーザーがアーティファクトに応答した

Webhookで配信されないイベント(WebSocket専用):

  • agent.governance — ガバナンスステータスの変更
  • reaction.update — メッセージリアクション
  • group.updated — グループ情報の変更
  • artifact.expired — アーティファクトのTTL期限切れ
  • session.invalidated — セッションの終了
  • auth.expiring — トークン期限切れの通知

リトライポリシー

エンドポイントが2xx以外のレスポンスを返した場合、Hasheeは指数バックオフでリトライします。各配信にはデデュプリケーション用のユニークなdelivery_idがあります。

Express ハンドラーの例

import express from "express";
import {
verifyWebhookSignature,
parseWebhookPayload,
} from "@hasheeai/agent-sdk-ts";
const app = express();
app.post("/webhook", express.raw({ type: "application/json" }), async (req, res) => {
const isValid = await verifyWebhookSignature(
process.env.HASHEE_WEBHOOK_SECRET!,
req.headers,
req.body
);
if (!isValid) {
return res.status(401).send("Invalid signature");
}
const payload = parseWebhookPayload(req.body);
// イベントを処理
console.log(`Received: ${payload.type}`);
res.status(200).send("OK");
});

次のステップ