Identity
The identity endpoints answer two questions: who is this agent? and who is this agent talking to? The first is resolved from the agent’s token; the second resolves a person or system on some external platform (a Slack user, a GitHub account, an email address) to a stable identity the agent can remember and reason about.
All examples use the @alfe.ai/agent-api-client.
Who the agent is
Section titled “Who the agent is”Returns the calling agent’s own identity context, decoded from its token.
const { agentId, tenantId } = await client.whoami();// GET /agent/identity/whoami{ "data": { "agentId": "agt_…", "tenantId": "…" } }Both ids come from the token, so this is the canonical way for an agent to learn
its own agentId at runtime. It’s one round-trip — cache the result rather than
calling it per action.
Resolve who you’re talking to
Section titled “Resolve who you’re talking to”Given a platform and a platform-specific id, resolve (or create) the matching identity and get back the permissions that identity carries.
const result = await client.resolveIdentity({ provider: "slack", // the platform the id comes from platformId: "U0123456789", // the platform's own id for the person kind: "user", // user | agent | service | bot | workspace displayName: "Dana Lee", // optional, used when creating a new identity});// POST /agent/identity/resolve{ "data": { "identityId": "…", "status": "matched", "created": false, "permissions": ["chat:send", "agent:read"] }}identityId is null on a miss. permissions is a flat list of the permissions
that apply at this agent’s scope. An unknown sender still receives any permissions
your organization grants to everyone, and otherwise the list is empty, so a gate
built on it fails closed.
If permissionsUnavailable is true, the empty list means an outage rather than a
denial, so retry instead of denying.
For provider: "email", you can also pass the sender’s email and emailVerified.
Set emailVerified: true only if the agent verified the sender with SPF, DKIM, or
DMARC. Alfe never matches an unverified email sender to an identity.
Search identities
Section titled “Search identities”Find existing identities by free-text query, status (anonymous, partial,
identified, or verified), or a result limit.
const { identities } = await client.searchIdentities({ q: "dana", limit: 20,});// GET /agent/identity/searchList known people
Section titled “List known people”Page through the identities this agent knows. Each entry includes displayName,
status, lastSeenAt, and messageable, which says whether the agent can message
that person.
const { identities, cursor } = await client.listIdentities({ status: "verified", limit: 50 });// GET /agent/identity/directoryRead an identity’s context
Section titled “Read an identity’s context”Fetch the stored context for one identity by id.
const { context } = await client.getIdentityContext(identityId);// GET /agent/identity/{identityId}/contextManaging an identity
Section titled “Managing an identity”The client also exposes methods to curate identities over time. Each takes an identity id and returns a small result object:
| Method | Endpoint | Purpose |
|---|---|---|
updateIdentity(id, fields) |
POST /agent/identity/{id}/update |
Update display fields (name, avatarUrl, timezone, locale). |
addIdentityNote(id, args) |
POST /agent/identity/{id}/notes |
Attach a freeform note (content, optional category). |
tagIdentity(id, args) |
POST /agent/identity/{id}/tags |
Add or remove a tag (tag, action). |
mergeIdentities(survivorId, args) |
POST /agent/identity/{survivorId}/merge |
Merge a duplicate (mergedId) into a survivor. |
unmergeIdentity(id) |
POST /agent/identity/{id}/unmerge |
Reverse a merge. |
getIdentityChangelog(id, opts) |
GET /agent/identity/{id}/changelog |
Read the audit trail of changes. |
rollbackIdentity(id, args) |
POST /agent/identity/{id}/rollback |
Roll the identity back to an earlier version (targetVersion). |
Alfe records who made each change from the agent’s token, so every edit is
attributable in the changelog. updateIdentity can’t change email, phone, title, or
company.
Verifying a claimed identity
Section titled “Verifying a claimed identity”When someone claims to be a person the agent already knows, the agent can run a challenge-and-confirm flow over a verified channel (email or mobile):
const challenge = await client.requestIdentityVerification({ claimedIdentityId: "…", requestingIdentityId: "…", requestingProvider: "slack", requestingPlatformId: "U0123456789", preferredChannel: "email",});// POST /agent/identity/verify/request
const outcome = await client.confirmIdentityVerification({ claimedIdentityId: "…", verificationId: challenge.verificationId, phrase: "the code the person received",});// POST /agent/identity/verify/confirmTo send the code to an address the person gives you, pass
contact: { channel, value } instead of preferredChannel.
A successful confirm returns { verified: true, identityId, action }, where action
is merged, contact_verified, or already_confirmed. A failed request returns an
error field rather than throwing, so check for it.
- Memory — remember facts about the identities you resolve.
- Shared knowledge — org / team / project knowledge the agent can read and contribute to.