Integration
Consumer Security
This page specifies the authorization model applied to consumer-facing project and agent retrieval, exposed via the /api/v2/project REST endpoints (see Project and Agent API) and execution via /socket/pipeline (plain web socket) or /socket.io (Socket.IO) endpoints.
It covers identity requirements, identity provider verification, external-role authorization, project group-level access, and agent visibility+executability rules.
Project Identity Modes
Each project in platform declares its user identity requirements through isIdentityRequired and identityProviders properties.
| Mode | isIdentityRequired |
identityProviders |
Client behavior when Project is open |
|---|---|---|---|
Not required |
|
empty |
The user is not prompted to sign in. The user’s identity is anonymous and bound to the device via |
Optional |
|
one or more providers |
The client offers sign-in through one of the listed identity providers when the project is opened, with an option to skip and sign in later. An anonymous caller is granted the same access as in |
Required |
|
one or more providers |
The client requires sign-in through one of the listed identity providers before the user can proceed. |
Identity Provider Claim Matching
Whenever a project declares one or more identityProviders, the requesting identity’s provider is checked against them before permission to run or list the project’s agents is granted.
The provider of the requesting identity is resolved as follows:
-
For a JWT-authenticated identity, the
idpRefclaim carried by the token. -
For a Basic-authenticated identity, the
idpRefstored on the matching basic identity record. -
For a request without an authenticated identity, there is no
idpRef(null).
Permission to run or list agents is granted without any further identity provider check when any of these holds:
-
project.identityProvidersis empty (no provider restriction configured), or -
the resolved
idpRefis the reserved valuepai-internal, identifying a fully trusted internal caller, or -
project.isIdentityRequiredisfalseand the request has no authenticated identity at all (and consequently noidpRef) — a fully anonymous caller is treated the same as in Not required mode.
Otherwise, the resolved idpRef must match the ref of one of project.identityProviders. This applies both to a project in Required mode and to any authenticated caller of a project in Optional mode — only a fully anonymous (unauthenticated) caller is exempt from the match in Optional mode. If the idpRef does not match, permission to run or list agents is denied (see Agent State Visibility), independent of isUsingExternalRoles.
Only once the identity provider match succeeds is the optional external-role check, described below, evaluated.
Optional External Role Authorization
A project may additionally restrict permission to run or list agents to identities holding a specific external role, controlled by its isUsingExternalRoles property. This check is evaluated only after the identity provider match described in Identity Provider Claim Matching has succeeded.
When isUsingExternalRoles is set to true, permission is granted only if an AccessControlList record exists, scoped to the project or to its owning tenant, that matches the requesting identity by either of the following:
-
the record’s
userIdmatches the caller’s internal user id (any ACL role qualifies), or -
the record’s
externalIdentity.idpRefmatches the identity provider (idpRef) claim of the identity used to authenticate the request, and itsexternalIdentity.roleis eithernullor is contained in theextRolesclaim of the identity.
If no such record exists, permission to run or list agents is denied. If a matching record is found — or isUsingExternalRoles is false — the project’s data including agents is returned according to the visibility rules described below.
If a project is returned without any agents because the requesting identity is not permitted to run agents there, the client shows a message such as "You do not have any agents available in this project. Reload this screen later or contact project administrator."
Project Groups and Group-Level Access
A project may organize its agents into one or more groups, declared as project.groups (each identified by a ref and a name). An agent optionally declares which of these groups it belongs to via its groupRefs property. An agent with an empty groupRefs does not belong to any group and is not subject to the group-level access rules described in this section.
A project or agent that never had groups explicitly configured is given a built-in default group (ref "default") rather than an empty list. An agent whose only group membership is this default group is treated the same as an agent with an empty groupRefs — always ungated for run purposes — even if the project separately defines a real, restricted group that happens to share the same ref.
Group-Level Access
A group may optionally restrict which identities can see and run the agents that belong to it, via one or more AccessControlList records scoped to the group by their groupRef property (in the same way a project- or tenant-scoped record is scoped via projectId/tenantId), matched by the same rules as project/tenant-level ACL records: the record’s userId matches the caller’s internal user id (any role qualifies), or the record’s externalIdentity.idpRef matches the identity’s idpRef and its externalIdentity.role is either null or contained in the identity’s extRoles.
A group with no such records is open: access to it is governed only by the identity’s general permission to run agents in the project (Identity Provider Claim Matching and, where applicable, Optional External Role Authorization).
For a restricted group (one with at least one ACL record), an identity is additionally granted access to that group only if it matches one of the group’s ACL records as described above.
An agent belonging to one or more groups is visible/executable if the requesting identity has access to at least one of those groups — group memberships are additive access paths, not compounding restrictions. Group-level access is evaluated only after, and only if, the identity’s general permission to run agents in the project already succeeded; it never widens access, only narrows it for agents placed in a restricted group.
Groups in the /api/v2/project Response
The groups array returned by /api/v2/project buckets the agents listed in the response’s agents property (see Agent State Visibility) per group. Each entry carries the group’s name and an agentRefs list, containing the refs of the returned agents whose groupRefs either is empty or contains that group’s ref.
The project’s built-in default group (ref "default") lists only returned agents in the Published state. Preview and Draft revisions visible to the requesting identity are still returned in agents, but are not listed in the default group’s agentRefs.
A group the requesting identity does not have access to is omitted from the groups array entirely, except for the project’s built-in default group (the one every agent with no explicit groupRefs belongs to), which is always included regardless of access.
Whether the requesting user has starred a given agent is reported per agent, via the isStarred property on each entry in agents — not as a separate group.
Agent State Visibility
When sign in is performed OR identity is not required, the project’s agents list property returns agent revisions according to their state, subject to the requesting identity’s permission to run agents (Identity Provider Claim Matching and, where applicable, external role authorization) and its ACL role on the project or tenant. Where noted below, an agent that belongs to one or more groups is additionally subject to group-level access:
Agent.state |
Visibility |
|---|---|
|
Visible to every identity permitted to run agents in the project and, if the agent belongs to one or more groups, holding access to at least one of them — except a |
|
Visible to every identity permitted to run agents in the project that also holds an ACL record (any role) on the project or its tenant — no direct reference required. If the agent belongs to one or more groups, the identity must also hold access to at least one of them. Additionally, when the agent is referenced directly by the |
|
Visible to every identity permitted to run agents in the project that also holds an Additionally, when referenced directly by the |
|
Visible only when referenced directly by the |
Group-level access is enforced identically, and independently of Agent.state, when an agent is executed through /socket/pipeline or /socket.io rather than merely listed: starting a session with an agent that belongs to one or more groups is denied unless the requesting identity holds access to at least one of them, in addition to its general permission to run agents in the project.
Sharing Drafts With an External Organization
An externalIdentity ACL record can satisfy the Draft direct-reference rule above, letting a customer’s staff test a Draft agent via a shared link without adding each person as a project member:
-
Set
project.isUsingExternalRolestotrue. -
Ensure the customer’s identity provider is listed in
project.identityProviders. -
Add one
AccessControlListrecord, scoped to the project or its tenant:{ "externalIdentity": { "idpRef": "<customer-idp-ref>", "role": null }, "role": "Consumer" }
Anyone authenticating through <customer-idp-ref> now satisfies the "any ACL role" requirement for direct-referenced Drafts — no per-person membership needed. This grants access to the customer’s whole organization on that provider, not one individual; for narrower scoping, set externalIdentity.role to a specific value the identity provider actually issues as a claim. It does not unlock Drafts in the regular listing — only the direct link; browsing Drafts still requires Owner/Editor.
Test Agents
An agent implemented as a TestAgent (used to simulate a counterpart persona for roleplay or training rather than to serve real end users) must remain in Published state to be executable, but is excluded from every ordinary agent listing — regardless of state, of the requesting identity’s permission to run agents, and of its ACL role.
A TestAgent is reachable only when referenced directly by the agentRef (or agentKey/agentId) parameter — e.g. a QR-code deep link — and only for an identity holding an Owner or Editor ACL record on the project or its tenant. Any other identity, including one that would otherwise see every Published, Preview, and Draft agent in the project, gets no indication that a TestAgent exists.
Direct Agent Reference Resolution
A project can be retrieved by reference to one of its agents, using agentRef, agentKey, or agentId parameter on /api/v2/project endpoint (see Project and Agent API).
-
A plain reference (
ref,key, oridwithout a revision suffix) resolves only to an agent whosestateisPublished. -
A revision-qualified reference (in
ref.revisionorid.revisionformat) resolves to the exact agent revision regardless of itsstate.
The agent revision resolved by its reference is included in the project’s agents property according to the visibility rules specified in the previous section.