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:
| Field | Type | Description |
|---|
escalationId | string | The escalation that was resolved. |
runId | string | The durable run handle to resume. |
agentId | string | The agent that paused. |
policy | string | The policy key the escalation ran under. |
choice | string | null | The selected choice id. null when canceled. |
response | object | Structured values when the escalation defined responseFields. |
resolvedBy | "human" | "timeout" | Whether a reviewer decided or the SLA timeout applied. |
answeredBy | string | null | The reviewer name, or null for a timeout. |
answeredAt | string | ISO timestamp of the decision. |