Skip to main content
Cadenya POSTs a webhook for everything an objective does: the agent’s messages, its tool calls, the final result. You do not need a live UI to put those to work. The practical move is a notification: email someone when their objective finishes, and alert the team when one fails. This guide builds a webhook handler that does exactly that, in TypeScript and Go. The same shape drives Slack, SMS, or a ticket, so once you have email working you can point it anywhere.

What you need

  • An agent with its webhook events URL pointed at the server you build here. See Approving a tool for wiring the URL and a tunnel.
  • Your webhook signing secret in CADENYA_WEBHOOK_KEY and your API key in CADENYA_API_KEY.
  • An SMTP account to send mail. This guide uses Nodemailer in TypeScript and the standard net/smtp package in Go.
  • Objectives tagged with the address to notify. Set it in labels when you start the objective, and every webhook for that run carries it.
Agent Webhook configuration with an ngrok Events URL ending in webhooks/cadenya

Set the receiver on the agent before publishing it

See Create an objective for the full request.

Step 1: Receive and verify the webhook

Read the raw body, hand it to unwrap, which checks the Standard Webhooks signature against CADENYA_WEBHOOK_KEY and parses the payload. Acknowledge with a 200 before you send any mail, so a slow SMTP call never trips a retry.

Step 2: Email on finish and failure

Cadenya sends a webhook for every objective event, but you would not email each assistant message; that is noise. The two worth a person’s inbox are finalized (the run is done, here is the result) and error (something broke). Read the recipient off the objective’s labels, then branch.
The finalized event carries the agent’s structured output at finalized.output, so the completion email includes the result with no extra fetch. See Get structured output for shaping it.

Make it reliable

Return 200 first, then send mail. Cadenya retries a delivery that does not ack, and an SMTP round trip is slow enough to cause repeats if you block on it.
A retry resends a delivery with the same webhook-id header. Track the IDs you have handled and skip repeats, so one finished objective does not send two emails.
The branch is the whole pattern. Swap send for a Slack post, an SMS, or a ticket create, and key the destination off labels the same way. For a live in-app feed, push each event to the browser over server-sent events instead of email.

What you built

A handler that verifies a Cadenya webhook, finds who to tell from the objective’s labels, and emails them the result when a run finishes or an alert when it fails. No polling, no dashboard watching, the news comes to the right inbox.

Going further

Approving a tool

Add a human in the loop: approve or deny a tool call from the same handler.

Get structured output

The schema behind the finalized event’s output object.