DEV Community

Fathin Dosunmu
Fathin Dosunmu

Posted on • Originally published at agentsim.dev

I Built an Autonomous Phone Verification Agent (Full Code + Tutorial)

You built an AI agent that can browse the web, fill forms, and make decisions. But it hits a wall every single time:

"This phone number cannot be used for verification."

Stripe. WhatsApp. Google. All of them run a carrier lookup. All of them block VoIP. And every cloud phone API returns line_type: VoIP.

Your agent is stuck. Not because it's dumb. Because the infrastructure is wrong.

Today I'll show you how to fix it. Full code. Real results.

The Problem in 30 Seconds

When Stripe receives a phone number, it doesn't just send an SMS. First, it queries the LERG/NPAC databases to check: what type of number is this?

$ curl https://lookups.twilio.com/v2/PhoneNumbers/+16505550001
{
  "line_type_intelligence": {
    "type": "voip",
    "carrier": "Twilio Inc."
  }
}
Enter fullscreen mode Exit fullscreen mode

Result: REJECTED. Stripe blocks VoIP numbers for verification. Always.

The same check happens at Google, WhatsApp, Telegram, banks. If your agent uses a cloud phone number, it will fail.

The Fix: Real SIM Infrastructure

The solution isn't a hack. It's the right infrastructure. AgentSIM provisions numbers on real physical SIM cards through Telnyx. Carrier lookup returns line_type: mobile -- exactly what Stripe, Google, and WhatsApp expect.

$ agentsim.provision({ country: "US" })
{
  "number": "+14155551234",
  "carrier": "T-Mobile",
  "line_type": "mobile"
}
Enter fullscreen mode Exit fullscreen mode

Building the Agent

Here's the complete code. Three steps. ~3.5 seconds end to end.

Step 1: Install

pip install agentsim
Enter fullscreen mode Exit fullscreen mode

Step 2: Provision a Number

import asyncio
from agentsim import AgentSIM

async def main():
    agentsim = AgentSIM(api_key="your-api-key")

    number = await agentsim.provision({
        "country": "US",
        "capabilities": ["sms"],
    })

    print(f"Number: {number.number}")
    print(f"Carrier: {number.carrier}")
    # Number: +14155551234
    # Carrier: T-Mobile
Enter fullscreen mode Exit fullscreen mode

Step 3: Wait for OTP

    otp = await number.wait_for_otp(timeout=30_000)

    print(f"OTP: {otp.code}")
    print(f"Service: {otp.service}")
    # OTP: 847291
    # Service: stripe
Enter fullscreen mode Exit fullscreen mode

That's it. The OTP is parsed automatically -- code extracted, service detected, structured JSON returned. No regex. No human reading SMS.

Full Autonomous Flow with Playwright

from playwright.async_api import async_playwright

async def verify_on_stripe():
    number = await agentsim.provision({"country": "US"})

    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page()
        await page.goto("https://connect.stripe.com/setup")
        await page.fill("input[name='phone']", number.number)
        await page.click("button[type='submit']")

        otp = await number.wait_for_otp(timeout=30_000)
        await page.fill("input[name='code']", otp.code)
        await page.click("button[type='submit']")

        print("Phone verified")
        await browser.close()
Enter fullscreen mode Exit fullscreen mode

Real Performance Numbers

This isn't theoretical. Here's what's running in production:

  • Provision time: 212ms average
  • OTP delivery: 3.5s average
  • Cost: $0.99 per session (provision + OTP + release)

Compare to alternatives:

Solution Cost Carrier Result
Twilio $1.15/number + usage line_type: VoIP (blocked)
JoltSMS $50/number/month line_type: mobile (works)
Shared virtual $0.30-2/number line_type: VoIP (blocked)
AgentSIM $0.99/session line_type: mobile (works)

At 100 verifications/month: JoltSMS costs $5,000. AgentSIM costs $99. 50x cheaper.

Why This Matters for AI Agents

AI agents are autonomous by design. They browse, decide, and act. But if every action that requires phone verification needs a human to read an SMS, your agent isn't autonomous -- it's a puppet.

Real SIM infrastructure removes the last human bottleneck. Your agent can:

  • Create and verify Stripe Connect accounts
  • Set up WhatsApp Business API
  • Verify Google accounts for service access
  • Register on any platform requiring SMS verification

All without human involvement.

MCP Native

If you're building with Claude Code, Cursor, or Windsurf -- AgentSIM has a built-in MCP server. One command to add it:

claude mcp add agentsim -- npx -y @agentsim/mcp-server
Enter fullscreen mode Exit fullscreen mode

Now your agent can provision numbers through natural language: "I need a US phone number to verify a Stripe account"

Try It Free

AgentSIM gives you 10 free sessions per month -- no credit card, no commitment. If the OTP doesn't arrive, you're not charged.

Get started at agentsim.dev/sign-up

One session = one number, one OTP, one verification. Your agent does the rest.


Open source at github.com/agentsimdev/agentsim. Docs at docs.agentsim.dev.

Top comments (0)