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 Retell’s call_ended event payload to Hamming by sending a POST request to https://app.hamming.ai/api/rest/v2/call-logs with the following body:

Visit Retell’s documentation to learn more about the call_ended event payload.

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 call_ended payload coming from Retell's webhook
  externalAgentId: "your-retell-agent-id", // Optional: The Retell agent ID to link this call to a specific agent
};

Example Retell call_ended payload that’s coming from req.body:

{
  "event": "call_ended",
  "call": {
    "call_type": "phone_call",
    "from_number": "+12137771234",
    "to_number": "+12137771235",
    "direction": "inbound",
    "call_id": "Jabr9TXYYJHfvl6Syypi88rdAHYHmcq6",
    "agent_id": "oBeDLoLOeuAbiuaMFXRtDOLriTJ5tSxD",
    "call_status": "registered",
    "metadata": {},
    "retell_llm_dynamic_variables": {
      "customer_name": "John Doe"
    },
    "start_timestamp": 1714608475945,
    "end_timestamp": 1714608491736,
    "disconnection_reason": "user_hangup",
    "transcript": "...",
    "transcript_object": [ [Object], [Object], [Object], [Object] ],
    "transcript_with_tool_calls": [ [Object], [Object], [Object], [Object] ],
    "opt_out_sensitive_data_storage": false
  }
}

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,
    externalAgentId: "your-retell-agent-id", // Optional: Links to your agent in Hamming
  };
  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.

monitoringwave

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
  externalAgentId: "your-vapi-assistant-id", // Optional: The VAPI assistant ID to link this call to a specific agent
};

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,
    externalAgentId: "your-vapi-assistant-id", // Optional: Links to your agent in Hamming
  };
  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.

monitoringwave

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": { // Optional: Add any additional metadata about the call
        "customer": "McDonalds",
        "environment": "production",
        "key": "value",
    },
    "externalAgentId": "your-custom-agent-id", // Optional: Links to your agent in Hamming
    "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.
  • externalAgentId is the ID of the agent in your system (optional). This links the call to a specific agent in Hamming for filtering.
  • 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",
  },
  externalAgentId: "restaurant-booking-agent-v1", // Optional: Links to your agent in Hamming
  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.

monitoringwave

Agent-Specific Monitoring

Once you’ve set up monitoring with the externalAgentId parameter, you can filter your production call logs by specific agents in the Hamming dashboard.

How It Works

  1. Agent Linking: When you send call logs with an externalAgentId, Hamming automatically links the call to the corresponding agent in your workspace using the agent’s sourceId.

  2. Filtering: In the monitoring dashboard, you can use the agent filter dropdown to view calls for specific agents only.

  3. Benefits:

    • Monitor individual agent performance in production
    • Compare metrics across different agents
    • Quickly identify agent-specific issues or patterns
    • Track improvements after agent updates

Setting Up Agent Linking

The externalAgentId should match the agent ID from your voice provider (e.g., Retell agent ID, VAPI assistant ID, or your custom agent identifier).

For agent linking to work:

  1. Sync Your Agents: Make sure your agents are synced to Hamming (either manually created or auto-synced from providers like Retell/VAPI).

  2. Use Consistent IDs: The externalAgentId you send must match the sourceId of the agent in Hamming.

  3. Include in Call Logs: Add the externalAgentId field when sending call logs:

{
  provider: "retell", // or "vapi", "custom"
  externalAgentId: "agent_123xyz", // Your agent's external ID
  payload: { ... },
  metadata: { ... }
}

Viewing Agent-Specific Data

Once calls are linked to agents:

  1. Navigate to the Monitoring Dashboard
  2. Use the agent filter dropdown to select a specific agent
  3. View filtered metrics, call logs, and performance data for that agent only

This enables you to:

  • Track call volume per agent
  • Monitor success rates by agent
  • Analyze latency and performance metrics per agent
  • Identify which agents need optimization