Agent SDK

Session scoping and OAuth

Scope MCP auth and resumed conversations to the current host session, pass host identity correctly, and choose between built-in and custom auth handling.

9 sections

For embedded and first-party product agents, the two most important identity inputs are:

  • appSessionKey
  • userIdentity

Together, they tell the SDK:

  • which signed-in host session the agent belongs to
  • which user should be associated with same-user MCP auth
  • when persisted auth or resumed conversation state should be invalidated

appSessionKey#

appSessionKey is your app's current signed-in session boundary.

Examples:

  • your session id
  • a stable signed-in token id
  • a value that changes on logout/login
TS
const agent = useAppAgent({
  apiKey: "emcy_sk_xxxx",
  agentId: "ag_xxxxx",
  appSessionKey: session.id,
});

Pass it so persisted MCP OAuth state and resumed conversations do not leak across session changes.

userIdentity#

userIdentity is the current signed-in host user.

TS
userIdentity: {
  subject: session.user.id,
  email: session.user.email,
  organizationId: session.organizationId,
  displayName: session.user.name,
}

Use it whenever the agent may need same-user OAuth-backed access to downstream MCP tools.

Built-in popup auth on web#

In the React package, if you do not provide onAuthRequired, the SDK uses its built-in popup auth controller.

That gives you:

  • popupAuthState
  • startOrRetryPopupAuth()
  • cancelPopupAuth()

This is the simplest path for web.

Custom auth handling#

If you want to own the auth UI flow yourself, provide onAuthRequired.

TS
const agent = useAppAgent({
  apiKey: "emcy_sk_xxxx",
  agentId: "ag_xxxxx",
  appSessionKey: session.id,
  userIdentity,
  onAuthRequired: async (serverUrl, authConfig) => {
    const token = await openCustomAuthModal(serverUrl, authConfig);
    return token;
  },
});

Use this when:

  • you already have a native auth-session flow
  • you need custom OAuth callback handling
  • you need host-specific consent UI

Native platform auth helper#

If you are building outside the default web popup flow and you have a platform auth implementation, use createPlatformAuthHandler from @emcy/agent-sdk/app.

TS
import { createPlatformAuthHandler } from "@emcy/agent-sdk/app";
 
const onAuthRequired = createPlatformAuthHandler({
  platform,
  userIdentity,
  oauthCallbackUrl: "myapp://oauth/callback",
});

This is especially useful for React Native or custom browser environments.

Browser platform defaults#

If serviceUrl points to localhost and you do not override them, the web experience defaults to:

  • http://localhost:3100/oauth/callback
  • http://localhost:3100/.well-known/oauth-client-metadata.json

That is designed to work cleanly with the local Emcy web app during development.

Resume scoping#

The App Agent layer persists conversation resume state by combining:

  • agent identity
  • appSessionKey
  • conversationResumeVersion
  • your optional conversation namespace

That means resumed conversations are automatically dropped when they are no longer compatible or no longer belong to the current signed-in session.

  • always pass appSessionKey
  • pass userIdentity for same-user MCP auth
  • use the built-in popup flow on web unless you have a strong reason not to
  • use explicit native platform auth on mobile
  • test logout/login and account-switch flows, not just the happy path