What Voice Agent Call Monitoring gives you

Voice Agent Call Monitoring help you monitor the health and reliability of your AI voice agents in production against real customer calls. It helps you answer questions like:

  • What’s the current health of my system?
  • Are there performance anomalies over time?
  • Should I scale resources or fallback to a different service provider based on observed latency or error trends?
  • Which calls are failing and why?
  • How are users interacting with the voice agent over multiple calls?
  • Where do users drop off in the call flow?
  • Do changes to the prompt or model correlate with better outcomes?
  • How do I find calls where the customer is upset? (i.e. high frustration Hume scores)

Set up Voice Agent Call Monitoring

For Retell and Vapi agents, it’s a few clicks to set up monitoring. For custom agents, you can send call recordings to Hamming via a webhook.

Retell Voice Agent Monitoring

The setup process is different depending on whether you’re already using Retell’s webhook or setting up a new one from scratch.

If you’re already using Retell’s webhook, you can set up monitoring in a few clicks.

1

Set up your .env file

Set up a Hamming API Key by going to hamming.ai/settings and selecting Create a new secret key at the top. Then, add the API key to your .env file as shown in the code snippet below.

HAMMING_API_KEY=<your_hamming_api_key>
2

Send in the Retell post-call payload to Hamming

You can send in the Retell post-call payload to Hamming by sending a POST request to https://app.hamming.ai/api/rest/v2/call-logs with the following body:

  const body = {
    provider: "retell", //Important to set this to "retell"
    metadata: {
      agent_name: "My Agent Name", //This is the name of your Retell agent
    },
    payload: req.body, // This is the Retell post-call payload coming from Retell's webhook
  };

Sample NodeJS server to send the payload to Hamming while consuming it for your own purposes:

import dotenv from "dotenv";
import { envsafe, str } from "envsafe";
import express from "express";

dotenv.config();

const app = express();
app.use(express.json());

export const env = envsafe({
  HAMMING_API_KEY: str(),
});

app.post("/retell-webhook", (req, res) => {
  const body = {
    provider: "retell",
    metadata: {
      agent_name: "My Agent Name",
    },
    payload: req.body,
  };
  await fetch(`https://app.hamming.ai/api/rest/v2/call-logs`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${env.HAMMING_API_KEY}`,
    },
    body: JSON.stringify(body),
  });
  res.sendStatus(200);
});

app.listen(3010, () => {
  console.log("Server is running on port 3010");
});
3

Monitor Calls

Once you’ve started sending the payload to Hamming, Hamming will log all inbound and outbound phone calls and generate Hume scores, providing valuable insights into the performance and sentiment of the calls.

VAPI Voice Agent Monitoring

The setup process is different depending on whether you’re already using VAPI’s webhook or setting up a new one from scratch.

If you’re already using VAPI’s webhook, you can set up monitoring in a few clicks.

1

Set up your .env file

Set up a Hamming API Key by going to hamming.ai/settings and selecting Create a new secret key at the top. Then, add the API key to your .env file as shown in the code snippet below.

HAMMING_API_KEY=<your_hamming_api_key>
2

Send in the VAPI post-call payload to Hamming

You can send in the VAPI post-call payload to Hamming by sending a POST request to https://app.hamming.ai/api/rest/v2/call-logs with the following body:

const body = {
  provider: "vapi", //Important to set this to "vapi"
  metadata: {
    agent_name: "My Agent Name", //This is the name of your VAPI agent
  },
  payload: req.body, // This is the VAPI post-call payload coming from VAPI's webhook
};

Sample NodeJS code to send the payload to Hamming while consuming it for your own purposes:

import dotenv from "dotenv";
import { envsafe, str } from "envsafe";
import express from "express";

dotenv.config();

const app = express();
app.use(express.json());

export const env = envsafe({
  HAMMING_API_KEY: str(),
});

app.post("/vapi-webhook", async (req, res) => {
  const body = {
    provider: "vapi",
    metadata: {
      agent_name: "My Agent Name",
    },
    payload: req.body,
  };
  await fetch(`https://app.hamming.ai/api/rest/v2/call-logs`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${env.HAMMING_API_KEY}`,
    },
    body: JSON.stringify(body),
  });
  res.sendStatus(200);
});

app.listen(3010, () => {
  console.log("Server is running on port 3010");
});
3

Monitor Calls

Once you’ve started sending the payload to Hamming, Hamming will log all inbound and outbound phone calls and generate Hume scores, providing valuable insights into the performance and sentiment of the calls.

Custom Agent Monitoring

If you’re using OpenAI’s real-time voice agent or other custom voice agents, you can send call recordings to Hamming via a webhook.

1

Set up your .env file

Set up a Hamming API Key by going to hamming.ai/settings and selecting Create a new secret key at the top. Then, add the API key to your .env file as shown in the code snippet below.

HAMMING_API_KEY=<your_hamming_api_key>
2

Send call recordings to Hamming

If you just have the recorded calls and no diarized transcripts, you can send just the call recordings to Hamming via a webhook:

curl --location 'https://app.hamming.ai/api/rest/v2/call-logs' \
--header 'Authorization: Bearer <HAMMING_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
    "provider": "custom",
    "metadata": {
        "agent": "My Test Agent"
    },
    "payload": {
        "call_id": "abc123",
        "recording_url": "https://storage.vapi.ai/2f465c6c-93d2-40f0-8ec9-dafdc23fb0d2-1732230739721-32d30dab-2b31-41d3-b6e3-64e8330c00e2-stereo.wav",
        "from_number": "+14255100373",
        "to_number": "+18335100415",
        "start_timestamp": 1732570954000,
        "end_timestamp": 1732570964000,
        "status": "ended"
        "transcript": ... // Optional
    }
}'
  • provider should be set to custom.
  • call_id is a unique identifier for the call.
  • recording_url is the URL of the call recording. For private recording URLs, we’d need a token to access it.
  • metadata is a key-value pair that you can use to store any additional information about the call.
  • from_number is the caller’s phone number.
  • to_number is the callee’s phone number.
  • start_timestamp is the start time of the call, in milliseconds.
  • end_timestamp is the end time of the call, in milliseconds.
  • status is the status of the call. (ended or error).
  • transcript is the transcript of the call (optional).
3

(Optional) Send the transcript with the tool calls

Sending the transcripts with the tool calls allows us to measure what is done (function calls) in addition to what is said.

If you have the transcript with the tool calls, you add the transcript to the payload object with the following type:

export type OpenAITranscriptType = {
  kind: "openai";
  messages: Array<
    | {
        role: "user";
        start?: number;
        content: string;
      }
    | {
        role: "assistant";
        start?: number;
        content: string;
        tool_calls?: Array<{
          id: string;
          type: "function";
          function: {
            name: string;
            arguments: string;
          };
        }>;
      }
    | {
        role: "tool";
        start?: number;
        content: string;
        tool_call_id: string;
      }
  >;
};

Example payload with transcript:

const examplePayload = {
  provider: "custom",
  metadata: {
    agent: "Restaurant Booking Agent"
  },
  payload: {
    call_id: "call_123456789",
    recording_url: "https://example.com/recordings/call_123456789.wav",
    from_number: "+14255551234",
    to_number: "+18335557890",
    start_timestamp: 1732570954000,
    end_timestamp: 1732571254000,
    status: "ended",
    transcript: {
      kind: "openai",
      messages: [
        {
          role: "user",
          start: 1732570955000,
          content: "Hi, I'd like to make a reservation for dinner tonight."
        },
        {
          role: "assistant",
          start: 1732570958000,
          content: "I'd be happy to help you make a dinner reservation. How many people will be dining?",
        },
        {
          role: "user",
          start: 1732570962000,
          content: "Four people, around 7:30 PM if possible."
        },
        {
          role: "assistant",
          start: 1732570965000,
          content: "I'll check the availability for 4 people at 7:30 PM tonight.",
          tool_calls: [
            {
              id: "call_abc123",
              type: "function",
              function: {
                name: "check_availability",
                arguments: JSON.stringify({
                  party_size: 4,
                  time: "19:30",
                  date: "2024-03-20"
                })
              }
            }
          ]
        },
        {
          role: "tool",
          start: 1732570967000,
          content: JSON.stringify({
            available: true,
            tables: ["table_23", "table_45"]
          }),
          tool_call_id: "call_abc123"
        },
        {
          role: "assistant",
          start: 1732570969000,
          content: "Great news! We have availability for 4 people at 7:30 PM tonight. Would you like me to proceed with the reservation?",
        }
      ]
    }
  }
};
  • start is the start time of the message, in milliseconds.

The remaining fields match the OpenAI’s API Spec.

4

Monitor Calls

Once calls are made, they will be logged in Hamming and you will see Hume scores, providing valuable insights into the performance and sentiment of the calls.