Personas
The Personas service gives your agents the identities they work as on outside systems: a mailbox, an API account, an app registration. Each Persona records who that identity is and holds its one credential, whose secret is kept in the platform's keychain rather than in a conversation. An agent passes a Persona's id to another service, and that service signs in with it.
A Persona belongs to your account, and starts private to whoever created it: only once it is shared can every member of the organization use it (see Private and shared Personas).
It offers a trial, and it can also be enabled in full and billed per use.
Every tool works on this system's own storage only; none reaches outside it. No tool signs in to the outside system or checks that a credential works.
Its tools
Each tool is charged under an operation of its own, named in brackets at the end of its entry: one unit per call.
Every tool that answers a Persona answers it without its secret, with its
dates in ISO form, with its ownerLink (see Handing a secret to its
owner), with its signInLink and account,
with adminConsentLink in its structured fields and never in its text (see
Signing an account in), and with a notice for each
Persona in the answer whose secret is not set, has expired or expires soon, or
whose account is not signed in or whose sign-in is estimated to have lapsed or
to lapse soon (see Expiry and notices). A
Persona is named by its personaId, the id personas_list answers.
Tools that only read
personas_listlists the Personas you can use, your own private ones and those shared with the organization: every one, or withtagonly those carrying that tag, or withexpiresWithinDaysonly those whose secret expires within that many days (for a signed-in Persona, whose sign-in is estimated to lapse within them), the already expired included. Give both to have both apply. Each Persona's line says whether it is private or shared, and whether its secret is set, or for a signed-in Persona which account it is signed in as. For an organization owner or admin it also answersforeignPrivate(see Private and shared Personas). It only reads (personas-list).personas_getreturns one Persona: its name, purpose, system kind, credential type and that credential's non-secret details, whether it is revealable, whether its secret is set and when it was last set, when it expires, its tags, its owner link, and when the Persona was created and last changed. It only reads (personas-get).personas_owner_linkreturns one Persona's owner link, the address of its own page, and whether its secret is set, for an agent that holds only the id. Every answer that carries a Persona already carries the same link. It only reads (personas-owner-link).personas_sign_in_linkreturns a signed-in Persona's sign-in link, the address where the person who manages it signs its account in, andsignedIn, whether it is signed in now, for an agent that holds only the id. Every answer that carries a signed-in Persona already carries the same link. A Persona of any other type is refused (PERSONA_CREDENTIAL_TYPE_MISMATCH). It only reads (personas-sign-in-link).
Tools that change things and lose nothing
personas_create_privatemakes a new Persona from aname, an optionalpurpose, itssystemKind, itscredential, an optionalsecret, an optionalsecretExpiresAt,revealableand optionaltags. Anyone in the organization may create one. The Persona is private to you, its creator, and you manage it; an organization owner or admin may also share it withpersonas_share. An agent working through a client registered by a member is refused (PERSONA_FORBIDDEN): a client acts for the organization, not for the member, so it could manage nothing it created (see Who manages a Persona). Aclient-secretcredential onmicrosoft-365is an app credential that only an organization owner or admin creates: anyone else is refused (PERSONA_APP_CREDENTIAL_RESERVED) and creates asigned-inPersona instead. Leavesecretout and the Persona is created with its secret pending: it waits until the person who manages it (its creator for a private Persona, an organization owner or admin for a shared one) sets it from the Persona's own page (see Handing a secret to its owner). Asecretthat is sent cannot be blank: the tool's input check refuses an empty one as an invalidsecret(VALIDATION_FAILED).secretExpiresAtis accepted only with asecret. A name one of your own private Personas already has, compared without regard to letter case, is refused.revealableis chosen here, once:falsecan never be changed totrue. Asigned-incredential takes nosecretand nosecretExpiresAt, and must be created withrevealable: false; its account is signed in afterwards, as Signing an account in says (personas-create-private).personas_add_tagputs onetagon a Persona. A tag it already carries leaves it as it was (personas-add-tag).personas_remove_tagtakes onetagoff a Persona. A tag it does not carry leaves it as it was (personas-remove-tag).
Tools that replace, disclose or remove, with no undo
personas_updatechanges any of a Persona'sname,purpose,systemKindandcredential, leaving the rest as they are; at least one must be given. Apurposeofnullclears it. The credential's type cannot change, nor can a signed-in Persona'ssystemKind, and acredentialgiven replaces the whole of its non-secret details: aclient-secretcredential sent withouttenantIdclears it. What it overwrites keeps no history and cannot be recovered. Moving aclient-secretPersona ontomicrosoft-365is refused (PERSONA_APP_CREDENTIAL_RESERVED) for anyone but an organization owner or admin; one already on it is not refused. The secret is untouched (personas-update).personas_replace_secretgives a Persona's credential a newsecret, and a newsecretExpiresAtor, when that is left out ornull, no expiry. For a Persona whose secret is not set yet, it sets the first one. The previous secret, if there was one, is overwritten and cannot be recovered; the credential's non-secret details are untouched. A signed-in Persona has no secret and is refused (PERSONA_CREDENTIAL_TYPE_MISMATCH): the person who manages it signs its account in again instead (personas-rotate).personas_lockmakes a revealable Persona unrevealable, for good: this cannot be undone. Locking one already locked leaves it as it was (personas-lock).personas_revealreturns the secret of a revealable Persona, in its answer and nowhere else. A Persona created unrevealable, or locked since, is refused, and nothing is revealed. A Persona whose secret is not set is refused too, since nothing has been stored for it. Each reveal is recorded (see Revealing and locking). Its answer comes back whole and is never stored or paged. A secret once in a transcript cannot be taken back out of it (personas-reveal).personas_deletedeletes a Persona and erases its secret, or its account's sign-in. Nothing of it can be recovered (personas-delete).personas_sign_outsigns a signed-in Persona out: it erases the account's sign-in and any sign-in still in progress, and nothing else of the Persona, which reads not signed in until the person who manages it signs it in again. What it discards only a person can give back, and it withdraws nothing at the provider (see Signing an account in). Each sign-out of a signed-in Persona is recorded: who signed it out, when, and on which surface. Signing out a Persona not signed in records nothing, and still ends any sign-in in progress. A Persona of any other type is refused (personas-sign-out).personas_shareshares one of your own private Personas with the organization, so every member can use it to act as the account. Only an organization owner or admin may share; anyone else is refused (PERSONA_FORBIDDEN), their own Personas included. What that means, in the tool's own words: Sharing makes this account available to your whole organization: any other user with access to the organization will be able to use this Persona to reach the other resources the account can reach. A Persona you did not create is refused, and so is one whose name a shared Persona already has. Asigned-inPersona (the OAuth user flow) is refused withPERSONA_SIGNED_IN_NOT_SHAREABLE, signed in or not (see Signed-in Personas cannot be shared). Sharing one already shared changes nothing (personas-share).personas_unsharereturns a shared Persona to its creator as a private one: other members can no longer use it. Only an organization owner or admin may do this; anyone else, its creator included, is refused (PERSONA_FORBIDDEN). An agent working through an API key, or through a client registered by an owner or admin, may unshare only a Persona such an agent created, and any other is refused as not found; a client registered by a member is refused (PERSONA_FORBIDDEN) like any other caller without the role. It is refused when the creator already has a private Persona of the same name. Unsharing one already private changes nothing (personas-unshare).
Private and shared Personas
A Persona is private to whoever created it until it is shared with the
organization. An agent working through an API key or client creates as the
organization's one agent principal, shared by every such key and client, so
a Persona one such agent created is private to all of them alike, and no
person can open it until it is shared. Because that principal is the
organization's and not a person's, such an agent creates and manages
Personas only when its credential carries the owner or admin role. An agent working through a person's
own sign-in creates as that person, so what it creates is that person's. No
other member can use a private Persona or see it among their own; an
organization owner or admin is shown it by its id, name, kind, owner
(createdBy) and creation date only, in foreignPrivate below, and can only
delete it. An organization owner or admin who created it may share it with
personas_share, which makes it usable by every member of the organization,
and an owner or admin returns it to its creator with personas_unshare.
Signed-in Personas cannot be shared
A signed-in Persona, one that uses the OAuth user flow, acts as the account
of the person who signed it in: its one sign-in is that person's consent and
multi-factor check. Sharing it would let every member and every agent of the
organization act as that account without signing in, and the provider's own
log would name the person who signed in for all of it. So personas_share
refuses a signed-in Persona with PERSONA_SIGNED_IN_NOT_SHAREABLE, whether it
is signed in now or not, and the Persona's page offers no Share for one. Each
member who needs the account creates their own private signed-in Persona and
signs it in. A Persona the whole organization needs is better made a
client-secret Persona for an app registration, with its administrator's
consent, which an organization owner or admin creates and shares.
personas_unshare still returns a signed-in Persona that was shared before
this rule to its creator.
Every answer that carries a Persona carries its kind, private or
organization (shared), and createdBy, the principal that created and owns
it: your own principal id for a Persona of yours. Personas stores that id in
lower case, and other services may answer the same principal's id in mixed
case, so compare principal ids across services without regard to letter case.
An organization owner or admin's personas_list also answers
foreignPrivate: the other members' private Personas, each by its id,
name, kind, owner (createdBy, its owner's principal id) and creation
date (createdAt) only. Such a Persona can only be deleted, with
personas_delete; no other tool reaches it. For everyone else
foreignPrivate is empty. An agent working through an API key or client is
never shown another member's private Personas, whatever roles its key
carries, and a personas_delete from it of one it cannot see is refused as
not found. An agent working through a person's own sign-in is shown what
that person is.
Who manages a Persona
Anyone in the organization creates Personas with personas_create_private,
always private to them, and manages the ones they created (an agent working
through an API key or client is the exception below):
personas_update, personas_replace_secret, personas_add_tag,
personas_remove_tag, personas_lock, personas_reveal, personas_delete,
signing it in and personas_sign_out. An organization owner or admin
manages, besides, every Persona shared with the organization, and alone may
personas_share and personas_unshare.
A person whose roles include neither owner nor admin, and an agent acting for
one, uses the shared Personas without managing them: every manage tool on a
shared Persona refuses them with PERSONA_FORBIDDEN, and so do
personas_share and personas_unshare on any Persona, their own included.
The share and unshare refusal comes before any Persona is looked up, whatever
the id. Every other manage refusal comes after the lookup: a Persona they
cannot see, another member's private one included, is refused as not found,
and only one they can already see answers PERSONA_FORBIDDEN, so no refusal
says whether a Persona they cannot see exists. They may not create a
client-secret Persona on microsoft-365, nor move one onto it
(PERSONA_APP_CREDENTIAL_RESERVED): that app credential is an owner's or an
admin's, and a signed-in Persona reaches their own account instead. The
tools that only read are open to everyone.
An agent holds the roles its credential carries, at most admin. An agent
working through a person's own sign-in is that person, with that person's
roles, and creates and manages exactly as they do. An agent working through
an API key or a client acts as the organization's one agent principal
instead, which no person is, so the Personas it creates are recorded as the
organization's and it creates and manages them by the owner or admin role
alone. An API key carries admin, so it manages the Personas it can see:
those such an agent created and those shared with the organization. A
client carries the roles of the person who registered it: one registered by
an owner or admin manages as an API key does, and one registered by a
member is refused (PERSONA_FORBIDDEN) by personas_create_private and by
every manage tool on a Persona it can see; it still uses the shared
Personas and those such an agent created.
Credentials
A Persona holds one credential, of one of four types. The secret is given
apart from the credential, as secret, and is never part of an answer except
personas_reveal's.
password: ausername, and the password as the secret.api-key: nothing besides the key, which is the secret.client-secret: aclientIdand, optionally, atenantId, and the client secret as the secret.signed-in: ausername, the address of the account the person who manages it is expected to sign in as, and no secret at all: the platform keeps the account's sign-in itself (see Signing an account in). It is never revealable, and never shared (see Signed-in Personas cannot be shared).
systemKind says which kind of system the Persona belongs to:
microsoft-365, google-workspace, imap, smtp, http-api or other.
microsoft-365 and google-workspace take signed-in, client-secret and
api-key, and refuse password; every other kind takes password, api-key
and client-secret, and refuses signed-in. A credential a kind does not take
is refused (VALIDATION_FAILED).
Microsoft and Google refuse plain password sign-in for accounts with
multi-factor authentication on their modern APIs. A password Persona is
therefore for IMAP, SMTP and other services that accept one, not for a
Microsoft or Google mailbox reached through those companies' APIs. There, use
a signed-in Persona for an account its creator can sign in as, with no app
registration of your own; or, on Microsoft 365, a client-secret Persona for
an app registration of your own, which an organization owner or admin
creates. For the calendar service, the help page m365-calendar names the
application permission that registration needs and how to limit the app to
the mailbox bound to the Persona.
Handing a secret to its owner
A secret need never pass through a conversation. Create the Persona without
secret, and its secret is pending. Hand the Persona's ownerLink to the
person who manages it (its creator for a private Persona, an organization
owner or admin for a shared one), when they hold the credential. An
organization owner or admin may instead share their own private Persona
first with personas_share and hand the link to another owner or admin who
holds it. Following it, they sign
in to the account (the page asks them to if they are not signed in), and set
the secret on the Persona's own page. A secret already set is replaced the
same way.
A secret set this way stays out of the conversation unless the Persona is
revealable and is revealed later: personas_reveal on a revealable Persona
shows the secret to the agent that calls it. Create the Persona with
revealable: false, or lock it with personas_lock before the secret is set,
if it should never be shown. The page's set and replace dialog says which the
Persona is: a revealable Persona's secret can be revealed by anyone in your
account and by your AI, and a locked one's by no page or tool.
The link carries the Persona's id and grants nothing by itself. Any member
who can see the Persona — its creator while it is private, every member once
it is shared — opens the page, signed in, and reads its non-secret details;
setting the secret or signing the account in there needs the person who
manages it: its creator for a private Persona, an organization owner or
admin for a shared one. Every answer that carries a Persona carries its link, and
personas_owner_link returns it for an id alone.
An agent reads the state from secretSet, which is false until the secret
is set, and from the secret-pending notice a pending Persona carries in
every answer. That notice's handover, and the handover that
personas_owner_link answers, say who to hand the link to, the sharing step
included where the Persona is private. Call personas_get afterwards to see the secret set and the
notice gone.
Signing an account in
A signed-in Persona holds no secret: the person who manages it (its
creator for a private Persona, an organization owner or admin for a shared
one) signs its account in on that account's own login, and the platform keeps the sign-in.
Create it with credential: {"type": "signed-in", "username": …}, the
account's address as username, a systemKind of microsoft-365 or
google-workspace, no secret and revealable: false. It starts not signed
in. Every answer that carries it carries its signInLink, secretSet says
whether it is signed in, and while it is not, it carries a sign-in-required
notice. personas_sign_in_link returns the link and signedIn for an id
alone.
Hand the signInLink to its creator, who signs in as the account. A
signed-in Persona cannot be shared (see Signed-in Personas cannot be
shared), so no one else can open it;
an agent working through an API key or client asks the person whose account
it is to create their own signed-in Persona and sign it in, rather than
creating one itself. Following it, they sign in to this system if asked, and are taken to
the account's own login, Microsoft's or Google's, where they sign in as the
account and agree to what this site may do; the Persona's page then says how
the sign-in ended. A Microsoft account must be a work or school account; a
personal Microsoft account cannot be signed in. Any Google account can be: a
Google Workspace account or a personal one. The person who started a sign-in
must finish it, within a limited time, or start again from the link. No step
an agent takes signs a Persona in: it is a person's act, and nothing of the
account's login passes through the conversation.
username only suggests the account to the login; the Persona is signed in as
whichever account the person signed in as. Every answer that carries
the Persona carries that account as account, and the Persona's page shows
it, so check it is the one intended. A Persona that reads not signed in
afterwards was never signed in, or its sign-in has ended: the attempt was
declined, did not finish in time or could not be verified, it was signed out,
it lapsed unused under the provider's own lifetime (such as the refresh
token's inactivity limit), the account's administrator withdrew it, or the
account's own policy ended it. The remedy is always the same link again.
If the login says an administrator must approve this site. An organization
can require its administrator to approve an app before its members may sign in
to it, and the login then stops the member there. For a Microsoft work or
school account, every answer that carries the Persona carries
adminConsentLink in its structured fields, never in its text: the address at
which the account's administrator approves this site once for every member of
their organization. It carries nothing secret; hand it to the administrator.
The Persona's page offers the same link after a declined sign-in. Once the
administrator has approved, the same sign-in link works. For a Google account,
adminConsentLink is null, since Google has no such address: a Google
Workspace administrator marks this site's app as trusted in the Google Admin
console, under Security → Access and data control → API controls → Manage
third-party app access, and the person who manages the Persona then signs
it in again from the same link. A personal Google account has no administrator to
approve anything. So an administrator reads what they approve, this site asks
a Microsoft work or school account for the permissions openid, profile,
email, offline_access, User.Read, Mail.ReadWrite, Mail.Send,
Calendars.ReadWrite and Calendars.ReadWrite.Shared, the last for the
calendars other people have shared with or delegated to the account, and any
Google account for the scopes openid,
email, https://www.googleapis.com/auth/gmail.modify,
https://www.googleapis.com/auth/gmail.send and
https://www.googleapis.com/auth/calendar.
personas_sign_out erases the account's sign-in and any sign-in still in
progress, and nothing else of the Persona: it reads not signed in until the
person who manages it signs it in again from the same link. Deleting the
Persona erases the sign-in too. Signing out erases this system's copy of the
sign-in; to withdraw the grant at the provider, remove the app on the
account's own Google or Microsoft account page.
Expiry and notices
A secret may carry an expiry, secretExpiresAt: a date and time with its
zone, written YYYY-MM-DDThh:mm:ssZ or with an offset in place of the Z.
It is stored and shown with the Persona, and a Persona whose secret has
expired is marked secretExpired (EXPIRED in the text). An expired secret
is reported, never blocked: the Persona still works for as long as the
outside system accepts the secret. Replace it with personas_replace_secret,
which also sets the new expiry.
For a signed-in Persona, secretExpiresAt is the platform's estimate of when
the account's sign-in lapses, and secretExpired says that estimate has
passed. Each renewal of the sign-in moves it, and the provider, the account's
administrator or the account's own policy may end a sign-in before it. Where
the provider gives no lapse to estimate from, as Google does not,
secretExpiresAt is null and the Persona's page reads No estimate.
Every answer that carries a Persona also carries a notice for each Persona in
it that needs one: as a line beginning Notice: after the answer's text, and
in the answer's notices list, each naming its kind and the Persona. A
Persona carries at most one notice, of one of these kinds:
secret-pending: its secret is not set. It carries the Persona's owner link, and no expiry or days left, since a pending secret has no expiry.secret-expired: its secret's expiry has passed.secret-expiring: its secret expires within your account's warning window.sign-in-required: a signed-in Persona is not signed in. It carries the owner link and the sign-in link, and no expiry or days left.sign-in-expired: a signed-in Persona's estimated lapse has passed.sign-in-expiring: a signed-in Persona's sign-in is estimated to lapse within the warning window.
An expired or expiring notice carries the expiry and the whole days left (negative once expired); the two sign-in kinds of them also carry the owner link and the sign-in link, since the remedy is the person who manages it signing the account in again, not a secret to replace. A Persona with no expiry, or one further off than the window, carries no expiry notice. The window is a setting (see Its settings).
Revealing and locking
Whether a Persona's secret may ever be shown is chosen when it is created,
with revealable. A Persona created unrevealable stays so: its secret can be
set, replaced and used by reference, and no tool returns it.
personas_reveal returns the secret of a revealable Persona only.
personas_lock turns revealable off, and nothing turns it back on, so a
Persona once locked is refused by personas_reveal from then on.
Every reveal is recorded: who revealed it, when, and on which surface (through the tools or on the dashboard), never the value. A reveal that cannot be recorded returns nothing. The record of a reveal is kept when the Persona is later deleted.
Tags
A tag is free-form text you choose, such as mailbox or billing, to group
Personas and to list them by. Leading and trailing spaces are trimmed, and two
tags that differ only in letter case are the same tag. Tags are given at
creation with tags, and changed one at a time with personas_add_tag and
personas_remove_tag.
Its settings
services.personas.max-personas is the most Personas your account may hold,
which you can set to at most 100 Personas. The platform has a ceiling of its
own on it, and the smaller of the two is the cap in force. Lowering it deletes
nothing: Personas already held stay, and only the next create past the cap is
refused.
services.personas.expiry-warning-days is how many days before a secret's
expiry, or a sign-in's estimated lapse, its Persona starts carrying a notice
(secret-expiring or sign-in-expiring), from 0 to 365 days. At its lowest,
only secrets and sign-ins already past carry one (secret-expired or
sign-in-expired).
Its limits
A Persona's fields are bounded: a name of 1 to 200 characters, unique without regard to letter case among your own private Personas, and among the Personas shared with the organization; a purpose of up to 4,000 characters; a user name of up to 320 characters; a client id and a tenant id of up to 450 characters each; each tag 1 to 64 characters, at most 20 tags on a Persona; and a secret of up to 32 KiB of UTF-8, with no control characters other than tab, line feed and carriage return. A name, a user name, a client id, a tenant id and a tag must each contain some visible text, and a name and a tag hold no control characters or line breaks. A tag is removed by naming it, without regard to letter case.
A list's expiry horizon is bounded: personas_list takes
expiresWithinDays from 0 to 3,650, in whole days.