---
updatedAt: 2026-04-06T16:22:31.000Z
agentTools:
  projectIndex: https://developers.newo.ai/llms.txt
---

# Actors, personas, and users

The Newo.ai platform uses a three-layer identity model to track every person or agent that participates in a conversation. Actors represent channel-specific endpoints, personas group those actors into a single profile, and users provide a runtime handle for reading and writing identity data from skill scripts.

## The identity hierarchy

The identity model follows a bottom-up structure. Each layer adds a level of abstraction on top of the one below it:

```mermaid
flowchart TB
    U["User (runtime alias)"] -.->|"alias for"| P["Persona (unified identity)"]
    P --> A1["Actor · Sandbox chat"]
    P --> A2["Actor · WhatsApp"]
    P --> A3["Actor · Phone / voice"]
    P --> A4["Actor · Web widget"]
```

* **Actor** -- A single communication endpoint on a specific integration and connector. An actor is the most granular identity the platform tracks.
* **Persona** -- A collection of one or more actors that all belong to the same real-world person (or agent). A persona carries attributes, a name, a title, and a description.
* **User** -- A runtime concept exposed through skill script actions (`GetUser`, `UpdateUser`). "User" refers to the persona of the human who is interacting with the agent in the current session.

Both humans and agents have personas. In any conversation there is always a **user persona** (the human) and an **agent persona** (the agent). Each side also has at least one actor that represents the specific channel being used.

## Actor model

An actor is the lowest-level identity record. It ties a single external endpoint to a persona through an integration-connector pair. Every inbound message or call creates or resolves an actor before the platform routes the event to an agent.

### Actor fields

| **Field**              | **Type** | **Description**                                                                                                                                            |
| :--------------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                   | UUID     | System-generated unique identifier for the actor.                                                                                                          |
| `name`                 | string   | Display name. For phone actors, this defaults to the phone number.                                                                                         |
| `integration_idn`      | string   | The identifying name of the integration this actor belongs to (e.g., `newo_voice`, `sandbox`).                                                             |
| `connector_idn`        | string   | The identifying name of the connector within the integration (e.g., `vapi_connector`, `widget_connector`).                                                 |
| `external_id`          | string   | An identifier from the external system. For phone calls this is the caller's number without the `+` prefix; for web chat it may be a browser-generated ID. |
| `contact_information`  | string   | Human-readable contact info such as a phone number or email address.                                                                                       |
| `persona_id`           | UUID     | The persona this actor is attached to.                                                                                                                     |
| `time_zone_identifier` | string   | The actor's local time zone, using a TZ database identifier (e.g., `America/New_York`).                                                                    |

## Persona model

A persona is the unified identity that groups actors together. Both users and agents have personas. A persona can have custom attributes (key-value pairs) attached to it, making it the primary place to store profile-level data such as preferences, language, or CRM identifiers.

### Persona fields

| **Field**     | **Type**       | **Description**                                                                                                         |
| :------------ | :------------- | :---------------------------------------------------------------------------------------------------------------------- |
| `id`          | UUID           | System-generated unique identifier.                                                                                     |
| `name`        | string         | Display name for the persona.                                                                                           |
| `title`       | string         | Optional title (e.g., job title or role label).                                                                         |
| `description` | string         | Optional free-text description.                                                                                         |
| `agent`       | object or null | If the persona is linked to an agent, this field contains the agent's `id`, `idn`, and `title`. Null for user personas. |
| `actors`      | array          | The list of actors attached to this persona.                                                                            |

### Persona attributes

Personas support arbitrary custom attributes. You can read, write, and delete attributes through both the API and skill script actions:

* `SetPersonaAttribute(id, field, value)` -- Write an attribute.
* `GetPersonaAttribute(id, field)` -- Read an attribute.
* `DeletePersonaAttribute(id, field)` -- Remove an attribute.

Attributes are stored as key-value pairs and can be grouped for organizational purposes. They are commonly used to store CRM-related data, user preferences, or any information that should persist across sessions and channels.

## User model (runtime)

In skill scripts, the term "user" is an alias for the human's persona in the current session context. The `GetUser` and `UpdateUser` actions provide a convenient way to access persona-level data without needing to look up persona IDs manually.

### Available user fields

| **Field**     | **Description**                         |
| :------------ | :-------------------------------------- |
| `id`          | The UUID of the user's persona.         |
| `name`        | The display name of the user's persona. |
| `title`       | The title field of the persona.         |
| `description` | The description field of the persona.   |
| `type`        | The persona type (user or agent).       |

### Example: reading and updating the user

```nsl
{{set(name="user_name", value=GetUser(field="name"))}}
{{SendMessage(message="Hello, " + user_name)}}

{{UpdateUser(name="name", value="Preferred Name")}}
```

`GetUser` defaults to the current session's user persona. To access a different persona, pass a `personaId` parameter.

## Agent personas

Every agent on the platform also has a persona. The agent persona stores the agent's name and can carry attributes just like a user persona. The key difference is that the agent persona's `agent` field is populated with the linked agent record, while user personas have this field set to null.

### Retrieving the agent persona in skill scripts

The `GetAgentPersona` action returns information about the agent's persona from within a running flow:

```nsl
{{Set(name="agent_name", value=GetAgentPersona())}}
{{Set(name="agent_persona_id", value=GetAgentPersona(field="id"))}}
```

By default, `GetAgentPersona` returns the persona's `name`. Pass `field="id"` to get the persona UUID instead.

### Agent-to-persona linking

Each agent record has a `persona_id` field that links it to its persona. This relationship is established when the agent is created and can be seen in the **Agents** page in Builder.

## Conversation participants

Every conversation in the system tracks participants using the persona and actor model. Each message (called an "act") records both the user side and the agent side:

| **Act field**      | **Description**                               |
| :----------------- | :-------------------------------------------- |
| `user_actor_id`    | The actor ID of the human's channel endpoint. |
| `user_persona_id`  | The persona ID of the human.                  |
| `agent_persona_id` | The persona ID of the agent.                  |
| `agent_actor_id`   | The actor ID on the agent side.               |
| `integration_idn`  | The integration the message arrived through.  |
| `connector_idn`    | The connector within that integration.        |

This structure allows the **Conversations** page in Builder to filter and group messages by user persona, agent persona, or specific actor.

## Multi-channel actor merging

A single person may contact an agent through multiple channels -- phone, web chat, WhatsApp, and so on. Each channel creates a separate actor, but all actors for the same person roll up into a single persona.

### Example: one person, three channels

Consider a customer named Maria who interacts with a hotel booking agent through three different channels:

```mermaid
flowchart TB
    P["Persona: Maria<br/>id: 7a1644f4-..."]
    P --> Phone["Actor: Phone call<br/>integration: newo_voice<br/>connector: inbound_calls<br/>external_id: 15551234567"]
    P --> Chat["Actor: Web chat widget<br/>integration: sandbox<br/>connector: website_widget<br/>external_id: s2SiH1"]
    P --> WA["Actor: WhatsApp<br/>integration: whatsapp<br/>connector: wa_connector<br/>external_id: 15551234567"]
```

Because all three actors share the same persona, the agent has access to Maria's full conversation history and attributes regardless of which channel she uses. This cross-channel continuity is a core feature of the platform.

:::
**🗒️ NOTE**
The platform uses the `external_id`, `integration_idn`, and `connector_idn` combination to determine whether an actor already exists. If a returning caller dials in from the same phone number on the same connector, the existing actor is resolved rather than a new one being created.
:::

## Actor creation flow

Actors are created automatically through a get-or-create pattern. When a new message or call arrives, the platform checks whether an actor already exists for the given `external_id` on the specified integration-connector pair. If not, it creates one.

### How get-or-create works

1. An inbound event arrives with channel-specific identifiers (e.g., a phone number, a chat session ID).
2. The platform calls the persona service's `get-or-create` endpoint with the `customer_id`, `integration_idn`, `connector_idn`, `external_id`, `contact_information`, and `name`.
3. If an actor with that `external_id` on that integration-connector pair already exists, it is returned.
4. If no matching actor exists, a new actor and its parent persona are created. The new actor's ID is returned.
5. The actor ID is then attached to the inbound event so the agent knows who is communicating.

### Creating actors from skill scripts

Actors can also be created programmatically in skill scripts using the `CreateActor` action:

```nsl
{{set(name="persona_id", value=CreatePersona(name="New Contact"))}}
{{set(
    name="actor_id",
    value=CreateActor(
        integrationIdn="sandbox",
        connectorIdn="connector",
        externalId="unique-external-id",
        personaId=persona_id,
        timeZone="America/Los_Angeles"
    )
)}}
```

This is useful for outbound scenarios where the agent needs to initiate contact with a new person on a specific channel.

## Managing personas in Builder

The **Personas** page in Builder provides a UI for viewing and managing personas. From this page you can:

* Search personas by name.
* Filter by whether a persona is linked to an agent ("With Agent") or not ("Without Agent").
* Open a persona to view its **Persona Details** tab (name, title, description, linked agent) and its **Actors** tab (list of all attached actors).
* Delete actors from a user persona. Actors attached to agent personas cannot be deleted from this UI.

:::
**⚠️ CAUTION**
Deleting an actor from a persona is permanent. The platform will no longer associate inbound events from that actor's `external_id` with the persona. A new actor will be created if the same `external_id` contacts the agent again.
:::

## Summary

| **Concept**       | **Purpose**                        | **Scope**                                              |
| :---------------- | :--------------------------------- | :----------------------------------------------------- |
| **Actor**         | Channel-specific endpoint identity | One per integration-connector-external\_id combination |
| **Persona**       | Unified identity across channels   | Groups all actors for one person or one agent          |
| **User**          | Runtime alias in skill scripts     | Points to the human's persona in the current session   |
| **Agent Persona** | Agent's identity                   | One persona per agent, linked via `persona_id`         |

The three-layer model ensures that every interaction is tracked at the channel level (actor), unified at the person level (persona), and accessible in skill scripts through a simple runtime interface (user). See **Integrations** for details on which channels create actors automatically, and see **Actions > Actor** and **Actions > Persona** for the full action reference.