# How AI agents can log in without seeing your passwords

> Compare 1Password Agentic Autofill, Bitwarden's Agent Access SDK, Browser Use sensitive data, OAuth token vaults, and why passkeys still block AI agents.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2026-09-08 | Topics: [AI](https://flaviocopes.com/tags/ai/) | Canonical: https://flaviocopes.com/ai-agent-passwords/

Someone asked me this a few days ago:

> Is there a 1Password-like solution for AI agents? Something that lets the agent use the passwords and passkeys I saved, so it can log in to my bank or an airline and manage stuff for me. Is that what 1Password Developer Environments is for?

The short answer: no, Environments is the wrong product. The right one is called **Agentic Autofill**, and 1Password is not the only company working on this.

The longer answer is this post. I want to explain what the actual problem is, how the different solutions attack it, and where each one stops working. Banks and passkeys come up at the end, because that part of the question has a less comfortable answer.

## The real problem is the model, not the agent

When we say "give the agent my password", what we mean in practice is "put the password somewhere the language model can read it".

That is the thing to avoid.

Everything a model reads can end up somewhere else. It can be echoed back in a reply. It can be written to a log. It can appear in a screenshot the agent takes to understand the page. It can be sent to the provider as part of the conversation. And if a web page contains hidden instructions, a prompt injection can tell the model to type the password into a form on another site.

So the goal is not "the agent can log in". The goal is **the agent can log in while the model never holds the secret**. Once you frame it this way, the solutions become easy to sort.

There are four patterns in use today. I'll go through them from worst to best.

## Pattern 1: paste the credentials in the prompt

This is what most people do the first time. You write "log in with user flavio@example.com and password hunter2" or you put the values in a `.env` file the agent can read.

It works, and it is the worst option. The password is now in the model context, in the conversation history, probably in a log file, and in whatever the agent decides to do next.

Don't do this for anything you care about. For a throwaway test account on your own staging server, fine.

## Pattern 2: let the agent use your logged-in browser

This is what agentic browsers do. ChatGPT Atlas, Perplexity Comet, and Claude in Chrome all run inside a browser profile where you are already signed in to your accounts.

The agent never types a password. It rides on your cookies.

That sounds safer, and in one way it is: no secret is typed anywhere. But the blast radius is your entire logged-in life. If a page manages to inject instructions, the agent can act on any site where you have a session. Your email, your calendar, your bank if you left that tab open.

The vendors know this. ChatGPT agent pauses when it hits a login page and asks you to take over the browser, and it stops taking screenshots while you type. Atlas has a "logged out" mode where the agent starts with a clean profile, and a "watch mode" that forces you to keep the tab visible on sensitive sites. These are decent mitigations. They are not a credential solution. They are a way of saying "we know this is risky, please watch".

If you use this pattern, my advice is to give the agent its own browser profile with only the accounts it needs, and nothing else.

## Pattern 3: the password manager fills the form, the model sees a placeholder

This is where things get interesting, and this is the answer to the original question.

The idea: the agent knows *that* a login is needed and *which* saved item to use. It does not know the value. When the agent reaches the login form, it asks the password manager to fill it. The password manager checks with you, fills the fields directly in the page, submits, and hands control back.

The model only ever sees something like "login for lufthansa.com, username flavio". Never the password. Never the one-time code.

Two password managers ship this today.

### 1Password Agentic Autofill

1Password calls it [Agentic Autofill](https://www.1password.dev/agentic-autofill), and the first consumer integration is [1Password for Claude](https://support.1password.com/1password-claude/), launched in July 2026 for Claude in Chrome.

Here is the flow when Claude needs to sign in during a task:

1. Claude reaches a login page and asks 1Password for a credential that matches the site.
2. 1Password shows you a prompt on your device: which item, for which site, requested by which agent. You approve with Touch ID, swap to a different account, or deny.
3. The 1Password extension fills the username, password, and one-time code directly into the page and submits the form. While this happens, Claude is paused. It does not read the page.
4. 1Password checks that the submission went through and that no secret is left in a field. If the login failed, it wipes the filled values before Claude looks again.

What Claude gets back is a status: success or failure. Plus, before the fill, an overview of the items you approved: title, username, and the websites saved on the item. That is the same information you see in 1Password's own inline suggestions. Enough to pick the right account, never the secret.

Two details are worth knowing.

The first is **Agentic Mode**. As soon as a compatible agent takes control of a tab, the 1Password extension locks itself down in that tab. The inline suggestions disappear, the popup is hidden, and only the items you approved for the current task are reachable. This kicks in even if you never set up the Claude integration. It is 1Password protecting itself from agents in general.

The second is scope. Approval is per session and per item. When the task ends, the access ends. Nothing carries over to the next task.

There is also a developer-facing version. Since October 2025, Agentic Autofill has been in early access with [Browserbase](https://www.browserbase.com/), the cloud browser platform. There the 1Password extension runs inside the headless browser, and your desktop app and Browserbase talk over an end-to-end encrypted channel. Same approval prompt on your machine, but the browser is in the cloud.

Limits, as of when I write this:

- It fills Login items: username, password, TOTP. It also handles "Sign in with Google" style buttons.
- **Passkeys are not supported.** More on why below.
- On 1Password Business, an admin has to turn on the "Allow AI agents to autofill for users" policy first.
- Every fill needs a human tap. There is no "run overnight" mode. That is deliberate.

And to close the loop on the original question: [1Password Developer Environments](https://flaviocopes.com/1password-environments/) is a different product. It stores `.env` style secrets (API keys, database URLs) and hands them to your scripts through a mounted file or `op run`. It is great for giving a coding agent the API keys a project needs, and I wrote about [using it with Cursor](https://flaviocopes.com/1password-cursor/). It has nothing to do with logging in to websites.

There is a third 1Password product that gets mixed up in this conversation: [Credential Broker](https://www.1password.dev/brokered-access), in public preview since July 2026 for Business accounts. It sits on top of Environments and answers a different question: how does a *machine* prove who it is before it gets secrets?

The workload (a GitHub Actions job, a Kubernetes pod, an agent runtime) presents an OIDC token. 1Password checks the token's claims against a trust policy an admin defined, such as "only jobs from this repository, on this branch". If they match, the workload receives the secrets from the connected Environment for the duration of the job, and the delivery is logged with the workload's identity. No long-lived service account token sits in the CI config.

So: Agentic Autofill is for an agent logging in to a website on your behalf, with you approving. Credential Broker is for an unattended workload fetching API keys, with its identity doing the approving. Same vault, two different doors. If you run agents in CI or on a server rather than in your browser, the broker is the one you want, and it is closer in spirit to the OAuth pattern I describe below than to the password-filling pattern.

### Bitwarden Agent Access SDK

Bitwarden took a different route. In March 2026 they published the [Agent Access SDK](https://github.com/bitwarden/agent-access), an open protocol for the same problem.

The shape is similar:

1. You pair an agent with your Bitwarden client once, through a small CLI.
2. When the agent needs a credential, it sends an encrypted request for one specific item.
3. The request lands on your device. You approve or deny it in the CLI.
4. If approved, that one credential travels back through the encrypted tunnel and is injected into the agent's process as environment variables. The tunnel closes. Next time, the whole thing repeats.

The encryption uses the Noise protocol, and the relay in between routes ciphertext without being able to read it. Bitwarden is explicit that this is an open standard other password managers could adopt, and that it is an early alpha meant for developers exploring the pattern, not for production.

The difference from 1Password is where the secret ends up. 1Password fills the web page itself. Bitwarden hands the value to a process you control. That makes it more flexible (it works for any tool, not only browsers) and slightly less airtight (the process that receives the variable has to be one that does not feed them to the model).

One thing to not confuse it with: Bitwarden also ships an [MCP server](https://github.com/bitwarden/mcp-server). That one lets an AI assistant read and manage your vault through the `bw` CLI. Useful for "generate a password and save it", but the values do go through the model. Bitwarden themselves recommend using it only with a local, self-hosted LLM. It is not the tool for the login use case. If you are new to MCP, my [free MCP course](https://flaviocopes.com/courses/mcp/) explains what a server like that actually exposes.

### Doing it yourself with Browser Use

If you are building the agent rather than using a product, the same placeholder idea is built into [Browser Use](https://docs.browser-use.com/), the open-source browser agent library.

You pass secrets in a `sensitive_data` dictionary. In the task you refer to them by name. The model sees only the names. When the model decides to type `x_pass` into a field, the library swaps in the real value at the DOM level, after the LLM call.

```python
from browser_use import Agent, Browser, ChatOpenAI

agent = Agent(
  task='Log in to lufthansa.com with x_user and x_pass, then open My bookings',
  sensitive_data={
    'https://*.lufthansa.com': {
      'x_user': 'flavio@example.com',
      'x_pass': 'the-real-password',
    },
  },
  browser=Browser(allowed_domains=['*.lufthansa.com']),
  use_vision=False,
  llm=ChatOpenAI(model='gpt-4.1-mini'),
)
```

Three settings matter here.

Scoping the credentials to a domain means they can only be filled on that domain. Without it, a prompt injection could steer the agent to another site and type your password there.

`allowed_domains` stops the browser from navigating anywhere else at all. The library warns you if you set `sensitive_data` without it.

`use_vision=False` stops screenshots from going to the model. A screenshot of a filled password field is a password in the model context.

For TOTP, you pass the shared secret under a key ending in `bu_2fa_code`, and the library generates a fresh code when the agent needs one.

Notice what this does and does not solve. The model never sees the values. But *your script* has them in plaintext. You still need to get them from somewhere safe, which is exactly where `op run` from 1Password or the Bitwarden SDK come in. The two layers compose.

## Pattern 4: skip the login page, use OAuth

Everything above assumes the agent has to go through a web login form. Sometimes it doesn't.

If the service you want the agent to use has an API with OAuth, the cleaner path is delegation: you log in once, you consent to a scope, and the agent gets a token limited to that scope. No password ever exists on the agent side. You can revoke the token without changing your password.

There is a small industry of "token vaults" for this now. [Arcade](https://www.arcade.dev/), [Nango](https://nango.dev/), and Auth0's Token Vault all store per-user OAuth tokens, refresh them, and inject them into tool calls so the model never sees them. If you are building agents that touch Google Workspace, GitHub, Slack, or similar, this is the right layer, and it is a much better fit than driving a browser.

The catch for the original question: your bank and your airline do not give you an OAuth API for your personal account. There is no scope to consent to. The login form is the only door. That is why the browser-fill pattern exists at all.

## Why passkeys don't work with agents yet

The question mentioned passkeys, and every product above says the same thing: not supported. This is not laziness. It is by design.

A passkey login is a [WebAuthn](https://flaviocopes.com/passkeys-webauthn/) ceremony. The site sends a challenge, the authenticator on your device signs it with a private key, and the site verifies the signature. Before signing, the authenticator requires **user presence**: a fingerprint, a face, a PIN, a tap on a security key. The whole point is that a human touched the device right now.

An agent cannot produce that gesture honestly. It could ask you to touch the sensor, and that is what happens today: the agent pauses, you unlock the passkey, the agent continues. But that is the human logging in, not the agent. And it means no unattended runs on passkey-only sites.

The workaround people use is to bootstrap a browser profile by hand, complete the passkey login yourself, and let the agent reuse the resulting cookies. That is pattern 2 with a narrower profile. It works until the session expires.

The longer-term direction is delegation rather than impersonation: you authenticate with a passkey, you consent to a scoped mandate, and the agent receives a short-lived token that says "acting on behalf of Flavio, for this task, until this time". That is what Visa and Mastercard are building for agent payments, and what the OAuth token-exchange work at the IETF describes. It is not something you can set up for your bank this year.

## About banks and airlines specifically

I'd separate the two.

An airline account is mostly low-stakes. Checking a booking, picking a seat, adding a frequent flyer number. If 1Password for Claude fills the login and you approve each fill, I think that is a reasonable use of an agent, with one condition: anything that spends money should pause for you. I wrote about [how to make an agent stop before irreversible actions](https://flaviocopes.com/ai-agent-irreversible-actions-safely/) and buying a ticket is exactly that kind of step.

A bank is different. Banks use passkeys, hardware tokens, app confirmations, and device binding precisely to make automation impossible, and most of them forbid it in their terms. The credential problem is solvable with the tools above. The rest is not, and I would not try. Read your balance through the bank's own export or through an aggregator with a proper API, if you have one.

## How I would use this

I keep my passwords and TOTP codes in 1Password already, so Agentic Autofill is the option I would try first.

The first thing I would do is open a separate Chrome profile just for Claude, sign in to nothing, and let 1Password be the only way into any account. That removes the logged-in browser problem before it starts.

Then I would approve fills for the boring accounts: the domain registrar dashboard where I check renewals, the analytics for my sites, the newsletter tool where I want a monthly export. These are the tasks I actually delegate to agents today with API keys stored in 1Password Environments. Agentic Autofill would extend that to services that only have a web UI.

For the agents I build myself, the ones that run inside a script with Browser Use or a plain Playwright session, I would keep the credentials in a 1Password vault and load them at runtime with `op run`, then pass them as `sensitive_data` scoped to the one domain they belong to. Two layers: the vault keeps the plaintext off disk, the placeholder keeps it away from the model.

Credential Broker would fit the one place where I already have secrets sitting in CI: this site has a GitHub Actions workflow that hits a Cloudflare deploy hook every morning to publish scheduled posts, and the hook URL lives in a GitHub secret. With the broker, the job would prove it is *that* workflow in *this* repository and fetch the URL from an Environment at runtime. It is a Business feature, so for a one-person setup it is more than I need, but that is the shape of it.

Where I would not use any of this:

- Anything passkey-only. It cannot work unattended, so there is no point automating it.
- My bank. See above.
- Any account where a wrong click costs money or deletes data, unless the agent stops for confirmation before the click.
- Shared or work accounts under someone else's admin policy, until the admin has turned the feature on deliberately.

If you want the background on why the isolation matters so much, my free [Security Fundamentals course](https://flaviocopes.com/courses/security-fundamentals/) covers trust boundaries, which is really what this whole post is about. The agent is on one side. Your secrets stay on the other. The password manager is the only thing allowed to cross.
