Headless Extension Connect
The Anima browser extension links an agent to a real browser so it can autofill vault credentials and drive logins without any secret entering the model’s context. Normally a person installs the extension and clicks Connect. For automation — a Puppeteer worker, a scheduled scraper, a partner integration — there is no person to click. Headless connect closes that gap: mint a one-time connect URL with the API, open it in the headless browser, and the extension binds its bridge to the agent automatically.The connect response never contains a token or a secret.
connectUrl itself carries a short-lived, single-use exchange code; the extension redeems it out of band. Nothing sensitive passes through the model.The flow
Mint a connect URL
Call
POST /v1/extension/connect. The API returns a connectUrl pointing at the console connect page, carrying a single-use exc_auto_… exchange code.Open it in the headless browser
Navigate the automation browser (with the Anima extension loaded) to
connectUrl. The exc_auto_ prefix tells the page to relay the code to the extension automatically — no click.Auth model
Who you authenticate as decides whether you passagentId:
| Credential | agentId | Behavior |
|---|---|---|
Master key (mk_) | Required | Selects which agent the extension connects as. |
Agent key (ak_) | Omit | The server resolves the agent from the key. Passing another agent’s id is rejected. |
session and pre_approved. The prompt_owner policy is not supported — there is no owner to approve an unattended connection, so the API rejects it:
pre_approved, the target agent must be on the org’s pre-approved allowlist (configure it under Settings → Extension in the console), or the request is rejected.
ttl
ttl is optional and shorten-only: "15m" | "1h" | "session". It may only be shorter than — or equal to — the org’s configured maximum. A value longer than the org policy is rejected rather than silently downgraded, so you learn the org forbids that lifetime instead of quietly getting a shorter one. Omit ttl to use the org default. A "session" TTL has no wall-clock expiry, so expiresAt comes back null.
The separate exchangeExpiresAt is the deadline for redeeming the connect URL itself (a single-use handoff window, ~60 seconds) — distinct from expiresAt, the lifetime of the resulting connection.
Mint a connect URL
Response
| Field | Type | Description |
|---|---|---|
agentId | string | The agent the extension will connect as. |
connectUrl | string | URL to open in the headless browser. Carries the single-use exc_auto_… code. |
expiresAt | string | null | When the resulting connection expires. null for a session TTL. |
exchangeExpiresAt | string | Deadline to redeem connectUrl (single-use handoff window). |
policy | "session" | "pre_approved" | The policy governing the session. |
Puppeteer worker recipe
End to end: mint the URL, launch Chrome with the automation bundle loaded, open the URL, and wait for the bridge.--headless=newis required. Chrome’s old headless mode cannot load extensions at all.- A fresh browser profile connects with no prompt. The
exc_auto_code auto-relays on page load. - Re-connecting a profile that already holds a live bridge requires confirmation. An unattended page must not silently replace an existing connection — the extension asks the owner to approve the re-pair, and denies otherwise. For a clean worker run, start from a fresh profile.
Related
- Vault — Browser Extension — how the extension performs credential autofill without exposing secrets.
- Vault — per-agent encrypted credential storage and the secret boundary.
- Security — key types (
mk_vsak_) and the master-key model.
