Identity Lifecycle
Agent Identity Lifecycle
Last updated: January 2026
This doc describes how agent identities (OAuth-based) are created, connected, refreshed, and revoked. For route reference see API.md and API_ENTRY_POINTS.md.
Overview
- Identity = one OAuth connection per agent per provider (e.g. Google, Microsoft). Used so an agent can act as a user (e.g. read calendar, send email).
- Flow: Create identity → connect (user completes OAuth in browser) → callback exchanges code for tokens → tokens stored encrypted. Refresh before expiry; revoke to disconnect.
1. Create identity
POST /api/agents/:id/identity
Body: { "provider": "google" | "microsoft", "emailAlias?: string", "scopes?: string[]" }
Creates a record; status is inactive until connect completes.
2. Connect (start OAuth)
POST /api/agents/:id/identity/:identityId/auth/connect
Returns { "connectUrl": "https://..." }. Redirect the user (or open in a new tab) to connectUrl. The user signs in with the provider; the provider redirects back to your callback URL.
3. Callback URL (redirect URI)
The backend must be reachable at this URL for the OAuth redirect:
{BACKEND_BASE}/api/agents/auth/callback/{provider}
- provider =
googleormicrosoft. - BACKEND_BASE = backend root URL. Set via:
- AGENT_IDENTITY_OAUTH_BASE_URL (backend env), or
- NEXT_PUBLIC_API_URL (if frontend and backend share the same origin in your setup), or
- default from request host when not set.
Configure in the OAuth provider console:
- Google: APIs & Services → Credentials → your OAuth 2.0 Client → Authorized redirect URIs → add
https://your-backend.netlify.app/api/agents/auth/callback/google(or your backend URL). - Microsoft: App registration → Authentication → Redirect URIs → add
https://your-backend.netlify.app/api/agents/auth/callback/microsoft.
After the user completes OAuth, the callback exchanges the code for access and refresh tokens, stores them encrypted, and returns a success page (“You can close this tab”).
4. Refresh tokens
POST /api/agents/:id/identity/:identityId/auth/refresh
Uses the stored refresh_token to get a new access token (and optionally a new refresh token). Call this when the access token is expired or near expiry, or on a schedule.
- Auth:
X-User-Emailor Bearer (session). - Response:
{ "ok": true, "identity": { ... } }.
If the refresh fails (e.g. token revoked at provider), the identity may need to be reconnected (user goes through connect again).
5. Revoke
POST /api/agents/:id/identity/:identityId/revoke
Clears stored tokens and marks the identity as revoked/inactive. The user can create a new identity or connect again later.
- Does not necessarily call the provider’s revoke endpoint; it’s a local disconnect. For full revocation at the provider, that may be added in a future release.
6. Health and reconnect
GET /api/agents/:id/identity/health
Returns health status (e.g. stale if not used for a long time, or token expired). Use this to show “Reconnect” in the UI when the identity is unhealthy.
Recovery: If refresh fails or health is bad, direct the user to connect again (same connect URL flow). No need to delete the identity first; connect overwrites the stored tokens.
7. Audits
GET /api/agents/:id/identity/audits?identityId=...&limit=...
Lists audit events for the identity (e.g. auth_callback, auth_refresh, revoke). Useful for debugging and compliance.
Env (backend)
| Variable | Purpose | |----------|---------| | GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET | Google OAuth for agent identity. | | MICROSOFT_CLIENT_ID / MICROSOFT_CLIENT_SECRET | Microsoft OAuth for agent identity. | | AGENT_IDENTITY_OAUTH_BASE_URL | Base URL for OAuth redirect (callback). Defaults to request host if unset. |
Ensure the callback URL derived from this base is registered in each provider’s console.