Technology ยท 12 min read

Killing the Robocall Cash Drain: How I Built a $0.00 Spam Firewall for AI Voice Agents

Preface & Prerequisites

Before reading further, let me establish the playing field. This architecture is specifically engineered for developers, founders, and operators who run their conversational AI voice agents on Vapi but manage their telephony infrastructure directly through Twilio (either via Twilio inventory or a Bring Your Own Carrier / BYOC link). If you are using Vapi's natively purchased numbers without direct backend access to your Twilio console, you will not be able to build this specific edge firewall. If you do own your Twilio lines, congratulations. You are about to save a lot of money.


Building with cutting-edge conversational AI platforms like Vapi is incredible. You design a custom voice agent, connect it to an LLM, handle backend routing, and suddenly you have an intelligent assistant answering calls seamlessly. It feels like the future, until the vultures find your number.

The Nightmare Scenario: Burning Cash on Bot-to-Bot Chats

A few days ago, I noticed my Vapi account balance was melting. When I opened up the logs, I found a digital horror show: a massive, relentless swarm of automated robocallers slamming my inbound line. These were not standard spammers you can easily block. They were using a sophisticated neighbor-spoofing rotation mechanism, swapping out caller IDs on every single attempt to slide right past traditional filters.

The Core Loop of the Exploit:

  1. The spam bot dials my Twilio inbound phone line.
  2. The call hits Vapi, which answers, spins up the voice transcription engine, and hands the audio over to the LLM backend to figure out if it is a person or a machine.
  3. The spam bot blasts an automated prerecorded recording for 5 to 10 seconds.
  4. Vapi finally categorizes the call as a bot and forcefully hangs up.

The catch? The connection lasted around 37 seconds. Every single call racked up a flat $0.05 processing fee. Over hours and days, those nickels compound into hundreds of dollars of pure waste, funding an empty, incredibly expensive conversation between two machines.

Why Built-In Application Filters Fail

When you are targeted by a rotating spam attack, trying to block numbers inside your Vapi dashboard or application level is a complete joke. It is an exhausting, manual game of digital whack-a-mole. Because Vapi must pick up the phone to listen, evaluate, and flag the call, you have already lost the budget game the millisecond the line connects and answers.

To win this war, you have to build an Edge Firewall. You need to intercept the call inside Twilio, cross-examine the incoming phone number against a dynamic blocklist, and terminate malicious callers completely for free before Vapi ever gets a notification that a call even exists.

Cost Comparison:

  • Old Approach (App-Level Detection): 37-Second Audio Pipeline Processing Cost → $0.05 / call
  • New Edge Firewall Approach: Twilio Carrier-Level Ring Rejection (0-Second Connection) → $0.00 / call

The Three-Tier Architecture of Absolute Retaliation

The solution requires three connected components working seamlessly together. This setup provides a simple, maintainable spreadsheet interface for you while giving your Twilio carrier infrastructure instantaneous routing directives.

  • The Database (Google Sheets): A standard cloud spreadsheet where you can drop raw numbers or exported logs instantly without dealing with code or complex database admin panels.
  • The Gateway API (Google Apps Script): A lightweight backend attached to your sheet that translates the spreadsheet rows into an instant JSON endpoint accessible by Twilio webhooks.
  • The Network Engine (Twilio Studio + TwiML Bins): A carrier-level routing machine that runs a data lookup mid-ring, splitting human traffic to Vapi while executing a hard SIP rejection protocol on spammers.

The Step-by-Step Blueprint: Build it Yourself

Step 1: Create the Cloud Database and Web App API

First, create a clean spreadsheet to act as your live blocklist. Head over to Google Sheets, create a new spreadsheet, and name the first row of Column A exactly Phone Number. Drop a dummy number in row 2 (e.g., 19415551234) to establish your layout structure.

Next, click on Extensions > Apps Script in the top menu. Wipe out any default boilerplate and paste the following performance-optimized look-up engine script. This specific code automatically cleans up text formatting, meaning you can blindly copy and paste numbers with spaces, dashes, or parentheses directly from your logs and it will still match perfectly:

function doGet(e) {
  var incomingPhone = e.parameter.phone;
  if (!incomingPhone) {
    return ContentService.createTextOutput(
      JSON.stringify({blocked: false})
    ).setMimeType(ContentService.MimeType.JSON);
  }
  
  // Strip all formatting symbols to allow raw numeric matching
  var cleanIncoming = incomingPhone.replace(/\D/g, ''); 
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var lastRow = sheet.getLastRow();
  
  if (lastRow < 2) {
    return ContentService.createTextOutput(
      JSON.stringify({blocked: false})
    ).setMimeType(ContentService.MimeType.JSON);
  }
  
  var data = sheet.getRange(2, 1, lastRow - 1, 1).getValues(); 
  var isBlocked = false;
  
  for (var i = 0; i < data.length; i++) {
    var blockedNum = data[i][0].toString().replace(/\D/g, '');
    if (blockedNum === cleanIncoming && blockedNum !== "") {
      isBlocked = true;
      break;
    }
  }
  
  return ContentService.createTextOutput(
    JSON.stringify({blocked: isBlocked})
  ).setMimeType(ContentService.MimeType.JSON);
}

Click the Save disk icon, then click the blue Deploy > New deployment button. Choose Web App as the type, configure the execution mode to run as Me, and set accessibility privileges to Anyone. Click deploy, approve permissions via your Google account, and copy the final generated Web App URL.

Step 2: Generate the $0.00 Carrier Rejection Command

If you route blocked numbers to a standard text-to-speech or answering widget in Twilio, the carrier will bill you for an active connection minute. To bypass this, we use a custom programmatic rejection layout via TwiML.

Log into your main Twilio Console dashboard, click the top global search bar, type TwiML Bins, and select it. Create a new bin, name it Hard Reject Spammers, and paste the following structural markup block:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Reject reason="busy" />
</Response>

Click save, then copy the unique Handler URL located right under the configuration name field.

Step 3: Construct the Twilio Studio Flow Core Logic

Navigate to Studio > Flows inside Twilio and select Create from Scratch. Name it Block Fucking Robo Calls. This visual drag-and-drop canvas acts as your live telephone switchboard network layout.

The Webhook Query: Pull an HTTP Request widget out of the left-hand tool tray and place it directly under your Trigger head block. Wire the Incoming Call handle into it. Configure its Method to GET, and set its request URL to your copied Google Sheets Web App URL, appending ?phone={{trigger.call.From}} to the end of the text string.

The Split Core Evaluator: Drag out a Split Based On... widget and route the Success pin of your HTTP Request straight into it. Set the Variable to Test property field exactly to {{widgets.check_sheet.parsed.blocked}}.

The Condition Assignment: Jump into the split widget's Transitions tab, create a new conditional matching requirement rule, set the comparative type indicator to Equal To, and assign its targeted monitoring verification value to exactly true.

Final Path Intercepts: Drag out two separate Add TwiML Redirect widgets from the toolbar panel.

Name the first one redirect_vapi, map it to the split's No Condition Matches bubble, and input your primary Vapi endpoint URL: https://api.vapi.ai/twilio/inbound_call.

Name the second one redirect_2, map it to your split's If value equal_to true bubble, and paste your copied TwiML Bin Handler URL.

Verify that all elements are securely connected, remove any orphaned lines, and hit the blue Publish button at the top right of your workspace canvas.

Step 4: Activate the Edge Firewall Routing Profile

With your visual logic mapping published, head over to your active phone lines inventory tab inside Twilio (Phone Numbers > Active Numbers). Click into your voice agent's inbound number block configuration, scroll directly down to the Voice & Fax routing sub-section panel, and alter your default handling profiles.

Switch the dropdown field from Webhook over to Studio Flow, locate your newly compiled Block Fucking Robo Calls layout inside the structural menu list options, and commit the update by hitting the blue save key.

The Results: Complete Silence and Cost Mitigation

Now, whenever an automated spam number dials in, Twilio executes an instant lookup against your Google Sheet while the call is still in the ringing state. If a match is found, the TwiML Bin fires an immediate SIP Reject response. The robocaller's machine hits a hard wall, receives an automated busy or disconnected tone, and drops the connection.

Because Twilio never transmits an active "Answer" signal back to the originating carrier network, the call duration is registered as exactly 0 seconds. The cost to you is exactly $0.00. Meanwhile, real customers slide right through the check rings instantly, connecting to your Vapi voice agent without seeing a single menu, experiencing an interactive audio prompt, or feeling a fraction of a millisecond of lag.

You can keep your Google Sheet open on your dashboard, monitor incoming caller profiles, paste in malicious targets as they appear, and watch your platform metrics return to perfect, clean performance.

Frequently Asked Questions

Why can't I just block spam numbers inside Vapi or my application layer?+

Because Vapi must answer the call to evaluate it. The moment the line connects, you are paying for transcription, LLM processing, and Twilio connection minutes. Blocking at the application layer means you have already lost the budget game. An edge firewall intercepts the call at the carrier level, before Vapi ever receives a notification, so the cost is exactly $0.00 per blocked call.

Does the TwiML Reject command actually cost $0.00?+

Yes. When Twilio executes a Reject instruction via TwiML, the carrier never sends an active Answer signal back to the originating network. The call duration registers as 0 seconds. No connection minute is billed, no processing fee is charged. The robocaller's machine receives a busy or disconnected tone and drops the line immediately.

How do I handle neighbor-spoofed numbers that rotate on every call?+

The Google Sheets blocklist approach handles this by letting you paste numbers in bulk directly from your call logs. Because the Apps Script strips all formatting and matches on raw digits, you can export Vapi or Twilio logs, copy the offending caller ID column, and paste it straight into the spreadsheet. The lookup runs on every inbound call, so new entries take effect immediately without any code deployment or server restart.

Keep Reading

Related Articles

Want to Discuss This?

I'm always up for a conversation. Reach out if something sparks your interest.