SDK Reference
Identity

Identity

Grounded has two identity layers now:

  • lightweight server-side identity in @grounded/tracing
  • stable browser identity and session context in @grounded/analytics

Server Identity In @grounded/tracing

tracing.identify({
  userId: 'user_123',
  sessionId: 'chat_123',
  anonymousId: 'anon_123',
  traits: {
    email: 'jane@example.com',
    plan: 'pro',
    region: 'us',
  },
});

The tracing SDK stores those traits in process memory and attaches them to future traces that match:

  • the same userId
  • the same sessionId
  • or the same anonymousId

Traits are merged into trace.metadata.identityTraits.

Browser Identity In @grounded/analytics

const analytics = init({
  apiKey: process.env.NEXT_PUBLIC_GROUNDED_PUBLISHABLE_KEY!,
  agentId: 'agt_support',
});
 
analytics.identify('user_123', {
  plan: 'pro',
  region: 'us',
});

The analytics SDK persists:

  • sessionId
  • anonymousId
  • userId

and exposes them with:

const context = analytics.getContext();

Primary Correlation Pattern

Use analytics.getContext() as the browser-to-server handoff contract.

Browser:

const groundedContext = analytics.getContext();
 
await fetch('/api/support/reply', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({
    message,
    grounded: groundedContext,
  }),
});

Server:

const trace = tracing.startTrace({
  name: 'support.reply',
  sessionId: req.body.grounded.sessionId,
  anonymousId: req.body.grounded.anonymousId,
  userId: req.body.grounded.userId,
  resource: { agentId: 'agt_support', snapshotId: 'snap_live' },
});

This is what lets Grounded merge browser telemetry and backend traces into one session timeline.

Important Limits

@grounded/tracing

  • traits are in-memory only
  • there is no cookie persistence
  • identity state is not shared across processes unless your app does it

@grounded/analytics

  • browser identity is for telemetry correlation, not profile storage
  • traits should stay small and non-sensitive
  • if you call reset(), a new sessionId and anonymousId are generated

Recommendations

  • use your internal stable user ID, not email, as the primary userId
  • treat traits as helpful context, not canonical profile storage
  • forward getContext() on any request that also emits backend traces