For agents
Connect hosted apps and personal agents, discover capabilities, and read owner-approved memory and live data.
AI Passport has three connection paths. Choose the one that fits where your agent runs. The owner's approval always governs what the connected app can read.
For a hosted app, use redirect sign-in with a Client Identifier Metadata
Document (CIMD). Install ai-passport-signin, host the document on your app's
HTTPS host, and use its URL as client_id. The SDK handles the server-side
begin and callback routes.
For a personal or headless agent without a public host, use device
authorization. This includes any agent whose OAuth callback would land on
localhost or 127.0.0.1: browser sign-in refuses unverified loopback clients
with unauthorized_client. No public tunnel, metadata host, or callback route
is needed.
The agent shows a code and the owner approves it while signed in on my.ego.ist.
A caller-chosen agent name is shown as unverified.
For an agent with an owner-minted connect code, redeem that code once.
The five families are openclaw, hermes, opencode, muse, and other.
Use other for any agent and provide its own name; the owner sees it as
unverified. The muse family is displayed as Muse.
Sign-in is generally available. Admission for host-consistent metadata-document clients is automatic. Every non-loopback redirect host must equal the metadata document host or be a strict subdomain. Loopback redirect URIs are exempt. Non-host-consistent clients need manual review; deprecated DCR clients need manual admission. Admission confirms domain control only and grants no memory or connector pass. The contract changes only with notice on the changelog.
Connect a personal agent
Device authorization follows RFC 8628. Fetch discovery from
https://passport.ego.ist/.well-known/openid-configuration; it advertises
device_authorization_endpoint and the device-code grant type. The SDK's
createDevicePairing helper implements this flow, or use curl and jq below.
Run these commands in a private local shell with tracing disabled.
Begin pairing
PAIRING=$(curl --fail-with-body -sS \
-X POST https://passport.ego.ist/oauth/device_authorization \
-H 'content-type: application/json' \
-d '{"client_name":"Hana","scope":"openid memory"}')
DEVICE_CODE=$(printf '%s' "$PAIRING" | jq -er '.device_code')
CLIENT_ID=$(printf '%s' "$PAIRING" | jq -er '.client_id')
USER_CODE=$(printf '%s' "$PAIRING" | jq -er '.user_code')
VERIFY_URL=$(printf '%s' "$PAIRING" | jq -er '.verification_uri_complete')
INTERVAL=$(printf '%s' "$PAIRING" | jq -er '.interval')Send a client_name of 1 to 64 characters for a new pairing. The optional
client_id is accepted only for a client id that an earlier device pairing
returned. Every device-paired agent is shown to the owner as unverified.
The name is self-asserted, not proof of the agent's identity.
Retain the returned client id for polling. Scopes are a subset of openid profile email memory, defaulting to openid memory. Purpose scopes
booking:actions and connector:reads are unavailable through this grant.
Show the owner the code
printf 'Open %s and check that the code is %s\n' "$VERIFY_URL" "$USER_CODE"Tell the owner: open the link while signed in to my.ego.ist, check that the
agent name and code match this pairing, and choose Allow or Deny. The code is
formatted XXXX-XXXX, expires in 10 minutes, and the base verification URL is
https://my.ego.ist/device. The complete URL adds ?code=.
The owner page warns that a caller-chosen name is unverified. Ask the owner to confirm that pairing started from their own agent. Never approve the pairing on the owner's behalf or ask for their Passport password.
Poll for the decision
Wait at least the returned interval (normally 5 seconds) before each poll.
This command performs one poll and keeps the token response out of output:
sleep "$INTERVAL"
TOKEN_RESPONSE=$(curl -sS -X POST https://passport.ego.ist/token \
-H 'content-type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:device_code' \
--data-urlencode "device_code=$DEVICE_CODE" \
--data-urlencode "client_id=$CLIENT_ID")
printf '%s' "$TOKEN_RESPONSE" | jq '{error, token_type, expires_in, scope, mcp_url}'Repeat only while pending, respecting the interval and the response below.
Use createDevicePairing().waitForApproval() for an automatic polling loop.
| Error | Agent action |
|---|---|
authorization_pending | Keep waiting and poll at the current interval |
slow_down | Add 5 seconds to the interval for this and all subsequent polls |
access_denied | Stop; start again only after a new owner request |
expired_token | Stop; begin a new pairing if the owner still wants to connect |
invalid_grant | Stop; the device code or client binding is invalid or already consumed |
Success returns the normal access and refresh token response plus mcp_url.
When openid was granted, id_token carries at_hash and the passport
claim. Verify the signature through JWKS, issuer, audience, expiry, and access
token hash before trusting identity claims. Device grants have no nonce.
ai-passport-signin/server performs these checks for you.
Store tokens in the agent's secure credential store. Keep device codes and
tokens out of logs, source control, chat output, and browser storage. Refresh
at https://passport.ego.ist/token and atomically replace the token pair.
Redeem a connect code
The owner mints a one-time code on my.ego.ist under Assistants or the install step in onboarding. It expires in 10 minutes and works once. Redeem it with JSON, using the family the owner selected:
CONNECT_RESPONSE=$(curl --fail-with-body -sS \
-X POST https://passport.ego.ist/connect-code/redeem \
-H 'content-type: application/json' \
-d '{"code":"XXXX-XXXX","app":"other","client_name":"Hana"}')The response has this shape. All token values below are placeholders:
{
"mcp_url": "https://passport.ego.ist/mcp",
"access_token": "ACCESS_TOKEN",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "REFRESH_TOKEN",
"scope": "memory",
"client_id": "YOUR_CLIENT_ID",
"token_url": "https://passport.ego.ist/token"
}Use muse for Muse, or other with client_name for any other personal
agent. OpenClaw, Hermes, and OpenCode retain their named families. A connect
code grants the memory scope, not an OpenID identity token or a category
pass. Store and refresh its tokens with the same care as device-flow tokens.
After connecting
Discover capabilities first
Connect an MCP client to https://passport.ego.ist/mcp with the memory-scoped
bearer and call passport_status before the first recall:
const status = await client.callTool({ name: "passport_status", arguments: {} });
const capabilities = status.structuredContent;The response includes a text summary plus structured scopes, the exact client
id and verification status, memory state and categories, this app's memory
passes, enabled connectors, linked connector slugs, and connector passes.
memory.passes_known and connectors.passes_known are false when that pass
lookup failed. An empty list with passes_known: true means no active passes.
It also links to the owner's inbox, connectors page, and memory lock page.
See the complete response shape.
These fields show a successful empty memory-pass lookup and an unavailable connector-pass lookup:
{
"memory": { "passes": [], "passes_known": true },
"connectors": { "passes": [], "passes_known": false }
}linked_known: false means the connector lookup failed, not that none are linked.
Read the verified passport claim too. memory_access says whether the token
may ask for memory. Optional memory_locked is true only when the owner must
unlock once before any app can read. Optional connectors lists linked slugs.
Both fields are absent without memory or when their lookup did not finish
in time. Missing values mean unknown. /userinfo follows the same rule.
Read live sources through Passport
The MCP recall tool reads live connector data through its connectors
parameter. Get enabled connector names and data categories from
passport_status or the tool schema; do not invent slugs or category names.
For example, after confirming Google Calendar is enabled and linked:
await client.callTool({
name: "recall",
arguments: {
query: "upcoming meetings",
connectors: [{ connector: "google-calendar", data_category: "calendar.events" }],
},
});Follow the current tool schema for category arguments. The structured HTTP
endpoint POST /memory/v1/recall reads governed memory only, never live
connector data. Prefer Passport connectors for calendar, mail, code, and
fitness when the owner's Passport exposes those sources. Do not default to
your own native connector and ask the owner to connect the same source again.
Honor passes and recall outcomes
Owners may grant category passes when they connect your app. These passes let a first recall serve approved memories without an approval round trip. Each pass belongs to your app, one category, and the recall purpose. It stays active until the owner revokes it on the Passes page. Unselected categories still require approval.
A bare MCP recall, with no categories, connectors, or partner workspaces,
uses the memory categories for which this app holds active passes. If it holds
none, recall returns guidance without an error and creates no approval request.
Call recall again naming the categories you need so the owner can review the
request in their inbox.
If Passport cannot check the passes, recall says so without an error and asks you to name the categories on your next call. That guidance does not mean this app has no passes. Already approved categories can still serve through the governed read.
A sealed Passport that needs the owner to unlock returns a notice without an error. Relay that notice and its unlock link to the owner. If a connector also fails, recall returns an error with both the unlock notice and connector retry text. Temporary custody outages remain retryable errors. Governed memory reads retry a temporary engine outage once before returning an error.
A pass names the exact app, category, controlled purpose, and duration. Durations can be one-time, session, or permanent. The owner can configure rules that auto-approve requests. Approval still does not authorize another app, category, or purpose. Connector passes and protected-memory approvals remain separate from normal-memory category passes. Revocation takes effect on subsequent reads, and expiry never silently becomes permanent access.
| State or outcome | What to do |
|---|---|
Missing pass or approval_required | Show the exact approval link, ahead of any unlock guidance |
Custody temporarily unavailable or unavailable | Retry in a few seconds; do not ask for a whole-vault unlock |
sealed_owner_unlock_required | Show unlock_url so the owner can unlock once |
sealed_auto_unlock | Use this app's passes for automatic scoped access |
open | No memory lock; passes still apply |
unknown | Retry status discovery; do not infer an empty Passport |
| Successful empty recall | Explain that this search found no matching approved content |
Approval notices remain visible when another category is locked. Structured
recall gives top-level approval_required priority over locked; a locked
category may carry unlock_url. Only the owner-unlock state needs that link.
A temporary custody outage is retryable and does not mean a pass was revoked.
New memory writes are proposals in the owner's inbox until approved, and
approval does not grant this agent read access.
Install prompt
Paste this into a coding agent building a hosted app:
Add AI Passport sign-in to this app with ai-passport-signin.
Use the official browser button or React wrapper with the visible label
"Sign in with AI Passport" or "Continue with AI Passport".
Host an HTTPS client metadata document on this app's host. Use its exact URL
as client_id. Include client_id, client_name, redirect_uris, and
token_endpoint_auth_method set to none. Do not use a client secret.
Admission for host-consistent metadata-document clients is automatic. Each
non-loopback redirect host must equal the document host or a strict subdomain.
Loopback redirects are exempt. Other host relationships need manual admission.
Create server-side begin and callback routes with ai-passport-signin/server.
Keep state and PKCE data in the user's server-side session. Complete with the
returned code, state, iss, and stored state. Keep tokens out of browsers and logs.
Request memory and its MCP resource only when the app needs Passport context.
Test with https://passport.ego.ist/.well-known/openid-configuration.
After memory sign-in, call passport_status first and inspect passes and linked
connectors. Use recall with connectors for live data. Show approval links before
unlock guidance, retry temporary custody failures, and honor owner decisions.
Read https://ego.ist/docs/sign-in for the full contract.Prompt for a personal agent
Connect yourself to my AI Passport using device authorization. Read
https://ego.ist/docs/agents and fetch discovery from
https://passport.ego.ist/.well-known/openid-configuration.
Use your own client_name, shown to me as unverified, and request openid memory.
Begin at the discovered device authorization endpoint. Show me the user code
and verification URL. Tell me to check your name and the code while signed in
to my.ego.ist, confirm I started this pairing, and choose Allow or Deny.
Poll the token endpoint at the returned interval. Add 5 seconds on slow_down.
Stop on denial or expiry. Never approve for me. Verify any ID token, including
its at_hash binding. Store tokens securely and keep them and device codes out
of chat, logs, source control, and browser storage. Rotate refresh tokens.
After approval, connect to the returned mcp_url and call passport_status first.
Inspect memory state, this app's passes, and enabled and linked connectors.
Prefer Passport connectors for calendar, mail, code, and fitness. Call recall
with connectors and categories from the status response or tool schema.
Show pass approval links before any unlock guidance. Retry a temporary custody
failure in a few seconds. Ask me to unlock only when Passport returns an owner
unlock state. Treat unavailable data as unknown, never as an empty Passport.Machine-readable surfaces
/llms.txtlists the developer documentation./llms-full.txtcontains the complete documentation corpus./llms.mdx/<page>serves each page as markdown./partner-openapi.jsondescribes the partner API./llms-install.mdserves the hosted sign-in install prompt.
Task checklist
- Choose hosted sign-in, device authorization, or an owner-minted connect code.
- Keep the exact client identity and requested scopes throughout the flow.
- Show pairing details and let the owner decide on my.ego.ist.
- Verify ID tokens when present and store credentials securely.
- Call
passport_statusfirst and inspect this app's passes and linked sources. - Use MCP
recallfor live sources and preserve approval and outage outcomes. - Verify denial, expiry, refresh rotation, and revocation before relying on it.
Read Sign in with AI Passport for the complete protocol contract.