# Agents

An **Agent** is a conversational AI assistant that lives in your account. It has a brain (model + instructions + tools), a look (theme), a set of channels it can talk on (livechat, WhatsApp, Instagram, Messenger), and one or more conversation flows that drive its behavior.

Agents are the top-level entity for everything related to chat. If you're building a chatbot in Frontline, you're building an Agent.

## Identity

| Field | Type | Notes |
|  --- | --- | --- |
| `id` | string | UUID. Use it as `agentId` in nested routes. |
| `name` | string | Max 256 characters. |
| `description` | string? | Optional free text. |
| `status` | enum | `ACTIVE` · `INACTIVE` · `PAUSED` · `ARCHIVED`. |
| `isOffline` | boolean | `true` when the Agent is not serving traffic. Managed via the deployment-status endpoint. |
| `createdAt` | string | ISO timestamp. |
| `updatedAt` | string | ISO timestamp. |


## Sub-resources

An Agent owns several sub-resources, each managed under `/agents/{agentId}/...`:

- **`agent-setting`** — the brain. AI model, instructions, temperature, tone, max iterations, custom tools, playbooks, connected accounts, selected tables. Fields like `aiModelId`, and `customToolIds` are validated against the corresponding resources before being saved.
- **`theme`** — the look. Title, initial message, placeholder, bubble colors, alignment, progress indicator, vertical position. Avatar and bubble image uploads are not exposed in the Public API.
- **`settings/{channel}`** — per-channel behavior. One sub-resource per channel: `livechat`, `whatsapp`, `instagram`, `messenger`. Each carries split-message rules, conversation-close policy, close instruction, etc.
- **`flows`** — conversation flows. See [Flows](/docs/concepts/flows).
- **`variables`** — agent-scoped data placeholders. See [Flow Variables](/docs/concepts/flow-variables).
- **`intents`** — NLP triggers. See [Intents](/docs/concepts/intents).
- **`analytics`** — credit usage, conversation counts, channel breakdown.
- **`conversations`** — read the agent's conversations and their message transcripts (read-only, basic fields). See [below](#reading-conversations--transcripts).


## Reading conversations & transcripts

Read the conversations an agent has handled and the message-by-message transcript of each one. These are **read-only** and currently expose **basic** fields.

**List** `/public/v1/agents/{agentId}/conversations` — paginated, with optional `is_closed`, `start_date`, and `end_date` filters. Each conversation:

| Field | Notes |
|  --- | --- |
| `id` | Use as `conversationId`. |
| `name` | Conversation label, if any. |
| `channel` | E.g. `LIVECHAT`, `WHATSAPP`, `OVERVIEW` (playground). |
| `is_closed` | Whether the conversation has been closed. |
| `contact_id` | Linked People record, if identified. |
| `created_at` | ISO timestamp. |
| `updated_at` | ISO timestamp. |


**Transcript** `/public/v1/agents/{agentId}/conversations/{conversationId}` — the conversation above plus `messages: [{ id, role, type, text, created_at }]`, in order. `role` distinguishes the contact from the agent; `text` is the message body.

## Capturing contact info creates a Person automatically

When a conversation captures a value into one of the standard **contact variables** — `first_name`, `last_name`, `email`, `phone_number` (also `address`, `role`, `website`, `location`, `language`) — that value is written straight to the conversation's **People** record.

Capturing any of the **identification** variables (`first_name`, `last_name`, `email`, `phone_number`) additionally **creates and identifies** the Person: an anonymous conversation contact becomes an identified People record. You do **not** need a separate "create record" step — just capture into those variable names.

- **Deduplication by email.** If the captured `email` matches an existing Person, the conversation is linked to that record instead of creating a duplicate.
- So a flow that collects a contact's name/email should capture into the agent's built-in `first_name` / `last_name` / `email` variables. Adding a node to *also* create the record would produce a **duplicate** People.


See [Flows](/docs/concepts/flows) for capturing variables inside a flow.

## Deployment lifecycle


```
INACTIVE  →  ACTIVE  ←→  PAUSED  →  ARCHIVED
              │
              └── isOffline=true  =  paid for, not serving traffic
```

Publishing an agent goes through `PUT /agents/{agentId}/deployment-status` and triggers billing checks. An offline `ACTIVE` agent is paid for but receives no traffic.

## Operations

| Verb | Path | Purpose |
|  --- | --- | --- |
| `GET` | `/public/v1/agents` | List, with `status` filter |
| `POST` | `/public/v1/agents` | Create (USER key) |
| `GET` | `/public/v1/agents/{agentId}` | Detail |
| `PUT` | `/public/v1/agents/{agentId}` | Update name/description |
| `DELETE` | `/public/v1/agents/{agentId}` | Soft delete (USER key) |
| `PUT` | `/public/v1/agents/{agentId}/deployment-status` | Publish / pause |
| `GET` | `/public/v1/agents/{agentId}/analytics` | Usage analytics |
| `GET` | `/public/v1/agents/{agentId}/conversations` | List conversations |
| `GET` | `/public/v1/agents/{agentId}/conversations/{conversationId}` | Conversation transcript |


Full list in the **[API Reference](/reference/openapi)** under the `Agents` tag.

## CLI


```bash
frontline agents list --status active --table
frontline agents create --name "Support Agent"
frontline agents agent-setting update --data '{"instructions":"Answer concisely.","aiModelId":1}'
frontline agents deploy --offline false
frontline agents conversations --table
frontline agents conversations get 42 --pretty
```

Agent-scoped CLI commands use the active agent saved in the current profile. Override per-call with `--agent-id <id>`.