LOOMAL
Stop sharing

Stop being the 2FA device
for your AI agent.

If your agent pings you for a 6-digit code every time it logs in, you've rebuilt the bottleneck the agent was supposed to remove. Give the agent its own TOTP.

Half the agent demos that look impressive fall apart in production because some service requires 2FA. The login screen asks for a code, the agent doesn't have one, the agent pings Slack to ask a human, the human is asleep, the workflow stalls until morning.

The instinct is to disable 2FA on the target account. That's the wrong fix. The right fix is to give the agent its own TOTP store, so it can answer the challenge the same way a human does — by generating a code from a shared secret and typing it in.

Why borrowing the human's authenticator breaks

The naive workaround is the agent reads codes off the developer's phone. This works for one agent doing one thing, once a day, when the developer is awake. It does not work for an agent running overnight, an agent serving a thousand users, or any workflow where the human is the bottleneck the agent was built to remove.

The less naive workaround — the agent gets access to the developer's full authenticator app — is worse. It gives the agent a credential it has no business holding (the second factor for every account the developer has), and it destroys the audit boundary between human and agent actions.

What agent 2FA actually looks like

TOTP is not magic. It's a shared secret — the thing encoded in the QR code when you set up Google Authenticator — plus the current time. Any code that holds the shared secret and knows the time can generate the six digits the login screen asks for.

Agent 2FA means the agent holds the shared secret. Not a human's shared secret; the agent's own, enrolled once against the target service. When the service challenges, the agent generates the code from its own store and submits it. The human is not in the loop because the human doesn't need to be — the agent is answering for itself.

Isn't this just making 2FA weaker?

It would be, if the agent's TOTP secret sat in an .env file. It doesn't. In a properly-shaped agent identity, the TOTP secret is encrypted at rest, readable only by the agent's identity, and revocable as a single operation. The threat model is no weaker than a human with a password manager that holds TOTP secrets — which is to say, comparable to the majority of 2FA deployments already in use.

The security win is scoping. A compromise of the agent's TOTP store exposes only the accounts that agent has legitimately enrolled for. There's no crossover to the human operator's personal accounts, which is exactly the failure mode you were trying to prevent.

The Loomal version

Loomal's vault includes a TOTP store. Enroll an account once — paste the otpauth secret via the REST API or scan the QR from the agent's provisioning tool. The secret is encrypted at rest, never returned in plaintext. The agent calls vault.totp with a label and gets the current six-digit code.

Combined with vault.get for passwords and mail.list_messages for email-verification codes, the same agent identity can complete a full login flow against most services on the open internet without a human in the loop.

FAQ

What about SMS-based 2FA?

Harder — SMS goes to a phone number, not an API. For critical services, push the vendor to offer TOTP (most now do). For the rest, services like Twilio can receive SMS to a number the agent polls, but it's a last resort.

Can I enroll the agent's TOTP for my own accounts?

You can, but you're back to the 'agent has credentials for humans' problem. Better to create a separate account for the agent on the target service, and enroll the agent's TOTP against that.

Does this cover WebAuthn / passkeys?

Not directly — passkeys are a different cryptographic primitive. For services that only support passkeys, you'll need platform-specific handling. TOTP remains the dominant 2FA factor across most services agents care about.

Give your agent its own identity.

Free tier, 30-second setup.

Last updated: 2026-04-15