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

false

empty

The user is not prompted to sign in. The user’s identity is anonymous and bound to the device via deviceRef; it does not carry over to another device.

Optional

false

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 Not required mode; a caller that does sign in must use one of the listed providers, or permission to run or list agents is denied (see Identity Provider Claim Matching).

Required

true

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 idpRef claim carried by the token.

  • For a Basic-authenticated identity, the idpRef stored 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.identityProviders is empty (no provider restriction configured), or

  • the resolved idpRef is the reserved value pai-internal, identifying a fully trusted internal caller, or

  • project.isIdentityRequired is false and the request has no authenticated identity at all (and consequently no idpRef) — 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 userId matches the caller’s internal user id (any ACL role qualifies), or

  • the record’s externalIdentity.idpRef matches the identity provider (idpRef) claim of the identity used to authenticate the request, and its externalIdentity.role is either null or is contained in the extRoles claim 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

Published

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 TestAgent, which is never included in this listing regardless of state; see Test Agents.

Preview

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 agentRef (or agentKey/agentId) parameter — typically through an /a/{agentRef} link — it is included unconditionally, regardless of permission to run agents (identity provider match or external-role authorization), regardless of ACL role, and regardless of group-level access, as long as either the project does not require identity or the caller is authenticated.

Draft

Visible to every identity permitted to run agents in the project that also holds an Owner or Editor ACL record 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 referenced directly by the agentRef (or agentKey/agentId) parameter, it is included for any identity holding an ACL record of any role on the project or its tenant, regardless of permission to run agents and regardless of group-level access.

Archived

Visible only when referenced directly by the agentRef (or agentKey/agentId) parameter, and only for an identity holding an ACL record of any role on the project or its tenant, regardless of permission to run agents and regardless of group-level access.

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.isUsingExternalRoles to true.

  • Ensure the customer’s identity provider is listed in project.identityProviders.

  • Add one AccessControlList record, 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, or id without a revision suffix) resolves only to an agent whose state is Published.

  • A revision-qualified reference (in ref.revision or id.revision format) resolves to the exact agent revision regardless of its state.

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.