Skip to content

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.

Returns the calling agent’s own identity context, decoded from its token.

identity.ts
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.

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.

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/search

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/directory

Fetch the stored context for one identity by id.

const { context } = await client.getIdentityContext(identityId);
// GET /agent/identity/{identityId}/context

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.

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/confirm

To 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.