Identity

For Coding Agents

identity.md

AGNT Identity

Why AGNT Identity

Every agent platform needs to know who's who. AGNT Identity is the foundation — users, accounts, team members, identifiers, and preferences. It's the layer that connects a person to their calendars, contacts, conversations, and agent behaviors.

Most platforms give you a user table and call it done. AGNT Identity gives you a full graph: a user has identifiers (email addresses, phone numbers), each identifier has platform connections (Google, Microsoft), each connection has preferences (working hours, buffer times, notification settings), and all of it is queryable through a single API.

This is not optional plumbing. This is the data model your agents think in.

Quick Start

1. Authenticate via OAuth

Get a Google OAuth login URL:

bash
curl "https://api.agnt.ai/auth/google?redirectUri=https://yourapp.com/callback"
json
{
  "ok": true,
  "url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=..."
}

After the user completes OAuth, exchange the code:

bash
curl -X POST https://api.agnt.ai/auth/exchange \
  -H "Content-Type: application/json" \
  -d '{
    "code": "4/0AbCD...",
    "state": "random-state-string",
    "provider": "google"
  }'
json
{
  "ok": true,
  "token": "eyJhbGciOiJSUzI1NiIs...",
  "user": {
    "id": "usr_abc123",
    "email": "jane@acme.co",
    "name": "Jane Chen",
    "accounts": [
      { "id": "acc_def456", "name": "Acme Corp", "role": "admin" }
    ]
  }
}

2. Get Account-Scoped Token

bash
curl -X POST https://api.agnt.ai/auth/account/acc_def456/token \
  -H "Authorization: Bearer $TOKEN"
json
{
  "ok": true,
  "token": "eyJhbGciOiJSUzI1NiIs..."
}

3. Create a User

bash
curl -X POST https://api.agnt.ai/users \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "bob@acme.co",
    "name": "Bob Park",
    "firstName": "Bob",
    "lastName": "Park",
    "timezone": "America/New_York"
  }'
json
{
  "ok": true,
  "user": {
    "id": "usr_ghi789",
    "email": "bob@acme.co",
    "name": "Bob Park",
    "firstName": "Bob",
    "lastName": "Park",
    "timezone": "America/New_York",
    "identifiers": [
      {
        "id": "idn_jkl012",
        "type": "email",
        "value": "bob@acme.co",
        "primary": true,
        "verified": false
      }
    ]
  }
}

Core Concepts

Users

A user is a person on your platform. They have a name, email, timezone, and optional metadata. Users are the anchor point — everything else (identifiers, calendars, contacts, memories, preferences) hangs off a user.

Users can be created explicitly via the API or auto-provisioned when a delegated JWT includes an email AGNT hasn't seen before. See Authentication for details on auto-provisioning.

Accounts

An account is an organization. Users belong to accounts as members with roles (member or admin). A user can belong to multiple accounts. API calls are scoped to an account via account-scoped JWTs.

Deleting an account cascades. Everything under it — users, identifiers, calendars, contacts, tasks, chats — is removed.

Identifiers

An identifier is a way to reach a person. Email addresses, phone numbers — anything that uniquely identifies a user across platforms. Each identifier has:

  • A type (e.g., email)
  • A value (e.g., jane@acme.co)
  • A primary flag (one identifier per type is primary)
  • A platforms object tracking OAuth connections (Google, Microsoft)

Identifiers are the bridge to external services. When a user grants Google OAuth access, that's recorded on an identifier. When you sync calendars, you sync them through an identifier. When you query availability, you query it for an identifier.

Preferences

Preferences are per-identifier settings that control agent behavior. They're organized by skill:

  • scheduling -- Working hours, default meeting durations, calendar read/write access, buffers
  • reminders -- Notification levels and timing for email, Slack, and Teams
  • followups -- Auto-followup configuration (enabled, count, interval)
  • travel -- Seat preference, cabin class, meal preference, airline preferences

Preferences are what make an agent personal. Two users can use the same scheduling agent, but one prefers 30-minute meetings with 15-minute buffers while the other prefers 60-minute meetings with no buffers. Preferences make that work without hardcoding.

Team Members

Team members are the humans who manage the account — your internal team. They're distinct from users (who are your end users). Members have roles:

  • admin -- Full access to account settings, certificates, and provider configuration
  • member -- Standard access to the account's resources

Invite members by email. They show up in the member list as "invited" until they accept.

API Reference

Auth Endpoints

MethodPathDescriptionAuth
GET/auth/googleGet Google OAuth login URLNone
GET/auth/google/callbackGoogle OAuth callbackNone
GET/auth/microsoftGet Microsoft OAuth login URLNone
GET/auth/microsoft/callbackMicrosoft OAuth callbackNone
POST/auth/exchangeExchange OAuth code for tokenNone
POST/auth/account/:accountId/tokenGet account-scoped JWTBearer
POST/auth/refreshRefresh tokenBearer
GET/auth/meGet current user infoBearer
POST/auth/accept-termsAccept terms of serviceBearer

Get OAuth Login URL

GET https://api.agnt.ai/auth/google?redirectUri=https://yourapp.com/callback
GET https://api.agnt.ai/auth/microsoft?redirectUri=https://yourapp.com/callback
ParameterTypeRequiredDescription
redirectUristringYesWhere to redirect after OAuth

Exchange OAuth Code

POST https://api.agnt.ai/auth/exchange
FieldTypeRequiredDescription
codestringYesOAuth authorization code
statestringYesState parameter from the OAuth flow
providerstringYesgoogle or microsoft

Refresh Token

POST https://api.agnt.ai/auth/refresh
FieldTypeRequiredDescription
accountIdstringYesAccount to scope the new token to

Get Current User

GET https://api.agnt.ai/auth/me
json
{
  "ok": true,
  "user": {
    "id": "usr_abc123",
    "email": "jane@acme.co",
    "name": "Jane Chen",
    "accounts": [
      { "id": "acc_def456", "name": "Acme Corp", "role": "admin" }
    ]
  }
}

Account Endpoints

MethodPathDescriptionAuth
GET/accountsList user's account membershipsBearer
POST/accountsCreate an accountBearer
GET/accountCurrent account detailsManagement
GET/account/statsAccount statisticsManagement
DELETE/accountDelete account (owner only, cascades)Management
PUT/account/settingsUpdate account settingsManagement

Create Account

POST https://api.agnt.ai/accounts
FieldTypeRequiredDescription
namestringYesAccount display name
slugstringYesURL-safe account identifier
json
{
  "ok": true,
  "account": {
    "id": "acc_xyz999",
    "name": "Acme Corp",
    "slug": "acme-corp"
  }
}

Account Statistics

GET https://api.agnt.ai/account/stats
json
{
  "ok": true,
  "stats": {
    "totalTasks": 1247,
    "pendingTasks": 23,
    "completedTasks": 1189,
    "totalCertificates": 3,
    "totalChats": 456,
    "apiCalls": 89432
  }
}

Credential Endpoints

MethodPathDescriptionAuth
GET/credentialsList credentials (secrets are masked)Management
PUT/credentialsUpdate provider credentialsManagement

OAuth Token Endpoints

MethodPathDescriptionAuth
GET/oauth-tokensGet OAuth tokensManagement
ParameterTypeRequiredDescription
identifierIdstringYesIdentifier to get tokens for
resourcestringYesOAuth resource type

Team Member Endpoints

MethodPathDescriptionAuth
GET/membersList team members (active + invited)Management
POST/membersInvite a team memberManagement
DELETE/members/:memberIdRemove a team memberManagement

Invite Member

POST https://api.agnt.ai/members
FieldTypeRequiredDescription
emailstringYesEmail address to invite
rolestringYesmember or admin
bash
curl -X POST https://api.agnt.ai/members \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "email": "newguy@acme.co", "role": "member" }'
json
{
  "ok": true,
  "member": {
    "id": "mbr_abc123",
    "email": "newguy@acme.co",
    "role": "member",
    "status": "invited"
  }
}

User Endpoints

MethodPathDescriptionAuth
GET/usersList usersManagement
POST/usersCreate a userManagement
GET/users/:userIdGet user (includes identifiers, contacts, memories)Management
PUT/users/:userIdUpdate userManagement
DELETE/users/:userIdDelete user (cascades to identifiers)Management
GET/users/:userId/contactsList user's contactsDelegated

List Users

GET https://api.agnt.ai/users
ParameterTypeDescription
statusstringFilter by status
emailstringFilter by exact email
externalIdstringFilter by external ID
pagenumberPage number (default: 1)
perPagenumberResults per page (default: 20)

Create User

POST https://api.agnt.ai/users
FieldTypeRequiredDescription
emailstringYesUser's email address
namestringNoFull name
firstNamestringNoFirst name
lastNamestringNoLast name
avatarstringNoAvatar URL
timezonestringNoIANA timezone
localestringNoLocale code (e.g., en-US)
externalIdstringNoYour application's user ID
assistantEmailstringNoEmail address for the user's AI assistant
metadataobjectNoArbitrary key-value metadata

Get User

GET https://api.agnt.ai/users/:userId

Returns the full user object including nested identifiers, contacts, and memories.

json
{
  "ok": true,
  "user": {
    "id": "usr_abc123",
    "email": "jane@acme.co",
    "name": "Jane Chen",
    "firstName": "Jane",
    "lastName": "Chen",
    "avatar": null,
    "timezone": "America/Los_Angeles",
    "locale": "en-US",
    "externalId": "your-app-user-123",
    "assistantEmail": "jane-assistant@agnt.ai",
    "metadata": { "plan": "pro" },
    "identifiers": [
      {
        "id": "idn_abc123",
        "type": "email",
        "value": "jane@acme.co",
        "primary": true,
        "verified": true,
        "platforms": {
          "google": { "accessGranted": true },
          "azure": { "accessGranted": false }
        }
      }
    ],
    "contacts": [],
    "memories": [],
    "createdAt": "2026-01-15T08:00:00.000Z",
    "updatedAt": "2026-03-01T12:00:00.000Z"
  }
}

Identifier Endpoints

MethodPathDescriptionAuth
GET/identifiersList identifiersManagement
POST/identifiersCreate an identifierManagement
GET/identifiers/:identifierIdGet identifier detailsManagement
PUT/identifiers/:identifierIdUpdate identifierManagement
POST/identifiers/:identifierId/linkLink identifier to a userManagement
POST/identifiers/:identifierId/make-primaryMake identifier primaryManagement
DELETE/identifiers/:identifierIdDelete (cascades to preferences, calendars, timelines)Management

List Identifiers

GET https://api.agnt.ai/identifiers
ParameterTypeDescription
typestringFilter by type (e.g., email)
userIdstringFilter by user ID

Create Identifier

POST https://api.agnt.ai/identifiers
FieldTypeRequiredDescription
typestringYesIdentifier type (e.g., email)
valuestringYesThe identifier value (e.g., jane@acme.co)
userDataobjectNoAdditional user data
userIdstringNoUser ID to link to
verifiedbooleanNoWhether the identifier is verified
primarybooleanNoWhether this is the primary identifier
platformsobjectNoPlatform connection flags
POST https://api.agnt.ai/identifiers/:identifierId/link
FieldTypeRequiredDescription
userIdstringYesUser ID to link to

Update Identifier

PUT https://api.agnt.ai/identifiers/:identifierId
FieldTypeDescription
verifiedbooleanVerification status
primarybooleanPrimary status
platformsobjectPlatform connection flags
metadataobjectArbitrary metadata

Preference Endpoints

MethodPathDescriptionAuth
GET/identifiers/:identifierId/preferencesGet all preferencesDelegated
GET/identifiers/:identifierId/preferences/:skillNameGet preferences for a skillDelegated
PUT/identifiers/:identifierId/preferences/:skillNameSet preferences for a skillDelegated

Skill names: scheduling, reminders, followups, travel

Scheduling Preferences

PUT https://api.agnt.ai/identifiers/idn_abc123/preferences/scheduling
json
{
  "availability": {
    "workingHours": {
      "MO": { "start": "09:00", "end": "17:00" },
      "TU": { "start": "09:00", "end": "17:00" },
      "WE": { "start": "09:00", "end": "17:00" },
      "TH": { "start": "09:00", "end": "17:00" },
      "FR": { "start": "09:00", "end": "17:00" },
      "SA": null,
      "SU": null
    },
    "workingHolidays": false
  },
  "defaults": {
    "virtualDuration": 30,
    "inPersonDuration": 60,
    "supervision": "autonomous"
  },
  "calendars": {
    "read": ["cal_def456", "cal_ghi789"],
    "write": ["cal_def456"]
  },
  "buffers": {
    "before": 5,
    "after": 15
  }
}
FieldTypeDescription
availability.workingHoursobjectPer-day working hours (MO-SU). null = day off.
availability.workingHolidaysbooleanWhether to work on holidays
defaults.virtualDurationnumberDefault virtual meeting duration in minutes
defaults.inPersonDurationnumberDefault in-person meeting duration in minutes
defaults.supervisionstringAgent autonomy level
calendars.readstring[]Calendar IDs to read for availability
calendars.writestring[]Calendar IDs to write events to
buffers.beforenumberMinutes of buffer before meetings
buffers.afternumberMinutes of buffer after meetings

Reminder Preferences

PUT https://api.agnt.ai/identifiers/idn_abc123/preferences/reminders
json
{
  "level": "standard",
  "email": {
    "enabled": true,
    "inPersonMinutes": 60,
    "virtualMinutes": 15
  },
  "slack": {
    "enabled": true,
    "inPersonMinutes": 30,
    "virtualMinutes": 10
  },
  "teams": {
    "enabled": false,
    "inPersonMinutes": 30,
    "virtualMinutes": 10
  }
}
FieldTypeDescription
levelstringReminder intensity level
email.enabledbooleanSend email reminders
email.inPersonMinutesnumberMinutes before in-person meeting
email.virtualMinutesnumberMinutes before virtual meeting
slack.enabledbooleanSend Slack reminders
slack.inPersonMinutesnumberMinutes before in-person meeting
slack.virtualMinutesnumberMinutes before virtual meeting
teams.enabledbooleanSend Teams reminders
teams.inPersonMinutesnumberMinutes before in-person meeting
teams.virtualMinutesnumberMinutes before virtual meeting

Followup Preferences

PUT https://api.agnt.ai/identifiers/idn_abc123/preferences/followups
json
{
  "enabled": true,
  "count": 3,
  "interval": 1440
}
FieldTypeDescription
enabledbooleanEnable automatic followups
countnumberNumber of followups (0-5)
intervalnumberMinutes between followups

Travel Preferences

PUT https://api.agnt.ai/identifiers/idn_abc123/preferences/travel
json
{
  "seatPreference": "window",
  "cabinClass": "business",
  "mealPreference": "vegetarian",
  "airlinePreferences": ["UA", "DL"]
}
FieldTypeDescription
seatPreferencestringSeat preference (e.g., window, aisle)
cabinClassstringCabin class (e.g., economy, business, first)
mealPreferencestringMeal preference
airlinePreferencesstring[]Preferred airline codes

For Coding Agents

If you're building an agent that needs to understand users, here's what matters:

  • Users vs. identifiers. A user is a person. An identifier is a way to reach them. One user can have multiple email identifiers. Always resolve from identifier to user when you need the full picture.
  • Check platforms on identifiers. Before trying to sync a user's Google Calendar, verify that platforms.google.accessGranted is true on their identifier. If it's not, the user needs to complete OAuth first.
  • Preferences drive behavior. Don't hardcode meeting durations or working hours. Read them from preferences. If preferences aren't set, use sensible defaults (30 minutes, 9-5 weekdays) but tell the user they can customize.
  • externalId is your bridge. When creating users, set externalId to your application's user ID. This lets you look up AGNT users by your own ID without maintaining a mapping table.
  • Cascading deletes are real. Deleting a user removes their identifiers, which removes their preferences, calendars, and timelines. Deleting an account removes everything. Make sure your agent warns before destructive operations.
  • GET /users/:userId is the richest endpoint. It returns identifiers, contacts, and memories in a single call. Use it when your agent needs full context about a person.

For Product Teams

AGNT Identity is the data model everything else builds on. Here's what shapes the product:

  • OAuth is the onboarding funnel. Google and Microsoft OAuth are the primary way users connect. The flow is standard: redirect to provider, user grants access, exchange code for token. The auth/exchange endpoint handles the handshake.
  • Accounts scope everything. All API calls happen within an account context. Account-scoped JWTs ensure data isolation. If you're building a multi-tenant product, each tenant maps to an AGNT account.
  • Team members are internal, users are external. Members are your team — the people who build and manage the product. Users are the end users your agents serve. They're separate concepts with separate APIs.
  • Preferences are per-identifier, not per-user. This seems like an odd choice until you realize a user might want different working hours for their work email vs. their personal email. Preferences attach to identifiers because identifiers are what connect to external services.
  • Account stats give you the dashboard. The /account/stats endpoint returns total tasks, pending tasks, completed tasks, certificates, chats, and API calls. This is your usage dashboard in one call.
  • Auto-provisioning reduces friction. When a delegated JWT contains an email AGNT hasn't seen, the user is created automatically. No signup form needed. No separate user creation step. This is deliberate — agents shouldn't wait for humans to register.