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 = google or microsoft.
  • 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-Email or 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.