Skip to main content
a credential item can hold passkeys in passkey fields. a browser attached to the item’s vault can then create a passkey on a website and sign in with it. KERNEL answers the page’s WebAuthn requests (navigator.credentials.create and navigator.credentials.get) and signs on its servers, so the private key never enters the browser, your application, or the model’s context. passkeys aren’t filled into pages. instead of fill, use three item operations: each operation returns immediately and has no time limit. your agent drives the website with its own browser tools; KERNEL only answers the page’s passkey requests.
while a passkey is armed, any script running on that website’s pages can obtain a sign-in without user interaction, as with a password manager that fills automatically. disarm as soon as the task is done.

Requirements

  • a credential item with provider: "kernel". see credential items.
  • a browser created with the item’s vault attached. use the browser’s session id in browser_id, not its name.
  • invoke an operation only when the item advertises it in available_operations. KERNEL rechecks eligibility when you invoke it.
  • SDK 0.131.0 or later for Node, Python, and Go, or CLI 0.50.0 or later.

Add a passkey field

a passkey field must be sensitive. add an optional, empty passkey field to an existing item with an update. a required passkey field needs a value when you add it, so use an optional field when KERNEL will create the passkey.
you can also declare the passkey field when you create the item. collection forms leave passkey fields out, so the item becomes ready once its other required fields have values.

Register a passkey on a website

invoke register_passkey with the browser’s session id, then have your agent open the website’s “add a passkey” flow in that browser. when the page calls navigator.credentials.create, KERNEL generates the passkey, stores it in the field, and only then returns it to the page. the website never receives a passkey that KERNEL failed to store.
field names an empty passkey field. omit it when the item has exactly one empty passkey field. the registration waits for the next passkey any page in that browser creates, so start it right before the website’s flow. each browser has one pending registration; a later register_passkey replaces it. after the website confirms the new passkey, the field reports has_value and the vault records a credential_passkey_registered event. sign in once with arm_passkey to confirm the website accepts it. KERNEL creates ES256 passkeys only; a website that doesn’t accept ES256 gets a NotSupportedError. to replace a stored passkey, clear the field or add another empty passkey field first. register_passkey only writes into an empty field.

Import an existing passkey

if you already hold a passkey, for example exported from a password manager, write it as the field’s value from your trusted backend. the value is a JSON-encoded passkey object from the FIDO Credential Exchange Format (CXF): other CXF members are ignored. keep the private key in trusted backend code; don’t put it in frontend code, agent prompts, command-line arguments, logs, or traces.
item reads never return the passkey. they report has_value for the field.

Sign in with a passkey

invoke arm_passkey, then have your agent sign in on the website as a user would, for example by selecting Sign in with a passkey. when a page in that browser whose origin matches the passkey’s relying party asks for a passkey, KERNEL answers with the armed passkey. this includes autofill requests that pages make as soon as they load.
status: "armed" means the browser will answer matching requests; it doesn’t mean a page has asked yet. pass field when the item has more than one passkey field holding a passkey. KERNEL builds each response from the origin Chrome reports for the requesting frame, not from what the page claims, and answers only pages on the passkey’s relying party. if the website lists the credentials it accepts, only a matching passkey answers. the vault records a credential_passkey_asserted event for each sign-in. a page opened in a new tab or window can run its first scripts before KERNEL’s handler attaches. if such a page asks for a passkey as soon as it loads, reload it.

Disarm

invoke disarm_passkey when the task is done. it removes the browser’s armed passkeys and its pending registration for the item. pass field to disarm one passkey field; omit it to disarm all of them.
pages that already loaded keep KERNEL’s handler, but they get the browser’s own passkey behavior after you disarm. an arm also ends when the browser ends, the vault is detached, or the item or field is deleted.

Use the CLI

Behavior and limits

  • arming a passkey for a website replaces any passkey armed earlier in the same browser for that website.
  • passkeys report a signature counter of 0 and set the backup flags, as synced passkeys do. websites don’t flag repeated sign-ins from different browsers as a cloned authenticator.
  • passkeys are never filled. fill rejects passkey fields, and passkey fields can’t be bindings for webmcp_invoke.
  • KERNEL-hosted collection forms and @onkernel/vault-react 0.4.0 and later leave passkey fields out. vault-react 0.2.0 can’t load an item that has a passkey field, so upgrade a custom form before adding one.
  • passkeys work only in browsers whose image supports them. on an older browser, arm_passkey and register_passkey return 409 with “browser does not support passkeys”.