identify() sends a user.identified event and attaches an externalUserId to the current session’s correlation ids. Use it once you know who the user is (an email, a database id, a Stripe customer id, or any stable identifier in your system).
Signature
track() with event: "user.identified" and passes userId as externalUserId. The call returns { eventId } immediately, the same as track().
A stable external identifier for the user. Database id, CRM record id, Stripe customer id, or similar. Emails work but are not ideal because they change.
User-level traits (name, email, plan, signup date, and so on). These land in the event
properties payload.MCP request metadata, typically
extra._meta. Required so the identify call can be correlated with the current session.Usage
identify() from the tool that first learns the user’s identity:
Identify inline with track()
If the same tool call both learns the identity and produces a domain event, pass externalUserId on the track() call instead of making a separate identify() call:
Inside tools and flows
When the server is wrapped withwithWaniwani(), the scoped client on context.waniwani (in createTool) or waniwani (in flow nodes) already has the request’s _meta attached, so identify() takes only userId and optional properties:
Anonymous vs. identified sessions
Sessions start anonymous. They get asessionId from _meta but no externalUserId. When you call identify() (or pass externalUserId on a track() call), future events in the session carry the user id. How the backend back-fills earlier events in the same session for a newly identified user is a server-side concern, not something the SDK controls.