Skip to main content
Cadenya sends you webhooks for all types of events that happen during an agent’s objective. Tool calls, messages, and approvals all go to the configured webhook URL on your agent. This makes it possible to steer agents as they need guidance during an objective, like for a tool approval. For example, if a tool approval is requested, you may want to send a message to Slack, an email to a customer, or a push notification to a device. The notification lets your end users know they need to hop in and weigh in on an action your AI agent wants to take. At a high level, this is the architecture of a simple app with Cadenya. High level app overview
Building in TypeScript, Go, or Ruby? The Cadenya SDK verifies the signature and parses the payload for you with webhooks.unwrap. The Approving a tool and Email updates from an objective guides build the full handler. The HMAC steps below show the mechanism by hand, for a language without an SDK helper or when you want to see what unwrap does under the hood.
Two tools pair well with agent webhooks: Svix Play as a destination, and the Standard Webhooks verifier, while you build against Cadenya.

Webhooks

Webhooks sent by Cadenya conform to Standard Webhooks. They are delivered as POST requests with a JSON envelope containing type, timestamp, and data (with flat agent, agentVariation, objective, and objectiveEvent keys). Signed via Standard Webhooks HMAC-SHA256 (webhook-id, webhook-timestamp, webhook-signature headers).

Handling a webhook

Cadenya webhooks contain metadata keys with the information about the event. For example, an objective_event.assistant_message looks like this:

Handling HMAC

Cadenya webhooks follow Standard Webhooks, verified with HMAC. Find the signing secret on the Webhooks page of your account settings, where you can also rotate it. Most languages have a Standard Webhooks library that verifies for you, Ruby included, and it decodes the base64 secret and checks the signature in one call. The Cadenya Ruby SDK wraps exactly that in webhooks.unwrap. To show the mechanism underneath, here it is by hand in Ruby. First, here’s an example of a request your server receives:
The signed string is {webhook-id}.{webhook-timestamp}.{raw-body}, HMAC’d with your account’s webhook signing key. That key arrives as whsec_<base64>: strip the whsec_ prefix and base64-decode the rest to the raw bytes you sign with. Ruby verifier (Sinatra-style)

Example workflow

Say you want to let a user know when your AI Agent is requesting permission to use a tool. For example: approving an expense for a user. The flow would look like:
  1. Cadenya sends your application a webhook
  2. Your application sends an email to the user with a link to approve or reject
  3. The customer clicks the “approve” link which is hosted by your app, and then sends Cadenya an approve tool call API request.
  4. Your AI Agent in Cadenya continues
You’d have a small app that looks like this in Ruby:

Use case: smelly expenses

Say you are building the next expense tracking application (because there aren’t enough), and you want an AI Agent to validate and run smell checks on the receipt for you. If the receipt is suspicious, the agent might ask for approval before marking it as completed. Your agent’s system prompt might resemble this:
Tool call flow example

Tricks

It is recommended to leverage the externalId and labels fields of any metadata key in Cadenya to track your own state. For example, if the receipt in your own database has an ID of receipt_cy1shs, you can store it in the externalId of your objective on create:
Now, when Cadenya sends you webhooks during the agent’s loop, you always receive that externalId you assigned in the payload: