Logins, secrets & profiles
Store write-only secrets the agent can type but never see, generate two-factor codes, and save sessions so later runs start signed in.
The agent can sign in to websites for you without the model ever seeing a password. You store each credential once in the vault, bound to the sites where it may be used, and pass its name to the run. The agent decides where a value goes. The value itself is decrypted and typed only at that moment, and only if the page is on a site you allowed.
| Option | Use it for | Stored |
|---|---|---|
| Vault secrets | Passwords, usernames, TOTP seeds you reuse | Encrypted until you delete it |
| Per-run secrets | A credential for one run only | Encrypted for the run, deleted when it ends |
| Profiles | Skipping the login on later runs | Cookies and local storage, encrypted |
| Credentials in the goal | Throwaway test accounts | In the run's goal text. Not recommended |
Store a secret in the vault#
PUT /v1/browser/vault/{name} stores a secret. Sending the same name again replaces it.
curl -X PUT https://lovelyrouter.com/v1/browser/vault/shop_password \
-H "Authorization: Bearer $LOVELY_API_KEY" \
-H "content-type: application/json" \
-d '{
"value": "correct-horse-battery-staple",
"kind": "password",
"origins": ["https://shop.example.com"]
}'The response confirms what was stored, without the value:
{ "name": "shop_password", "kind": "password", "origins": ["https://shop.example.com"], "stored": true }Secrets are write-only: no endpoint returns a value. You can also manage them in the console under Secrets & files. The Python and Node.js samples use the API, H and headers setup from Run your first task.
Secret fields
namestringRequiredIn the path. 1 to 64 characters: lowercase a-z, 0-9, _, ., -, starting with a letter or digit. The agent sees this name, so make it descriptive: github_password, not pw1.
valuestringRequiredThe secret, up to 4 KB (a larger value returns 413). For totp, the base32 seed.
kindstringDefault passwordWhat the value is. It decides which fields the agent may type it into.
originsarrayRequired1 to 20 sites where the secret may be typed, as https://host or https://*.example.com. https only, except http://localhost and http://127.0.0.1.
kind | Typed into | Notes |
|---|---|---|
password | Password fields only | |
username | Text, email, phone, search, URL and number fields | Not password fields |
text | Text, email, phone, search, URL and number fields | Any other value: account numbers, answers to security questions |
totp | Text, phone, number and password fields | Stored as the seed. The agent types the current 6-digit code |
Origins#
The agent may type a secret only when the page it is on, as the browser reports it, matches one of the secret's origins:
https://shop.example.commatches that exact site, and only over https.https://*.example.commatchesexample.comand every subdomain, such aslogin.example.com.
A secret is not even offered to the agent on any other site. If a lookalike phishing page asks for your login, the agent has no way to type the value there.
Use secrets in a run#
Pass the names in secrets. The run may use only the secrets you list.
curl https://lovelyrouter.com/v1/browser/runs \
-H "Authorization: Bearer $LOVELY_API_KEY" \
-H "content-type: application/json" \
-d '{
"goal": "Sign in and tell me the status of my latest order.",
"start_url": "https://shop.example.com/login",
"secrets": ["shop_user", "shop_password"]
}'The trace shows which secret went where, never the value: the step's action reads secret:e4:shop_password. A name that isn't in your vault returns 400 with Unknown vault secret(s): shop_pw. Store them with PUT /v1/browser/vault/{name}.
Two-factor codes#
For sites that use an authenticator app, store the TOTP seed as a totp secret. The seed is the text behind the QR code you scan when you turn on two-factor login (often shown as "can't scan the code?"): 16 or more characters of A–Z and 2–7. Spaces and dashes are ignored.
curl -X PUT https://lovelyrouter.com/v1/browser/vault/github_totp \
-H "Authorization: Bearer $LOVELY_API_KEY" \
-H "content-type: application/json" \
-d '{"value": "JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP", "kind": "totp", "origins": ["https://github.com"]}'When the site asks for the code, the agent types the current one (standard 6-digit, 30-second codes). Pass the seed's name in secrets with the username and password.
For codes sent by text message or email, let the agent ask you: it pauses with a question and you reply with {"secret": "481923"}. See Answer a question.
Per-run secrets#
When you don't want to store a credential, for example one your own users give you for a single task, pass it in ephemeral_secrets. It works like a vault secret, but lives only for the run: it is stored encrypted while the run is live and deleted when it ends.
{
"goal": "Sign in and tell me the account's plan name.",
"start_url": "https://app.example.com/login",
"ephemeral_secrets": {
"customer_email": { "value": "ada@example.com", "kind": "username", "origins": ["https://app.example.com"] },
"customer_password": { "value": "s3cret-pa55word", "kind": "password", "origins": ["https://app.example.com"] }
}
}Names follow the vault rules, and must not repeat a name you also pass in secrets. kind defaults to password, and origins is required.
Credentials in the goal#
If the goal itself contains a password ("log in as demo / demo1234"), the agent can type it into the password field. This works, but the goal is sent to the model, returned in the run object and kept in your run history. Use it only for throwaway test accounts. For anything real, use a vault or per-run secret.
Save and reuse a session#
A profile is a saved browser session: the cookies and local storage of the sites a run visited. Save one after a login, and later runs start signed in, with no secrets and no two-factor prompt.
Save a profile with save_profile (a name up to 64 characters):
{
"goal": "Sign in to the shop and tell me my name as shown on the account page.",
"start_url": "https://shop.example.com/login",
"secrets": ["shop_user", "shop_password", "shop_totp"],
"save_profile": "shop-login"
}When the run ends, profile_saved in the run object shows what was saved:
{ "profile_saved": { "id": "prof_4c1e9a7b2d0f3e5a8b6c", "name": "shop-login", "cookies": 14 } }Start a later run from it with profile (its name or id):
{
"goal": "Open my orders and tell me the status of the latest one.",
"start_url": "https://shop.example.com/account/orders",
"profile": "shop-login"
}- Saving under an existing name updates that profile. To keep a session fresh, pass the same name as both
profileandsave_profile. - The profile is saved whatever the run's final status.
- Sessions expire on the website's schedule. When a profile stops working, run the login again with
save_profile. Passing thesecretsalong withprofilelets the agent sign in again on its own if the session has expired. - An unknown profile returns
400withUnknown profile "shop-login" (GET /v1/browser/profiles). - A profile holds live session cookies. Treat it like a password and delete the ones you no longer need.
Manage secrets and profiles#
# List secrets: names, kinds, origins and dates, never values
curl https://lovelyrouter.com/v1/browser/vault -H "Authorization: Bearer $LOVELY_API_KEY"
# Delete a secret
curl -X DELETE https://lovelyrouter.com/v1/browser/vault/shop_password -H "Authorization: Bearer $LOVELY_API_KEY"
# List profiles
curl https://lovelyrouter.com/v1/browser/profiles -H "Authorization: Bearer $LOVELY_API_KEY"
# Delete a profile by name or id
curl -X DELETE https://lovelyrouter.com/v1/browser/profiles/shop-login -H "Authorization: Bearer $LOVELY_API_KEY"Each secret in the list shows last_used_at, so you can see when a run last typed it. The API reference has the full response shapes.
How your secrets are protected#
- Encrypted at rest. Secrets, per-run secrets, profiles and uploaded files are encrypted with AES-256-GCM, under keys derived separately for your account and for each run. Each value is bound to its owner and name, so it can't be decrypted as anyone else's or under another name.
- Write-only. The API never returns a secret value, to you or to anyone with your key.
- Never sent to a model. The agent works with names like
shop_password. The value is decrypted only at the moment it is typed, after the page's site and the field type have been checked. - Scrubbed from output. Any secret value of six characters or more that shows up in page text, the answer,
dataor the step trace is replaced with[secret:<name>]. In accurate mode, screenshots stop once a secret has been typed. - Short-lived when you want it. Per-run secrets and secret replies are deleted when the run ends.
Your API key can use the vault, so protect it like the secrets themselves. Limit what a key can do in API keys and turn on two-factor login for your account in Account security.