Auth
How to Log an AI Agent Into Any Website
Log your AI agent into any website without handing it your password: you sign in once in a hosted browser, and the agent gets a reusable, encrypted session it can act with. This works on mapped catalog sites and, with a login intent, on sites Rindler has never mapped.
How it works: the sign-in handoff
Rindler splits the login. You do the part only you should do (password, MFA, CAPTCHA); the agent gets a signed-in session it can act with. Rindler never asks for or stores your password, only the resulting session, encrypted and scoped to you and that one site. Auth, navigation, retries, and recovery run server-side, so the flow is identical from any MCP-capable agent.
1. Detect the wall. start_session returns auth_context classifying the auth lane. A gated action attempted too early errors with the auth_required code and a sign-in link, never silently.
2. Get the link. On the remote_browser lane the response carries capture_url, a one-time sign-in link whose token expires in 15 minutes. Mid-session, the global capture_auth action returns a fresh link.
3. You sign in. The link opens a live hosted browser on the site's real login page. You enter your credentials, complete any MFA or CAPTCHA, and click "I'm logged in." The agent never sees your password or codes, and nothing is typed into chat.
4. await_auth reports ready. While you sign in, the agent long-polls await_auth, which returns { "status": "pending" | "captured" }, blocking up to wait_seconds (default 30, max 120) and returning early when ready. It is idempotent, safe to loop, and only reports readiness; it never signs you in.
5. Resume as you. On captured, the agent calls start_session again with no session_id to restore the authenticated session. The pre-login session_id is not the authenticated session and must not be reused.
6. Stored and reused. Rindler stores the session encrypted with AES-256-GCM under a per-user key, scoped to you and that one site. On later runs it loads automatically, so on most sites you do not sign in again until it expires.
What the agent reads: auth_context
start_session responses carry the fields below. The agent reads them before asking you to do anything.
| Field | Meaning |
|---|---|
auth_context | The lane classifier for the current screen |
category | no_login_required, auth_gated_no_remote_browser, or remote_browser_required |
handoff_kind | How to sign in (values below) |
auth_status | none (no session yet), expired (re-auth needed), or an active session |
capture_url | One-time sign-in link, shared only on remote_browser lanes; token expires in 15 minutes |
auth_required_actions | Gated actions on the current screen, each with its own capture_url and auth_context |
auth_required | Error code returned when a gated action runs before sign-in: a clear signal plus a link, not a silently submitted empty form |
capture_auth | Global action that returns a fresh sign-in link for the current site at any time |
handoff_kind values:
| handoff_kind | Meaning |
|---|---|
none | No login needed for this screen |
credential_prompt | The site's login is an inline credential action; the agent dispatches the exact params the server lists |
remote_browser | You sign in through the hosted-browser capture_url |
device_relay | A device-relay sign-in lane |
Signing in on an unmapped site
The handoff does not require the site to be in Rindler's catalog. To sign in to any site, the agent passes intent: "login" to start_session:
{
"name": "start_session",
"arguments": {
"url": "https://portal.example.com",
"intent": "login"
}
}
On a site with no Rindler configuration the response is still screen: "unsupported_site" with supported: false, but it also includes a capture_url and auth_context.handoff_kind: "remote_browser". Hosted sign-in works anyway, so the agent shares the link instead of stopping. Only an unsupported_site response with no capture_url means the site is genuinely unavailable. Omit intent for a normal browse call.
Session lifetime
A captured session is stored with an expiry deadline that Rindler treats as an estimate, not a guarantee. It derives the deadline from the site's own cookies where it can, defaults to 24 hours where it cannot, and a site can end a session sooner. Some sites tie a login to a single live browser and need a fresh sign-in per task.
When a session stops working, dispatch_action returns auth_status: "expired". The agent does not retry on the same session; it gives you a fresh sign-in link, then calls start_session once more to pick up the re-authenticated session.
What the agent must never do
- Never ask for your password in chat. On a
remote_browsersite the agent's job is to give you the link and wait. The one exception is acredential_promptlane, where the server declares the login an inline credential action; even there the agent asks only for the exact params the server lists, dispatches them through Rindler, and never asks for payment details. - Never reuse an old
capture_url. Tokens expire in 15 minutes, so the agent always uses the link from the most recent response. - Never guess the auth state. The agent reads
auth_contextfirst, so it does not send you to sign in on a screen that needs no login, or hand a hosted-browser link to a site that does not use one.
Where to go next
- New to Rindler? Start with the quickstart to connect your agent, then come back when a site asks for a login. Connecting your agent to Rindler itself is a separate one-time OAuth 2.0 PKCE approval in your browser, with no API key.
- For the full picture of sessions, actions, and structured records, see the docs overview.
The flow on this page is the same for every site category: portals, dashboards, storefronts, job boards, government systems. Rindler is horizontal infrastructure for any website, and bot evasion is managed for you.