Follow the Journey
3 min read

Vault Gets OTP

Two-factor authentication for AI agents

Vault stored secrets. API keys, database passwords, encryption keys.

But there's a class of secrets it couldn't handle: credentials with 2FA.

Log into Stripe? Need the password and the TOTP code.

Log into AWS? Need the password and the authenticator app.

AI agents can't reach for your phone. So they couldn't log in.

Now they can.

The problem

Two-factor authentication is great for security. Terrible for automation.

Your browser automation needs to log into a service. The service requires 2FA. The automation stalls, waiting for a code that only exists in your authenticator app.

So you either:
1. Disable 2FA (bad for security)
2. Use app-specific passwords (not always available)
3. Skip automating that service (limits what AI can do)

None of these are good options.

Vault now stores credentials

Not just API keys. Full credentials.

# Store a credential
vault set my-service \
  --type credential \
  --username "[email protected]" \
  --password "s3cr3t" \
  --otp-secret "JBSWY3DPEHPK3PXP"

Username. Password. OTP secret. All encrypted with AES-256-GCM.

OTP generation on demand

When an AI agent needs to log in:

# Get credentials
creds = BrainzLab::Vault.get_credential("my-service")
# => { username: "[email protected]", password: "s3cr3t" }

# Generate current OTP
otp = BrainzLab::Vault.generate_otp("my-service")
# => "847291"

The OTP is generated server-side. TOTP or HOTP. Standard algorithms.

The agent fills in the login form, types the password, enters the OTP. Login complete.

Integration with Vision

This is where it gets powerful.

Vision (our visual testing tool) can now test authenticated pages:

tests:
  - name: "Stripe Dashboard"
    url: "https://dashboard.stripe.com"
    credentials: "stripe-admin"  # References Vault
    steps:
      - fill: { selector: "#email", value: "${username}" }
      - fill: { selector: "#password", value: "${password}" }
      - click: "#submit"
      - fill: { selector: "#otp", value: "${otp}" }
      - click: "#verify"
      - screenshot: "stripe_dashboard"

Vision retrieves credentials from Vault. Generates the OTP. Completes the login. Captures the screenshot.

Fully automated. Fully secure.

MCP tools

Claude Code gets new capabilities:

vault_get_credential — Retrieve username and password.

vault_set_credential — Store new credentials.

vault_generate_otp — Get current TOTP/HOTP code.

vault_verify_otp — Validate an OTP (for building your own 2FA).

Ask Claude: "Log into the admin panel and check the user count."

Claude retrieves credentials from Vault. Generates the OTP. Uses browser automation to log in. Gets the data.

AI agents with secure credential access.

The security model

Credentials are encrypted at rest with AES-256-GCM.

OTP secrets never leave the Vault server—codes are generated server-side.

Access is logged. Every credential retrieval. Every OTP generation. Full audit trail.

Environment separation. Production credentials can't be accessed from development.

Why this matters

AI agents are only as capable as the systems they can access.

2FA was a wall. Services that require it were off-limits for automation.

Vault OTP removes that wall.

Now AI can:
- Test authenticated admin panels
- Automate tasks in 2FA-protected services
- Handle the full login flow without human intervention

The scope of what's automatable just expanded significantly.

Try it

# Store a credential with OTP
vault set github \
  --type credential \
  --username "[email protected]" \
  --password "your-password" \
  --otp-secret "YOUR_TOTP_SECRET"

# Generate an OTP
vault otp github
# => 847291

Secure credentials. On-demand 2FA. Full automation.

— Andres

Want to follow the journey?

Get Updates