Personas
Personas represent browser identities with their own credentials keychain and email inbox. Attach a persona to an agent or journey so the agent knows which credentials to use for authentication.
Overview
Personas are distinct from roles. Where a role controls what an agent says (prompt injection), a persona represents a browser identity with its own credentials and email inbox. Attach a persona to an agent or journey so the agent knows which credentials to use when it needs to log in.
Credentials
Each persona has a credentials keychain. Credentials are stored encrypted and retrieved by the agent at runtime. Two types are supported: username_password (email and password pair) and secret (a single value like an API key or token). A persona can hold multiple credentials, for example an application login plus an API token, or credentials for different environments. The agent picks the right one by label.
Email inbox
Each persona gets a dedicated email address derived deterministically from its name and tenant. Inbound emails are stored and can be read by the agent during execution. This is useful for testing email verification flows, OTP codes, password resets, and any other flow that requires receiving an email.
Create a new persona
Parameters
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
name | string | body | Yes | Persona name (unique per tenant, max 40 characters) |
Status Codes
| Code | Description |
|---|---|
201 | Persona created |
400 | Validation error |
401 | Unauthorized |
409 | Duplicate persona name |
Response Body
{
"id": "aa0e8400-e29b-41d4-a716-446655440000",
"tenant_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Sarah",
"is_default": false,
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}/api/v1/personasList personas
Parameters
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
limit | integer | query | No | Number of results to return (default: 20) |
cursor | uuid | query | No | Cursor for pagination |
Status Codes
| Code | Description |
|---|---|
200 | OK |
401 | Unauthorized |
Response Body
{
"personas": [
{
"id": "aa0e8400-e29b-41d4-a716-446655440000",
"tenant_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Sarah",
"is_default": false,
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
],
"next_cursor": "bb0e8400-e29b-41d4-a716-446655440000"
}/api/v1/personasGet persona by ID
Parameters
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | uuid | path | Yes | Persona ID |
Status Codes
| Code | Description |
|---|---|
200 | OK |
400 | Invalid UUID |
401 | Unauthorized |
404 | Persona not found |
Response Body
{
"id": "aa0e8400-e29b-41d4-a716-446655440000",
"tenant_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Sarah",
"is_default": false,
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}/api/v1/personas/{id}Delete a persona
Deletes a non-default persona. Returns 409 Conflict if the persona is the tenant default — change the default first.
Parameters
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | uuid | path | Yes | Persona ID |
Status Codes
| Code | Description |
|---|---|
204 | Persona deleted |
400 | Invalid UUID |
401 | Unauthorized |
404 | Persona not found |
409 | Cannot delete default persona |
/api/v1/personas/{id}Set a persona as the tenant default
Atomically changes the default persona for the tenant. The previous default is unset. Returns the updated persona.
Parameters
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | uuid | path | Yes | Persona ID |
Status Codes
| Code | Description |
|---|---|
200 | Default updated |
400 | Invalid UUID |
401 | Unauthorized |
404 | Persona not found |
Response Body
{
"id": "aa0e8400-e29b-41d4-a716-446655440000",
"tenant_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Sarah",
"is_default": true,
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:35:00Z"
}/api/v1/personas/{id}/defaultList persona credentials
Returns all credentials associated with this persona. Sensitive values (passwords, secrets) are never included in the response.
Parameters
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | uuid | path | Yes | Persona ID |
Status Codes
| Code | Description |
|---|---|
200 | OK |
400 | Invalid UUID |
401 | Unauthorized |
404 | Persona not found |
Response Body
{
"credentials": [
{
"id": "cc0e8400-e29b-41d4-a716-446655440000",
"persona_id": "aa0e8400-e29b-41d4-a716-446655440000",
"label": "Staging login",
"cred_type": "username_password",
"email": "user@example.com",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
]
}/api/v1/personas/{id}/credentialsAdd a credential to a persona
Creates a new encrypted credential on the persona. The test run can retrieve these at runtime via the get_credentials tool. For username_password and magic_link types, the email is auto-derived from the persona name — emails sent to this address are readable via the test run's emails_read tool (used for magic links, verification codes, and OTPs). For external type, the email is customer-provided and the test run CANNOT read emails sent to it.
Parameters
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | uuid | path | Yes | Persona ID |
label | string | body | Yes | Human-readable label for this credential |
cred_type | string | body | Yes | Credential type: username_password (auto-derived email + password), magic_link (auto-derived email, no password — test run reads login link from its inbox via emails_read), secret (API key or token), or external (customer-provided email + password — note: the test run CANNOT read emails sent to external addresses; emails_read only works with the auto-derived email) |
email | string | body | No | Login email — auto-derived for username_password/magic_link; required and user-supplied for external |
password | string | body | No | Login password (required for username_password and external, stored encrypted) |
value | string | body | No | Secret value (required for secret type, stored encrypted) |
auth_notes | string | body | No | Optional notes about how to authenticate (shown to the test run) |
Status Codes
| Code | Description |
|---|---|
201 | Credential created |
400 | Validation error |
401 | Unauthorized |
404 | Persona not found |
Response Body
{
"id": "cc0e8400-e29b-41d4-a716-446655440000",
"persona_id": "aa0e8400-e29b-41d4-a716-446655440000",
"label": "Staging login",
"cred_type": "username_password",
"email": "user@example.com",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}/api/v1/personas/{id}/credentialsDelete a credential
Removes a credential from the persona.
Parameters
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | uuid | path | Yes | Persona ID |
credentialId | uuid | path | Yes | Credential ID |
Status Codes
| Code | Description |
|---|---|
204 | Credential deleted |
400 | Invalid UUID |
401 | Unauthorized |
404 | Persona or credential not found |
/api/v1/personas/{id}/credentials/{credentialId}