Skip to content
Agent Consent Patterns

Pattern 12 ยท Trust & transparency

Credential Handoff

The safest secret is the one the machine never touches. When the job needs your password, the machine steps aside. You hand the secret to a keeper you trust, and the machine gets back a small key for this one job, never the secret.

The safest secret is the one the agent never holds. When a task needs a password or a card number, the agent should step aside and hand the exchange to something the user already trusts (a password manager, a passkey, the provider's own payment page), then take back only a scoped credential, never the secret itself.

Exclude the agent from the credential exchange by construction: sign-in and payment route to a trusted holder (password manager, WebAuthn authenticator, provider checkout) with the exclusion made legible, and only a task-scoped, expiring credential returns to the agent. Structural non-possession, not policied restraint.

Problem

Machines need secrets sometimes: to log in, to pay, to approve a charge. The easy trick is "just give me your password and I'll do it." That trick is a disaster. A secret the machine sees can get written down, tricked out of it by a hostile scroll, or used again later. You just handed your riskiest thing to your most trickable helper.

Worse: a password gives the machine more than the job needs. You wanted one flight booked. Now the machine holds a key to your whole account, reusable, forever. Every other rule on this site (smallest key, marked doors, visible leashes) breaks the moment the machine holds the keyring.

Agents need to do things that require secrets: sign in to a service, pay for a booking, authorise a charge. The tempting shortcut is to let the agent collect the password or card number: "just tell me your login and I'll handle it." That shortcut is a disaster. A secret the agent sees is a secret that can be logged, cached in a prompt, leaked through an injection, or replayed later. It hands the most dangerous thing the user owns to the least trustworthy point in the system.

The deeper problem is that a credential typed to the agent grants far more than the task needs. The user wanted to book one flight, and now the agent holds reusable, unscoped access to their whole account. Every principle elsewhere in this collection (least privilege, scoped grants, legible authority) collapses the moment the agent becomes the thing that holds the keys.

Tasks that require secrets tempt the architecture toward its worst configuration: the agent as credential collector. The objection is not that agents are malicious but that they are the system's maximum-exposure component: everything an agent sees enters a context window that gets logged, cached, retried across requests, and processed alongside adversarial content. A password in the prompt is one successful injection away from exfiltration, and unlike a scoped token it cannot be revoked by expiry; it must be rotated, account by account, after every suspected exposure.

The authority-theoretic failure is as serious as the leakage one. A raw credential is the maximally unscoped grant: it confers whole-account, reusable, unattributable access, and the service cannot distinguish agent action from user action, so every downstream control (per-scope permissions, receipts with authority attribution, revocation of the agent's access specifically) is severed at the root. One typed password silently converts a bounded delegation into full impersonation. This is why the pattern is load-bearing for the whole collection: Scoped Grant, legible authority, and the intersection bound all presuppose that the agent's access is a distinct, inspectable object, and a shared secret destroys that distinctness. The exclusion must be structural rather than policied ("the agent promises not to look" is not a security boundary), which is what separates this pattern from a privacy setting.

Solution

Keep the machine out of the secret-passing entirely:

  • Hand the exchange to a trusted keeper. The password goes to your password-keeper, your fingerprint-lock, or the shop's own pay-window: someone you already trust with this secret.
  • Draw the fence where everyone can see it. Say plainly: the secret goes from you to the keeper, never through the machine. The fence is the whole point. Make it visible.
  • Hand back only a small key. The machine gets a signed-in session, a one-use token, a "paid โœ“". Never the secret. Just enough for this one job, and it expires on its own.

Keep the agent out of the credential exchange entirely:

  • Hand off to a trusted holder. Route sign-in and payment to a password manager, a passkey/WebAuthn flow, or the provider's own payment page: a party the user already trusts with this secret.
  • Make the exclusion legible. State plainly that the secret goes from the user to that holder and never through the agent. The boundary is the point of the pattern, so it should be visible, not implied.
  • Take back only a scoped credential. What returns to the agent is a signed-in session, a one-time token, or a confirmation. Never the secret, and scoped to just the task at hand.

Restructure the flow so the agent is outside the credential path by construction:

  • Route the exchange to a trusted holder. Password manager, passkey/WebAuthn authenticator, or the provider's own checkout: a party whose trust relationship with this secret predates the agent. The user-to-holder channel bypasses the agent's context entirely; there is no prompt for the secret to enter.
  • Render the exclusion legibly. The boundary ("your password goes to the holder and the service; the agent never sees it") is stated on the surface, not implied by plumbing. Legibility here is dual-purpose: it lets the user verify the safe flow, and it trains the discrimination that makes phishing detectable. A surface that does ask for the password now reads as anomalous. An invisible boundary protects the credential but not the user's threat model.
  • Return only a scoped credential. The agent receives a session, one-time token, or confirmation: task-scoped, expiring, never the secret. The return leg is where least privilege is enforced: the derived credential's scope is the actual delegation, whatever the task claimed to need, so its boundaries (scope, TTL) are the delegation's real terms. This is also what keeps the agent's access a distinct, attributable, revocable object. That property is what every other pattern on this site builds on.

The structure mirrors tokenization and delegation-by-capability generally: possession of the root secret stays with the principal and their chosen custodian; the delegate operates on derived, attenuated instruments.

Live demo

Sign in to Delta

Booking your flight needs you to sign in. I'll hand this to your password manager rather than ask you to type it to me.

Password manager1Password
Your password goes straight to 1Password and Delta. The agent never sees it, and can't store or replay it.

The agent receives:

  • A signed-in session, scoped to this booking
  • Expires in 1 hour, no stored password

The card above is the real CredentialHandoff component from @agentconsent/react. Continuing hands the exchange to the password-keeper. What comes back is a key good for this booking only, never the password.

The demo is the CredentialHandoff component from @agentconsent/react. Continuing hands the exchange to the password manager; what comes back is a booking-scoped session, never the password.

The demo is the CredentialHandoff component from @agentconsent/react. Continue delegates the exchange to the password manager. The return leg is enumerated on the surface (a booking-scoped session with an expiry, never the password), so the derived credential's terms are part of the consent.

Anatomy

Anatomy of the Credential Handoff surface, with parts numbered as listed below.
  1. The task. What needs a secret, stated plainly ("Sign in to Delta", "Pay $340"), so the user knows exactly which exchange they're being asked to authorise.
  2. Trusted holder. Who the secret goes to instead of the agent (a password manager, a passkey, the provider's own payment page), named with its kind, so the user recognises something they already trust.
  3. Exclusion boundary. The pattern's heart: an explicit statement that the agent is outside this exchange. The password or card number flows from the user to the holder and never through the agent.
  4. What comes back. What the agent receives in place of the secret (a scoped session, a one-time token, a confirmation), so least privilege is visible: it gets exactly enough to finish the task.
  5. Continue. The primary action hands off into the trusted holder. It's a step out to a place the user controls, not a form that collects the secret in the agent's surface.
  6. Cancel. Backing out is always available and costs nothing, nothing is signed in, nothing is charged, and the agent has seen nothing either way.

When to use it

  • Every log-in. Passwords, fingerprints, one-time codes: send them through the keeper or the device's own lock, never the machine's own asking-box.
  • Every payment. Route to Apple Pay, a stored-card token, or the shop's own pay-window. The machine works from a pay-token, never the card numbers.
  • Every heavy secret. Recovery codes, API keys, signing keys: if the leak would hurt badly, hand off instead of holding.
  • Any sign-in. Passwords, passkeys, MFA: delegate to a password manager or the platform authenticator rather than collecting them in the agent's surface.
  • Any payment. Route to Apple Pay, a card-on-file tokeniser, or the merchant's own checkout, so the agent works from a payment token, not a card number.
  • Any high-value secret. Recovery codes, API keys, private keys: if leaking it would be serious, the agent should hand off rather than hold it.
  • All authentication. Passwords, passkeys, MFA, delegate to the password manager or platform authenticator. Passkeys are the limiting case worth designing toward: WebAuthn never transmits a shared secret at all, so the "secret in transit" the handoff protects simply doesn't exist.
  • All payment. Apple Pay, card-on-file tokenizers, or the merchant's own checkout. The agent operates on a payment token whose blast radius is bounded by the tokenizer, and which composes naturally with Spend & Rate Limits enforced at the instrument.
  • Any secret whose compromise is expensive to reverse. Recovery codes, API keys, private keys. The rotation cost of a leaked root secret is the metric; where it's high, structural non-possession beats any policy about careful handling.

When not to use it

  • Things that aren't secrets. A shipping address or a display name needs no keeper ceremony. Save the fence for real secrets.
  • Where a small key already exists. If the service was connected through a Scoped Grant, the machine already holds a job-sized key. It should never be asking for a password at all.
  • When you can't truly keep the machine out. A flow that looks like a handoff but still threads the secret through the machine is the sickness dressed in the cure's clothes.
  • Non-secret inputs. A shipping address or a display name isn't a credential; routing it through a handoff is pointless friction. Reserve this for secrets.
  • Where a scoped grant already exists. If the user has connected the service through a Scoped Grant or OAuth, the agent already has task-scoped access and shouldn't be prompting for credentials at all.
  • When you can't actually keep the agent out. Don't dress up a flow that still funnels the secret through the agent as a handoff, that's the anti-pattern wearing the pattern's clothes.
  • Non-secret inputs. Addresses and display names carry no replay value; ceremonializing them dilutes the handoff's signal. The boundary announcement must stay correlated with actual secrets or it stops teaching the threat model.
  • Where scoped access already exists. A standing Scoped Grant or OAuth connection is the derived credential; an agent with one that still prompts for passwords is either broken or phishing, and users should be entitled to assume the latter.
  • When the exclusion can't be made real. A flow that visually resembles a handoff while routing the secret through the agent (or agent-controlled infrastructure) is strictly worse than honest collection: it spends the pattern's trust vocabulary on a false claim, poisoning the discrimination the legible boundary exists to build. If the architecture can't support the exclusion, don't borrow its interface.

Real-world examples

  • 1Password's agent autofill. When a browsing machine hits a log-in wall, everything pauses for the human to approve with their fingerprint on their own device; the password then slips into the browser through a sealed channel. The machine gets a signed-in session. It never sees the password.
  • ChatGPT agent's takeover mode. At a log-in or pay screen, control flips to the human, who types straight into the page; the machine is shut out of that typing. The fence drawn the simplest way possible: secret goes person-to-site, never through the machine.
  • Apple Pay and passkeys. The before-machines gold standard: the shop gets a one-use token instead of your card numbers, and a passkey never sends a shared secret anywhere at all. Proof that "act for me without holding my secret" works for billions of people.
  • 1Password Secure Agentic Autofill. When a browser agent hits a login, the flow pauses for the human to approve via biometric on their own device; credentials are then injected into the browser session through an encrypted channel. The agent gets a signed-in session. It never sees the password.
  • ChatGPT agent's takeover mode. When a task reaches a login or payment form, control flips to the human, who types directly into the page; the agent is excluded from that input. The handoff boundary drawn in the simplest possible way: the secret goes person-to-site, never through the model.
  • Apple Pay and passkeys. The pre-agent ceiling to aim for: tokenization hands the merchant a one-time token instead of the card number, and a passkey never transmits a shared secret at all, proof that "act on my behalf without holding my secret" scales to billions of users.
  • 1Password Secure Agentic Autofill. The dedicated-custodian architecture: the agent's run pauses for human biometric approval on the user's own device, credentials inject into the browser session over an encrypted channel, and the agent resumes with a signed-in session. Notable for putting the approval on hardware the agent doesn't control. The consent channel is out-of-band from the compromised-context threat.
  • ChatGPT agent's takeover mode. The minimal viable exclusion: at login/payment forms, control transfers to the human, who types directly into the page with the model excluded from the input path. No custodian infrastructure required, which makes it the floor implementation, and its weakness (the human must notice when takeover is warranted) the argument for explicit boundary surfaces.
  • Apple Pay and passkeys. The pre-agent proofs of scale. Tokenization gives merchants one-time instruments instead of PANs (derived, attenuated credentials at billions-of-transactions scale); WebAuthn eliminates the shared secret entirely, making phishing structurally rather than behaviorally resistant. Together they establish that non-possession delegation is not exotic: it is how payments and authentication were already heading, and agents inherit the architecture rather than inventing it.

Annotated screenshots of these flows are being collected. Products are credited, annotations follow the site-wide callout conventions, and any screenshot is removed on request. See About.

Accessibility

  • The card is one named region, titled by the job ("Sign in to Delta"), so a screen reader announces the whole handoff as one thing.
  • The fence-sentence is a note, "the machine never sees it" gets spoken, not carried only by a drawn border.
  • The keeper's kind is a text badge (Password manager, Passkey, Payment, Provider), and what the machine gets back is a real list. The shape of the trade survives without eyes.
  • Continue and Cancel are ordinary buttons in a sane order; nothing traps focus here, because the handoff itself walks you into the keeper's own accessible flow.
  • The surface is a role="group" labelled by its task title, so assistive tech announces the whole handoff as one named region.
  • The exclusion boundary is a note, so the fact that the agent is excluded is announced to a screen reader. It isn't carried by the visual fence alone.
  • The trusted holder's kind is a text badge (Password manager, Passkey, Payment, Provider), and what the agent receives is a real list, so the shape of the handoff survives without vision.
  • Continue and Cancel are ordinary buttons in a logical order; nothing here traps focus, because the handoff itself moves the user into the trusted holder's own accessible flow.
  • The surface is a role="group" named by the task title. The handoff is one addressable decision, announced as such.
  • The exclusion boundary is a role="note": "the agent never sees it" enters the accessibility tree as content. The boundary is the pattern's central claim, and a claim carried only by a visual fence would be inaudible exactly where the phishing-discrimination training matters most.
  • The holder's kind is a text badge (Password manager, Passkey, Payment, Provider) and the return leg is a semantic list; custodian identity and derived-credential terms, the two facts the consent turns on, both survive non-visual rendering.
  • Continue and Cancel are ordinary buttons with no focus trap, deliberately, because the surface's job is to hand the user onward into the holder's own accessible flow; trapping focus at the boundary would make the handoff itself the obstacle.

Anti-patterns

  • The machine as keyholder. Letting the machine collect, keep, or reuse a password or card number. The exact thing this pattern exists to kill. If the machine can see it, it's already too exposed.
  • The fake handoff. A flow that looks like handing to a keeper but still threads the secret through the machine or its den. The fence must be real, not painted on.
  • The invisible fence. Handing off correctly but never saying the machine is shut out. So you can't tell this apart from a thief's box asking for your password. Say the fence out loud.
  • The oversized return-key. Taking back a forever, whole-account key instead of a this-job token throws away the entire point. The machine gets exactly enough to finish. No more.
  • Secrets typed into chat. "Paste your password here and I'll log in". The failure in its rawest form, training people to do exactly the thing that gets them robbed.
  • The agent as keyholder. Letting the agent collect, store, or replay a password or card number. The exact thing this pattern exists to prevent. If the agent can see it, it's already too exposed.
  • A fake handoff. A flow that looks like a delegation but still routes the secret through the agent (or a server the agent controls). The boundary has to be real, not cosmetic.
  • An invisible boundary. Handing off correctly but never telling the user the agent is excluded, so they can't tell this apart from a phishing prompt asking for their password. Make the exclusion legible.
  • Unscoped return. Taking back long-lived, full-account access instead of a task-scoped token squanders the whole point. The agent should get exactly enough to finish, and no more. This is the same least-privilege bound as everywhere else: the handoff must not hand the agent more than its principal meant to delegate.
  • Typing secrets into chat. "Paste your password here and I'll log in". The most direct version of the failure, normalising exactly the behaviour that makes users phishable.
  • The agent as keyholder. Collection, storage, or replay of raw credentials by the agent is the configuration the pattern exists to make unreachable. Exposure is a property of seeing, not of intent. A context window is a log, and a logged secret is a leaked one on a delay.
  • A fake handoff. Delegation theater: the visual grammar of a handoff over a flow that still routes the secret through the agent or agent-controlled infrastructure. Worse than honest collection: it counterfeits the trust signal, and each counterfeit degrades every genuine boundary's credibility.
  • An invisible boundary. A structurally correct exclusion that goes unstated is indistinguishable, from the user's side, from a phishing prompt. So it protects this credential while leaving the user's discrimination untrained for the next surface. The boundary must be legible to do its second job.
  • Unscoped return. Recovering long-lived, full-account access instead of a task-scoped token re-creates the raw credential's authority profile one layer up; the exclusion becomes cosmetic. The return leg is governed by the same least-privilege intersection bound as everywhere else. The derived credential must not exceed what the principal meant to delegate, in scope or in time.
  • Typing secrets into chat. The unmediated failure, and the behavioral externality is the worst part: every product that normalizes secrets-in-chat trains the reflex that phishing harvests, imposing costs on users far beyond the product's own boundary.

Code

import { CredentialHandoff } from "@agentconsent/react";
import "@agentconsent/react/theme.css";

<CredentialHandoff.Root onHandoff={continueInHolder} onCancel={backOut}>
  <CredentialHandoff.Header>
    <CredentialHandoff.Icon>๐Ÿ”‘</CredentialHandoff.Icon>
    <CredentialHandoff.Title>Sign in to Delta</CredentialHandoff.Title>
  </CredentialHandoff.Header>

  <CredentialHandoff.Handler kind="password-manager" name="1Password" />

  <CredentialHandoff.Boundary>
    Your password goes straight to 1Password and Delta. The agent never sees it.
  </CredentialHandoff.Boundary>

  <CredentialHandoff.Returns>
    <CredentialHandoff.Return>A booking-scoped session</CredentialHandoff.Return>
    <CredentialHandoff.Return>Expires in 1 hour, no stored password</CredentialHandoff.Return>
  </CredentialHandoff.Returns>

  <CredentialHandoff.Actions>
    <CredentialHandoff.Cancel>Not now</CredentialHandoff.Cancel>
    <CredentialHandoff.Handoff>Continue in 1Password</CredentialHandoff.Handoff>
  </CredentialHandoff.Actions>
</CredentialHandoff.Root>

Boundary renders a role="note" so the exclusion is announced; Handler names who holds the secret; Returns lists the scoped credential the agent gets back. This surface never collects the secret. It's a decision to hand off, not a form. All parts are unstyled primitives with data-acp attributes; skip theme.css and style them yourself, or override the --acp-* tokens to retheme.