Armature attributes every tool call to an actor — a stable, privacy-preserving identifier for the user or account behind the session.
The default
Out of the box, the SDK derives an actor seed from the request’s authentication, in order:
- A configured
actorId (if you set one — see below)
- The request’s auth info: token, client ID, API key, or principal ID
- The
Authorization header
"anonymous" as the last resort
The seed is SHA-256 hashed before transmission — raw tokens and header values never leave your server. Two sessions from the same authenticated user hash to the same actor, so per-user views line up without Armature ever seeing the credential.
Custom actor resolution
If your server knows the real user (for example, after validating an OAuth token), resolve the actor yourself so sessions group by your user IDs:
Whatever you return is still hashed before it is sent.
Attach a readable identifier
Hashes group sessions; they don’t tell you who a session was. To label sessions with an identifier you choose — an internal user ID, an account slug, an email — set the identifier option (actorIdentifier in TypeScript and PHP, actor_identifier in Python, ActorIdentifier in Go):
The value doubles as the actor seed (hashed into the actor ID) and is sent verbatim in a small identity event whenever it changes, so the dashboard can display it. The SDK doesn’t interpret it — any non-empty string works. Unlike actorId seeds, the identifier is transmitted as-is by design: don’t put anything in it you wouldn’t show in the dashboard.
In the Go official-SDK adapter, install the analytics middleware before your auth middleware if ActorSeed reads values that auth injects into the context — otherwise the actor resolves before auth has run.
Anonymous traffic
Unauthenticated servers still get useful sessions: the actor falls back to anonymous, and session identity (which conversation the calls belong to) is tracked separately via the MCP session ID. You lose per-user grouping, not session replay.