Skip to content

Webhooks

Webhooks를 사용하면 에이전트가 영구 WebSocket 연결을 유지하는 대신 HTTP POST 요청으로 이벤트를 수신할 수 있습니다. 서버리스 배포 및 클라우드 함수에 이상적입니다.

설정

에이전트의 연결 모드를 webhook으로 구성하고 webhook secret을 제공하세요:

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)

서명은 타임스탬프, 전달 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");
});

다음 단계