Skip to main content

Webhooks

When a reviewer decides — or a policy timeout path applies — TryAgent sends a signed POST to your escalation’s resume.url. The SDK verifies the signature for you so you never hand-roll HMAC.

The signature

When resume.secret is set, TryAgent signs the exact JSON body with HMAC-SHA256 and sends:
  • x-tryagent-event: escalation.decided for a reviewer decision, or escalation.breached when the SLA timeout applies. The resolvedBy field (human or timeout) carries the same distinction.
  • x-tryagent-delivery: <delivery id>
  • x-tryagent-signature: v1=<hex hmac>
Verification runs on Web Crypto, so it works unchanged on Node 20+, edge runtimes, Deno, and Workers.
Always pass the raw, unparsed request body. Re-serializing JSON changes the bytes and breaks the signature. Callbacks without resume.secret are unsigned — always set a secret in production.

webhooks.constructEvent

Verifies the signature and returns the typed event. Throws WebhookSignatureError when verification fails, so a returned event is always safe to act on.
import { TryAgent, WebhookSignatureError } from "@tryagent/sdk";

const tryagent = new TryAgent({ apiKey: process.env.TRYAGENT_API_KEY! });

export async function POST(request: Request) {
  const body = await request.text();

  try {
    const event = await tryagent.webhooks.constructEvent({
      payload: body,
      signature: request.headers.get("x-tryagent-signature"),
      secret: process.env.TRYAGENT_WEBHOOK_SECRET!,
    });

    await resumeWorkflow(event.runId, {
      escalationId: event.escalationId,
      choice: event.choice,
      answeredBy: event.answeredBy,
      answeredAt: event.answeredAt,
    });

    return Response.json({ ok: true });
  } catch (error) {
    if (error instanceof WebhookSignatureError) {
      return Response.json({ error: "Invalid signature" }, { status: 401 });
    }
    throw error;
  }
}

webhooks.verify

Returns a boolean instead of throwing or parsing — use it when you want to branch on validity yourself.
const valid = await tryagent.webhooks.verify({
  payload: body,
  signature: request.headers.get("x-tryagent-signature"),
  secret: process.env.TRYAGENT_WEBHOOK_SECRET!,
});
Both methods are also exported as standalone functions, constructWebhookEvent and verifyWebhookSignature, for use without a client instance.

Event shape

constructEvent resolves to a WebhookResumeEvent:
FieldTypeDescription
escalationIdstringThe escalation that was resolved.
runIdstringThe durable run handle to resume.
agentIdstringThe agent that paused.
policystringThe policy key the escalation ran under.
choicestring | nullThe selected choice id. null when canceled.
responseobjectStructured values when the escalation defined responseFields.
resolvedBy"human" | "timeout"Whether a reviewer decided or the SLA timeout applied.
answeredBystring | nullThe reviewer name, or null for a timeout.
answeredAtstringISO timestamp of the decision.