# Agents, Teams & Tags

## v\_Agent\_{TenantName}

Agent information including tenant membership and profile data. This view combines data from two sources:

* **agent-by-tenant**: Tenant membership data (status, role)
* **agent profile**: Personal data (firstName, lastName, email)

### Columns

| Column       | Type     | Description                      |
| ------------ | -------- | -------------------------------- |
| `id`         | varchar  | Unique agent identifier          |
| `tenantId`   | varchar  | Tenant identifier                |
| `firstName`  | varchar  | First name (from profile)        |
| `lastName`   | varchar  | Last name (from profile)         |
| `name`       | varchar  | Display name (from profile)      |
| `email`      | varchar  | Email address (from profile)     |
| `status`     | int      | Agent status code                |
| `statusName` | varchar  | Status name (see below)          |
| `role`       | int      | Agent role code                  |
| `roleName`   | varchar  | Role name (see below)            |
| `workerId`   | varchar  | Twilio TaskRouter worker ID      |
| `invitedAt`  | datetime | When agent was invited to tenant |
| `updated`    | datetime | Last update timestamp            |

### Status Values

| Name        | Description                |
| ----------- | -------------------------- |
| Invited     | Invited but not yet active |
| Active      | Active agent               |
| Deactivated | Deactivated agent          |

### Role Values

| Name  | Description         |
| ----- | ------------------- |
| Agent | Standard agent role |
| Admin | Administrator role  |

***

## v\_AgentProfile\_{TenantName}

Agent profile data (firstName, lastName, email). This is the underlying data source for agent personal information, filtered to agents belonging to the tenant.

### Columns

| Column      | Type     | Description                 |
| ----------- | -------- | --------------------------- |
| `id`        | varchar  | Unique agent identifier     |
| `firstName` | varchar  | First name                  |
| `lastName`  | varchar  | Last name                   |
| `name`      | varchar  | Full name (computed)        |
| `email`     | varchar  | Email address               |
| `workerId`  | varchar  | Twilio TaskRouter worker ID |
| `createdAt` | datetime | When agent was created      |

{% hint style="info" %}
Agent profiles are filtered per-tenant using `ARRAY_CONTAINS(tenantIds, tenantId)`. Each tenant only sees agents that belong to their organization.
{% endhint %}

### Example Queries

```sql
-- Conversations handled per agent
SELECT a.name, COUNT(*) AS Handled
FROM v_Conversation_YourCompany c
JOIN v_Agent_YourCompany a ON c.assignedToAgentId = a.id
GROUP BY a.name
ORDER BY Handled DESC

-- Agent activity with message counts
SELECT
    a.name,
    COUNT(DISTINCT c.id) AS Conversations,
    COUNT(t.id) AS MessagesSent
FROM v_Agent_YourCompany a
LEFT JOIN v_Conversation_YourCompany c ON c.assignedToAgentId = a.id
LEFT JOIN v_ConversationTimeline_YourCompany t
    ON t.agentId = a.id AND t.typeName = 'Message'
GROUP BY a.name
```

***

## v\_Team\_{TenantName}

Team/queue information.

### Columns

| Column        | Type     | Description            |
| ------------- | -------- | ---------------------- |
| `id`          | varchar  | Unique team identifier |
| `name`        | varchar  | Team name              |
| `description` | varchar  | Team description       |
| `created`     | datetime | When team was created  |
| `updated`     | datetime | Last update timestamp  |

### Example Queries

```sql
-- Conversations per team
SELECT t.name AS TeamName, COUNT(*) AS Conversations
FROM v_Conversation_YourCompany c
JOIN v_Team_YourCompany t ON c.teamId = t.id
GROUP BY t.name
ORDER BY Conversations DESC

-- Open conversations per team
SELECT t.name AS TeamName, COUNT(*) AS OpenConversations
FROM v_Conversation_YourCompany c
JOIN v_Team_YourCompany t ON c.teamId = t.id
WHERE c.statusName = 'Active'
GROUP BY t.name
```

***

## v\_Tag\_{TenantName}

Conversation tags with hierarchy and type support.

### Columns

| Column          | Type     | Description                     |
| --------------- | -------- | ------------------------------- |
| `id`            | varchar  | Unique tag identifier           |
| `tenantId`      | varchar  | Tenant identifier               |
| `tagName`       | varchar  | Tag display name                |
| `description`   | varchar  | Tag description                 |
| `tagType`       | int      | Tag type code                   |
| `tagTypeName`   | varchar  | Tag type: `Topic` or `Metadata` |
| `parentTagId`   | varchar  | Parent tag ID (for nested tags) |
| `level`         | int      | Hierarchy level (0 = root)      |
| `hierarchyPath` | varchar  | Full path in hierarchy          |
| `sortOrder`     | int      | Display sort order              |
| `created`       | datetime | When tag was created            |
| `updated`       | datetime | Last update timestamp           |

### Tag Type Values

| Name     | Description                                                      |
| -------- | ---------------------------------------------------------------- |
| Topic    | Conversation subject (e.g., Billing, Refunds, Technical Support) |
| Metadata | Classification info (e.g., Country, Product, Priority)           |

{% hint style="info" %}
**Topic tags** describe what the conversation is about. **Metadata tags** classify or categorize conversations with additional attributes.
{% endhint %}

### Example Queries

```sql
-- List all tags with hierarchy
SELECT tagName, tagTypeName, level, hierarchyPath
FROM v_Tag_YourCompany
ORDER BY hierarchyPath, sortOrder

-- Get root-level tags only
SELECT tagName, tagTypeName, description
FROM v_Tag_YourCompany
WHERE level = 0
ORDER BY sortOrder

-- Get child tags of a parent
SELECT tagName, level
FROM v_Tag_YourCompany
WHERE parentTagId = 'parent-tag-id'
ORDER BY sortOrder

-- Get only Topic tags
SELECT tagName
FROM v_Tag_YourCompany
WHERE tagTypeName = 'Topic'

-- Conversations by tag (using conversationTagNames from Conversation view)
SELECT conversationTagNames, COUNT(*) AS Count
FROM v_Conversation_YourCompany
WHERE conversationTagNames IS NOT NULL
GROUP BY conversationTagNames
ORDER BY Count DESC
```

{% hint style="info" %}
Tags support hierarchical organization. Use `parentTagId` and `level` to navigate the tree structure. The `hierarchyPath` column contains the full path for sorting and display.
{% endhint %}

***

## v\_CustomFieldDefinition\_{TenantName}

Custom field definitions for contacts and conversations.

### Columns

| Column                | Type    | Description                                      |
| --------------------- | ------- | ------------------------------------------------ |
| `id`                  | varchar | Unique field identifier                          |
| `key`                 | varchar | Field key (used in JSON)                         |
| `name`                | varchar | Display name                                     |
| `description`         | varchar | Field description                                |
| `scope`               | int     | Scope code                                       |
| `scopeName`           | varchar | `Contact` or `Conversation`                      |
| `type`                | int     | Field type code                                  |
| `typeName`            | varchar | Field type (see below)                           |
| `allowedValues`       | varchar | JSON array of allowed values (for select fields) |
| `order`               | int     | Display order                                    |
| `isMandatory`         | bit     | Whether field is required                        |
| `parentFieldKey`      | varchar | Parent field key (for conditional fields)        |
| `visibilityCondition` | varchar | JSON visibility condition                        |

### Scope Values

| Name         | Description                    |
| ------------ | ------------------------------ |
| Contact      | Field applies to contacts      |
| Conversation | Field applies to conversations |

### Type Values

| Name         | JSON Property  |
| ------------ | -------------- |
| Text         | `stringValue`  |
| Integer      | `integerValue` |
| Number       | `numberValue`  |
| Boolean      | `boolValue`    |
| SingleSelect | `stringValue`  |
| MultiSelect  | `arrayValues`  |

### Example Queries

```sql
-- List all conversation custom fields
SELECT [key], name, typeName, allowedValues
FROM v_CustomFieldDefinition_YourCompany
WHERE scopeName = 'Conversation'
ORDER BY [order]

-- List all contact custom fields
SELECT [key], name, typeName, isMandatory
FROM v_CustomFieldDefinition_YourCompany
WHERE scopeName = 'Contact'
ORDER BY [order]

-- Get allowed values for a single-select field
SELECT [key], name, allowedValues
FROM v_CustomFieldDefinition_YourCompany
WHERE typeName IN ('SingleSelect', 'MultiSelect')
```

### Joining with Conversation Custom Fields

Use this view to dynamically extract custom field values with their display names:

```sql
-- Extract custom field values with display names
SELECT
    c.id AS ConversationId,
    cfd.[key],
    cfd.name AS FieldName,
    cfd.typeName,
    CASE cfd.typeName
        WHEN 'Text' THEN JSON_VALUE(c.conversationCustomFields, '$.' + cfd.[key] + '.stringValue')
        WHEN 'SingleSelect' THEN JSON_VALUE(c.conversationCustomFields, '$.' + cfd.[key] + '.stringValue')
        WHEN 'Integer' THEN JSON_VALUE(c.conversationCustomFields, '$.' + cfd.[key] + '.integerValue')
        WHEN 'Number' THEN JSON_VALUE(c.conversationCustomFields, '$.' + cfd.[key] + '.numberValue')
        WHEN 'Boolean' THEN JSON_VALUE(c.conversationCustomFields, '$.' + cfd.[key] + '.boolValue')
    END AS Value
FROM v_Conversation_YourCompany c
CROSS JOIN v_CustomFieldDefinition_YourCompany cfd
WHERE cfd.scopeName = 'Conversation'
    AND JSON_VALUE(c.conversationCustomFields, '$.' + cfd.[key]) IS NOT NULL
```

{% hint style="info" %}
Custom field definitions describe the metadata (name, type, allowed values). The actual values are stored in `conversationCustomFields` (on conversations) and `contactCustomFields` (on contacts) as JSON.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://atender-labs.gitbook.io/atender-labs-docs/analytics/views/agents-teams-tags.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
