Skip to main content

How do AI agents handle 2FA / MFA?

How do AI agents handle 2FA / MFA?
Lucas Giordano's avatarBy Lucas Giordano · Co-founder, Notte
Last updated · Published
TL;DR

AI agents handle 2FA by routing every verification channel — SMS code, email confirmation, TOTP secret — through a digital identity the agent owns. The identity holds an SMS-capable phone and a programmatically-readable email inbox; TOTP secrets sit in the attached credential vault. The agent reads the code from whichever side channel the site uses and types it back into the form, no human in the loop.

How do AI agents handle 2FA / MFA?

2FA is the wall where most agent products stop. The verification channel — phone, inbox, authenticator app — sits outside the browser by design, which means the agent can't see it. The pre-identity workaround was a human forwarding codes by hand; that scales to zero customers in zero days, and it's incompatible with anything async.

The problem 2FA causes for agents

Almost every meaningful service now requires a second factor. Three flavors, all hostile to traditional automation:

  1. SMS codes — a six-digit number gets texted to a phone. The agent doesn't have a phone, and the developer's phone can't be in the loop on every run.
  2. Email codes or magic links — sent to an inbox. Even if the agent has email access, it has to parse the message and either type the code or click the link.
  3. TOTP from an authenticator app — six-digit codes derived from a shared secret captured at enrollment time. Without that secret, the agent can't generate the next code.

Without identity-aware tooling, "agent plus 2FA" forced one of three bad choices: bypass 2FA on test-only accounts (works for internal tools, breaks on real ones), put the developer's phone or inbox in the loop (kills async runs), or hard-code session cookies after a manual login (expires within days).

How a Notte agent handles each 2FA channel

Each verification type maps to a primitive on the digital identity the agent attaches to:

  • SMS — the identity owns a real SMS-capable phone number (not a VOIP one that gets rejected). Incoming codes arrive at that number and the SDK exposes them to the agent.
  • Email codes / magic linksidentity.emails(only_unread=True, limit=10, timedelta=…) returns recent messages. The agent reads the code or follows the magic link.
  • TOTP / authenticator — the shared secret captured at enrollment is stored in the identity's credential vault alongside the password. The current TOTP value is computed at runtime and injected into the form via the same FillAction substitution as the password.

In practice the agent figures out which channel to wait on based on what the page asks for. You don't normally call .emails() or check the SMS inbox yourself — the agent does, then submits the code:

main.py
import datetime as dt
from notte_sdk import NotteClient

client = NotteClient()
identity = client.Persona(create_vault=True)
identity.add_credentials(url="https://example.com/")

with client.Session() as session:
    agent = client.Agent(persona=identity, session=session, max_steps=15)
    response = agent.run(
        task="Sign up at example.com and complete the email + SMS verification."
    )

# You can also inspect the inbox directly after the run:
recent = identity.emails(
    only_unread=False,
    limit=5,
    timedelta=dt.timedelta(minutes=10),
)

Common use cases

  • Sign-up automation that completes verification end to end — the most common reason teams reach for digital identities at all.
  • Multi-tenant products where each end-user has their own identity and therefore their own 2FA channels, with full per-user isolation.
  • Recovery flows where the agent has to read a recovery code or accept a security challenge that arrives by email.
  • Long-running authenticated scraping where the target site re-prompts for 2FA periodically and the agent needs to refresh without human help.

When agent-driven 2FA isn't the right answer

Some 2FA flows are too custom for any agent to navigate end to end: vendor-specific SSO, bank step-up auth with photo verification, sites that lock onto a single trusted device for life. The right move there isn't a smarter agent — it's a browser profile. A human (or you, the developer) completes the login once with persist=True; every subsequent agent session attaches the same profile and starts already authenticated. Identities and profiles are complementary primitives: identities for sign-ups and recurring 2FA the agent can solve, profiles for the flows it can't.

The other honest limit: passkeys aren't fully covered by either pattern yet — see what are passkeys for AI agents. For sites that require a passkey and nothing else, a human-in-the-loop step may still be the cleanest answer.

Key takeaways

  • 2FA breaks traditional automation because the verification channels (phone, inbox, authenticator) are all outside the browser the agent controls.
  • Notte gives the agent its own channels via a digital identity: real SMS phone, programmatic email, TOTP-aware vault.
  • The agent reads the code from the right channel automatically — typically you only call agent.run(task=…) and the verification step happens inside that.
  • Pair with credential vaulting for the password layer and digital identity for the rest of the persistent presence.

Build your AI agent on the open web with Notte

Cloud browsers, agent identities, and the Anything API — everything you need to ship reliable browser agents in production.