LangChain, n8n, and AutoGPT share a common blind spot: they can browse, search, write, call APIs, and orchestrate multi-step workflows — but the moment a platform asks for a phone number for SMS verification, the agent stops cold. This guide shows you exactly how to give your agent a real, persistent phone number it can use autonomously, using a physical SIM and standard tooling.

Why This Problem Is Harder Than It Looks

The obvious first answer is a virtual number API — Twilio, Vonage, or similar. The problem is that the platforms that require SMS verification are frequently the same ones that have invested in detecting virtual numbers. A carrier lookup on a Twilio number returns a VoIP flag. Many financial services, exchanges, and social networks silently reject these at registration time, or route accounts using them into extended manual review queues.

The second obvious answer is the developer's own mobile number. This is fragile in production: one fraud flag affects every agent using the number simultaneously, and it creates a permanent identity link between the developer and every account the agent registers.

The solution that actually works in production is a physical SIM card in a USB modem on the same machine as the agent — or on a networked machine the agent can reach. It registers as a real mobile subscriber with real carrier metadata, passes all carrier lookup checks, and gives you full programmatic control over SMS receipt.

Hardware Requirements

You need two things: a KYC-free physical SIM (no ID required, no account) and a USB LTE modem. Huawei E3372, ZTE MF833, and Sierra Wireless RV55 are all well-supported on Linux. Cost: $20–40 for the modem, $25 for the SIM. The SIM activates before it ships — no setup step on your end.

On Linux the modem appears as /dev/ttyUSB0 (or similar). A quick check:

ls /dev/ttyUSB*     # before plugging in
ls /dev/ttyUSB*     # after — the new entry is your modem

The SMS Reader Module

Install pyserial and create a module your agent can call:

# sms_reader.py
import serial, re, time

MODEM_PORT = '/dev/ttyUSB0'
BAUD = 115200

def init_modem():
    m = serial.Serial(MODEM_PORT, BAUD, timeout=5)
    m.write(b'AT+CMGF=1 ')   # text mode
    m.write(b'AT+CNMI=2,2,0,0,0 ')   # push new SMS to serial
    return m

def read_otp(modem, timeout=90, sender_filter=None):
    deadline = time.time() + timeout
    sender = ''
    while time.time() < deadline:
        line = modem.readline().decode('utf-8', errors='ignore').strip()
        if line.startswith('+CMT:'):
            sender = line   # next line is message body
        elif sender:
            if sender_filter and sender_filter not in sender:
                sender = ''
                continue
            match = re.search(r'\d{4,8}', line)
            if match: return match.group()
            sender = ''
    return None

The sender_filter parameter lets you filter by sender name (e.g. "Google", "Coinbase") to avoid false positives from unrelated messages arriving during the wait window.

LangChain Integration

Wrap the reader as a LangChain tool using the @tool decorator:

from langchain.tools import tool
from sms_reader import init_modem, read_otp

modem = init_modem()   # initialise once at startup

@tool
def receive_sms_otp(sender: str = '', timeout: int = 90) -> str:
    """Wait for an SMS OTP. Optionally filter by sender name.
    Returns the OTP code as a string, or 'TIMEOUT' if none received."""
    code = read_otp(modem, timeout=timeout, sender_filter=sender or None)
    return code if code else 'TIMEOUT'

Add this to your agent's tool list and it can call it naturally within any workflow. A typical usage in a registration chain: the agent submits a phone number to a platform, calls receive_sms_otp(sender="Platform"), waits, and passes the returned code to complete verification — no human step.

n8n Integration

In n8n, expose the SMS reader as an HTTP endpoint using FastAPI or Flask, then call it from n8n's HTTP Request node:

# api.py
from fastapi import FastAPI
from sms_reader import init_modem, read_otp

app = FastAPI()
modem = init_modem()

@app.get("/otp")
def get_otp(sender: str = '', timeout: int = 90):
    code = read_otp(modem, timeout=timeout, sender_filter=sender or None)
    return {"otp": code, "success": code is not None}

In your n8n workflow: after triggering an SMS send on the target platform, add an HTTP Request node pointing to http://localhost:8000/otp?sender=Platform&timeout=90. The response JSON contains the OTP code, which you can pass to the next node in the workflow using an expression.

AutoGPT / OpenAgents Integration

For AutoGPT-style agents, register the SMS reader as a command in your plugin or command registry. The function signature should return a plain string (the OTP) so the agent can include it directly in subsequent actions without parsing. Ensure your system prompt includes a brief description of when to call it: "After triggering SMS verification on a platform, use receive_sms_otp to retrieve the code before proceeding."

Multiple Agents, Multiple Numbers

For setups where multiple agents need isolated numbers — common in multi-tenant or multi-account workflows — use one USB modem per agent, connected via a powered USB hub. Each modem appears as a separate serial device (ttyUSB0, ttyUSB1, etc.). Initialise a separate modem instance for each agent process. Simbotica allows up to three SIMs per order, making three-agent setups trivial to provision in a single transaction.

Acquiring the SIM Autonomously

If you're building an agent that needs to self-provision its own number — without any human interaction — Simbotica's order endpoint supports the x402 payment protocol. The agent POSTs to /api/submit-order-base, receives a 402 with payment terms, signs a USDC authorization with an EVM wallet, and re-POSTs with the payment header. The SIM ships to whatever address the agent specifies. No account, no API key, no human approval required. Documentation at simbotica.xyz/llms.txt.

Get the SIM Your Agent Needs

Physical SIM. No KYC. Real mobile number. Works with LangChain, n8n, AutoGPT, and any Python agent framework. $25.

Order Now →