API Web Hook
You need configure a webhook url for each agent you create. Long running text responses from agents and configured functions are sent to webhooks.
To securely consume a webhook response, you can optionally validate the webhook using the x-signature token sent with the response. The token must be validated with the same api key used to make the request to the agent.
// Header
'x-signature': xxxxxxxxxxxxxxx
// Webhook Text Response
{
"message": {
"id": "duH7f5mOItDIlpYRbMPDE",
"agentId": "hyeyry3mOItehdsfp373hhs",
"role": "assistant",
"content": "The diagnosis of Pediculus Capitis (head lice) is a valid medical condition. The details provided do not indicate any fraudulent activity."
}
}
Here is a smaple code to securely verify your hooks
const crypto = require('crypto');
function verifyWebhookSignature(req, secret) {
const signature = req.headers['x-signature'];
const payload = JSON.stringify(req.body);
// Compute the hash using HMAC with SHA256 and the shared secret
const hash = crypto.createHmac('sha256', secret).update(payload).digest('hex');
// Compare the computed hash with the signature
return hash === signature;
}
// Usage in Express.js
app.post('/webhook', (req, res) => {
const secret = 'your_api_key';
if (!verifyWebhookSignature(req, secret)) {
return res.status(403).send('Forbidden');
}
// Handle the webhook
res.status(200).send('Webhook received');
});
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
public class WebhookVerifier {
public static boolean verifyWebhookSignature(HttpServletRequest req, String secret) throws Exception {
String signature = req.getHeader("x-signature");
StringBuilder payload = new StringBuilder();
try (BufferedReader reader = req.getReader()) {
String line;
while ((line = reader.readLine()) != null) {
payload.append(line);
}
}
Mac sha256HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
sha256HMAC.init(secretKey);
byte[] hashBytes = sha256HMAC.doFinal(payload.toString().getBytes(StandardCharsets.UTF_8));
String hash = bytesToHex(hashBytes);
return hash.equals(signature);
}
private static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder(2 * bytes.length);
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
}
import hmac
import hashlib
def verify_webhook_signature(req, secret):
signature = req.headers.get('x-signature')
payload = req.data.decode('utf-8') # Assuming you're using Flask, this will give you the raw payload
# Compute the HMAC SHA256 hash
hash = hmac.new(secret.encode('utf-8'), payload.encode('utf-8'), hashlib.sha256).hexdigest()
# Compare the computed hash with the signature
return hash == signature
# Usage in Flask
from flask import Flask, request, abort
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
secret = 'your_shared_secret'
if not verify_webhook_signature(request, secret):
abort(403) # Forbidden
# Handle the webhook
return 'Webhook received', 200
require 'openssl'
def verify_webhook_signature(req, secret)
signature = req.headers['x-signature']
payload = req.body.read
# Compute the HMAC SHA256 hash
hash = OpenSSL::HMAC.hexdigest('SHA256', secret, payload)
# Compare the computed hash with the signature
hash == signature
end
# Usage in Sinatra
require 'sinatra'
post '/webhook' do
secret = 'your_shared_secret'
halt 403, 'Forbidden' unless verify_webhook_signature(request, secret)
# Handle the webhook
status 200
'Webhook received'
end
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"io/ioutil"
"net/http"
)
func verifyWebhookSignature(r *http.Request, secret string) bool {
signature := r.Header.Get("x-signature")
body, _ := ioutil.ReadAll(r.Body)
defer r.Body.Close()
h := hmac.New(sha256.New, []byte(secret))
h.Write(body)
hash := hex.EncodeToString(h.Sum(nil))
return hash == signature
}
func webhookHandler(w http.ResponseWriter, r *http.Request) {
secret := "your_shared_secret"
if !verifyWebhookSignature(r, secret) {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
// Handle the webhook
w.WriteHeader(http.StatusOK)
w.Write([]byte("Webhook received"))
}
func main() {
http.HandleFunc("/webhook", webhookHandler)
http.ListenAndServe(":8080", nil)
}
<?php
function verifyWebhookSignature($request, $secret) {
// Get the signature from the request headers
$signature = $request->getHeader('x-signature')[0]; // Assuming you're using PSR-7 Request
$payload = $request->getBody()->getContents(); // Get the raw body payload
// Compute the HMAC SHA-256 hash
$hash = hash_hmac('sha256', $payload, $secret);
// Compare the computed hash with the signature
return hash_equals($hash, $signature);
}
// Usage in a PSR-7 compatible framework like Slim or Laravel (with Request injection)
$app->post('/webhook', function ($request, $response) {
$secret = 'your_shared_secret';
if (!verifyWebhookSignature($request, $secret)) {
return $response->withStatus(403)->write('Forbidden');
}
// Handle the webhook
return $response->withStatus(200)->write('Webhook received');
});
You can optionally use this approach to seurely consume a hook, or ensure that your webhook url is on a secured https certificate.
Last updated