# Moveo.AI Documentation
> Revolutionize your customer experience using an AI agent
This file contains all documentation content in a single document following the llmstxt.org standard.
## Dialog webhooks
A dialog webhook is a webhook that runs as part of a workflow. You add a **webhook action** to a dialog node, point it at a configured webhook, and the AI Agent calls your endpoint when the conversation reaches that node. The endpoint can return new context variables (to carry data forward) or its own [responses](./responses/overview) (to take control of the agent's reply).
Use a dialog webhook to:
- Validate information collected from the user.
- Fetch data from another system, like a customer record or inventory status.
- Trigger an action with side effects, such as sending an OTP or creating a ticket.
:::note
This page covers how to wire a dialog webhook into a workflow. To configure the webhook itself (URL, verification token, headers), see [Webhooks](./webhooks). For the request and response payload schemas, see [Build a webhook](./build-a-webhook).
:::
## Add a webhook action to a workflow
1. Open the AI Agent and pick the dialog where you want the webhook to run.
2. Drag a **Webhook** action onto the node, in the position where the call should happen.
3. Configure the action:
| Field | Description |
| --- | --- |
| Webhook | Pick the webhook from the list of webhooks configured on the AI Agent. Only webhooks of type `dialog` appear here. |
| Fallback | A text response sent to the user if the webhook call fails or times out. Used as a graceful degradation when `fail on error` is off. |
Once the action runs, any context variables your endpoint returns are immediately available to the rest of the workflow — condition nodes downstream can branch on them, and other actions can interpolate them into their text.
## What gets sent and received
When the action fires, Moveo sends the conversation's full context, the user's input, and the recognized intents and entities. Your endpoint replies with any combination of:
- **Context updates** — new or changed variables to carry forward in the session.
- **Responses** — a list of reply objects (text, media, carousel, webview, etc.) that the agent will deliver to the user instead of generating its own reply.
Full schemas for the request body, the supported response types, and the rules around updating context are in [Build a webhook → Type reference](./build-a-webhook#type-reference).
---
## Advanced setup
The **Advanced** page allows you to configure key parameters of your AI Agent, including selecting a
language model, setting prediction confidence, and defining inactivity timeouts.
## Match user's language
By default, responses are generated in the language the AI Agent has been set up to. However, you can configure the AI Agent to match the user's language regardlessly of the language the AI Agent has been set up to, or if the knowledge base is in a different language.
To do this you have to:
1. Navigate to your AI Agent
2. Go to **Overview** tab
3. Click on the **Advanced** section in the sidebar
4. Enable the **Match user's language** switch
5. Save your changes
## Model strategy
The **Models** section lets you choose the language models that power your AI Agent. You set a
**default** list of models that run in order — if one fails, the next takes over — and you can
optionally **customize the models per channel** (Chat, Email, and Voice).
For full details, see the [Model strategy](./model-strategy.md) guide.
## Prediction threshold
This setting controls the confidence level required for an **[intent](./intents.md)**
prediction to be considered correct. The threshold ranges from 0 to 1.
- **Lower threshold (more flexible, but increases false positives)**\
In customer support scenarios, a lower threshold allows the AI Agent to be more responsive. Even if
it’s uncertain about a user’s intent, it will still attempt a relevant response. This helps keep conversations
flowing but may sometimes result in incorrect predictions.
- **Higher threshold (more conservative, requiring clearer user input)**\
In fields like legal or financial assistance, a higher threshold ensures only the most confident predictions
are accepted. This reduces errors but may require users to phrase their questions more precisely for
accurate responses.
## Inactivity timeout
This setting determines how long the AI Agent retains context before resetting due to user
inactivity.
:::note
This timeout will take over the whole session time out when this AI Agent is assigned to it.
:::
For a comprehensive understanding of timeout mechanisms in Moveo, including inactivity timeout,
session timeout, and keep alive, refer to the [Timeout mechanisms](../guides/timeouts) documentation.
Adjusting this setting optimizes the AI Agent's performance based on your workflow requirements.
- **Shorter timeouts (e.g., 5–30 min)** → Ideal for fast-paced interactions where outdated context
should be discarded quickly. This prevents the AI Agent from using stale information that might
mislead the conversation.
- **Longer timeouts (e.g., 2, 8, 24 hours, or more days)** → Useful for cases where conversations span extended
periods. For example, in complex troubleshooting or long-running customer support sessions, a
longer timeout allows the AI Agent to maintain context even if the user returns hours later.
## Factuality sensitivity
This setting controls how strictly AI Agent responses are evaluated for correctness before being
delivered to the user. When a response doesn't meet the selected guard level, it is redirected to
the [Unknown](./triggers/unknown.md) flow instead of being delivered.
- **Off** → No factuality enforcement. Responses are delivered without validation.
- **Light Guard** → Flags major inaccuracies and attempts correction, but delivers the response
anyway.
- **Strong Guard** (default) → Catches major inaccuracies, attempts correction, and redirects to the
Unknown flow if correction fails.
- **Maximum Guard** → Catches both major and minor inaccuracies, attempts correction, and redirects
to the Unknown flow if correction fails.
**Minor inaccuracies** are small assumptions that are not explicitly supported by the provided
knowledge but remain plausible, low-risk, and non-contradictory.
**Major inaccuracies** are claims or instructions that are unsupported, invented, or contradictory
to the provided knowledge and risk misleading the user.
:::tip
Use **Strong Guard** or **Maximum Guard** in regulated industries (e.g., finance, healthcare, legal)
where accuracy is critical. Use **Light Guard** for more conversational use cases where strict
factuality is less important.
:::
## Reminder
A reminder is a feature that triggers a [dialog node](./dialogs.md#triggers) when a certain period of time passes after the last user message.
In order to set up a reminder:
1. Go to your AI Agent
2. Go to **Settings** tab
3. Scroll to **Reminder** section
4. Select the waiting to trigger the reminder
5. Select the node that should handle the reminder
6. Save your changes
---
## Build a webhook
This guide walks through implementing a webhook endpoint that Moveo can call during a conversation. It covers the request format, signature verification, response contracts per webhook type, operational practices, and a few worked use cases. A complete TypeScript type reference is at the end.
The examples use Next.js with TypeScript, but the patterns translate to any HTTP framework.
:::note
For configuring a webhook in the Moveo UI (URL, verification token, custom headers, types) and for the payload differences across types, see [Webhooks](./webhooks).
:::
## What you'll build
By the end of this guide you will have:
1. An HTTPS endpoint that accepts `POST` requests from Moveo.
2. HMAC SHA256 verification of the `X-Moveo-Signature` header.
3. Body validation with Zod.
4. A response shaped for the webhook type you configured (dialog, first message, pre message, or post message).
## Prerequisites
- Node.js 18 or newer
- A TypeScript project (Next.js, Express, Fastify, or any HTTP framework)
- A public-facing HTTPS URL — non-HTTPS URLs are rejected by Moveo in production
- A verification token configured on the webhook in the Moveo UI
## The request from Moveo
Every webhook call is a `POST` with a JSON body. The body shape depends on the [webhook type](./webhooks#payload-differences-per-type); the headers are the same across types:
| Header | Description |
| --- | --- |
| `X-Moveo-Signature` | HMAC SHA256 of the request body, hex-encoded |
| `X-Moveo-Request-Id` | Unique identifier for this call — log it for correlation |
| `X-Moveo-Session-Id` | The conversation session |
| `X-Moveo-Account-Id` | The Moveo account |
| `X-Moveo-Account-Slug` | The account slug |
Custom headers configured on the webhook are sent on every call. The full payload reference per webhook type is in the [Webhooks](./webhooks#payload-differences-per-type) page; ready-to-use type definitions for TypeScript, Python, and Go are in the [Type reference](#type-reference) at the end of this guide.
## Verify the signature
The signature confirms the request came from Moveo and was not tampered with. Always compute it before doing anything else with the body — including parsing it as JSON, in case the body was modified in transit.
Use the **raw request body** (not a parsed JSON object) and the verification token configured on the webhook.
```ts title="verify-signature.ts"
export const verifySignature = (rawBody: string, signature: string, token: string): boolean => {
const expected = crypto.createHmac('sha256', token).update(rawBody).digest('hex');
const a = Buffer.from(expected, 'hex');
const b = Buffer.from(signature, 'hex');
return a.length === b.length && crypto.timingSafeEqual(a, b);
};
```
```py title="verify_signature.py"
def verify_signature(raw_body: bytes, signature: str, token: str) -> bool:
expected = hmac.new(token.encode("utf-8"), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
```
Use a constant-time comparison (`timingSafeEqual` / `compare_digest`) — a regular string `===` is vulnerable to timing attacks.
## A complete handler
The handler below runs four steps in order: verify the signature, validate the body, do the work, respond. The example is for a dialog webhook; the same skeleton applies to event webhooks — only the body schema and the response shape change.
```ts title="api/orders.ts"
const WEBHOOK_TOKEN = process.env.MOVEO_WEBHOOK_TOKEN!;
const bodySchema = z.object({
context: z.object({
customer_id: z.string(),
}),
});
export const config = {
api: { bodyParser: false },
};
const readRawBody = async (req: NextApiRequest): Promise => {
const chunks: Buffer[] = [];
for await (const chunk of req) {
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
}
return Buffer.concat(chunks).toString('utf-8');
};
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// 1. Verify the signature against the raw body
const rawBody = await readRawBody(req);
const signature = req.headers['x-moveo-signature'];
if (typeof signature !== 'string' || !verifySignature(rawBody, signature, WEBHOOK_TOKEN)) {
return res.status(401).json({ error: 'invalid signature' });
}
// 2. Parse and validate the body
const body = bodySchema.parse(JSON.parse(rawBody));
// 3. Do the work
const order = await fetchOrder(body.context.customer_id);
// 4. Respond — context updates feed back into the conversation
return res.json({
context: {
order_status: order.status,
order_total: order.total,
},
});
};
export default handler;
```
A few notes on the structure:
- **Disable the body parser**, or capture the raw body before it is parsed, so the signature is computed against the exact bytes Moveo signed.
- **Validate at the boundary.** Use Zod (or your validator of choice) once at the top of the handler. Downstream functions should receive already-typed inputs.
- **Keep the handler thin.** External API calls belong in their own module. Idempotency, retries, and caching are concerns of the underlying API client, not the webhook handler.
## Respond by webhook type
Each webhook type has its own response contract. Returning fields the contract does not honor is silently ignored.
### Dialog webhooks
A dialog webhook can return a `context` object, a `responses` array, or both. The `responses` array supports text, media, event, carousel, webview, and reset entries — see the [response action types](#response-actions) below.
```json
{
"context": {
"order_status": "pending",
"order_total": 49.5
},
"responses": [
{
"type": "text",
"texts": ["Your order is on the way!"]
}
]
}
```
Responses are validated. Invalid responses are logged as warnings and skipped; a request that fails validation entirely returns an error to the agent.
### First message and pre message webhooks
Return a `context` object and, optionally, a modified `input`. These webhooks fire before the agent processes the user's input and cannot reply on the agent's behalf.
The `input` object accepts two fields:
- **`input.text`** — replaces the user message before the agent sees it. Useful for normalization or moderation. 1–4096 characters.
- **`input.trigger_node_id`** — UUID of an existing dialog node. Routes directly to that node and bypasses intent classification. The UUID must reference a node on the AI Agent.
```json
{
"context": {
"live_instructions": "The user is George, a VIP customer.",
"user_crm_level": "platinum"
}
}
```
Rewrite the user input:
```json
{
"input": {
"text": "I want to cancel my order"
}
}
```
Route to a specific dialog node:
```json
{
"input": {
"trigger_node_id": "9c8e4f1a-2d6b-4e3a-9f1b-1c2d3e4f5a6b"
}
}
```
### Post message webhook
Return a `context` object and, optionally, a `responses` array. If `responses` is present, it replaces the agent's planned reply for this turn. Items in this array are sent to the user as-is — no templating or context-variable substitution is applied.
```json
{
"context": {
"last_intent": "order_inquiry"
},
"responses": [
{
"type": "text",
"texts": ["Override: please contact us at support@example.com."]
}
]
}
```
### Context update rules
The same rules apply to every webhook type that returns a `context`:
- At most 100 variables, 32 KB total.
- Names: 1–128 characters, alphanumeric plus `_`, `-`, `.`.
- Reserved names that cannot be set or overwritten: `user`, `global`, `channels`, `campaign`, `tags`, anything beginning with `sys-` or `channels.`.
- Individual `user.*` fields can be updated using dotted-path notation (e.g. `"user.email": "alice@example.com"`); the `user` object as a whole cannot be replaced.
## Operating in production
A few constraints to design around:
- **Timeouts** — Moveo waits 1.5 seconds for the connection and 15 seconds for a response. Defer non-critical work (analytics, log shipping, cache warming) until after the response is sent.
- **No automatic retries** — a failed call surfaces as an error to the agent and is not retried. If your endpoint must be exactly-once, implement idempotency on your side using `X-Moveo-Request-Id` as the dedupe key.
- **HTTPS only** — non-HTTPS URLs and loopback or private addresses are rejected at configuration time in production.
- **History is opt in** — to receive `history` in the body, add `X-Moveo-Include-History: true` as a custom header on the webhook configuration. Without it, history is omitted to keep payloads small.
- **Choose `fail_on_error` deliberately** — leave it off for non-critical webhooks (analytics, enrichment) so the agent can keep talking when your endpoint hiccups. Turn it on for webhooks the conversation cannot proceed without (authentication, payment).
- **Don't log payload bodies as is** — Moveo payloads typically contain user information. Log identifiers (`X-Moveo-Request-Id`, `session_id`) instead.
## Test locally
You can test your endpoint with `curl` once you compute a valid signature. The signature is HMAC SHA256 of the exact body bytes, keyed with the verification token from the Moveo UI:
```sh
BODY='{"channel":"web","session_id":"abc","brain_id":"xyz","lang":"en","context":{"customer_id":"123"}}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$MOVEO_WEBHOOK_TOKEN" | awk '{print $2}')
curl -X POST https://your-app.example.com/api/orders \
-H "Content-Type: application/json" \
-H "X-Moveo-Signature: $SIG" \
-d "$BODY"
```
For an end-to-end test against Moveo itself, expose your local server with ngrok or Cloudflared, paste the public URL into the webhook configuration, and use the **Send test request** button in the [UI tester](./webhooks#test-your-webhook).
## Use cases
The patterns below are the worked counterparts of the brief use cases on the [Webhooks](./webhooks#use-case-examples) page.
### Use case: live instructions
**Webhook type:** first message or pre message.
Fetch user data from your system the moment a session starts and inject it into the conversation as `live_instructions`. The agent reads `live_instructions` from context on every turn and uses it to personalize replies. This is the cleanest way to keep the agent's prompt short while still acting on real-time customer data.
```ts title="api/live-instructions.ts"
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const userId = req.body.context.user_id;
const userInfo = await API.getUserInfo(userId);
const { name, transactions, atm } = userInfo;
const latestTransaction = transactions[0];
const liveInstructions = [
`1. User name: ${name}`,
`2. Recent activity: ${name} made a ${latestTransaction.type} of ${latestTransaction.amount} ${latestTransaction.currency}, pending and expected to settle in 2–4 days.`,
`3. The nearest ATM is at ${atm.address}.`,
].join('\n');
return res.json({
context: {
live_instructions: liveInstructions,
},
});
};
export default handler;
```
:::tip
Format `live_instructions` with newlines (`\n`) and consistent numbering. The agent reads it as plain text — well-structured input produces more reliable behavior.
:::
### Use case: validate input
**Webhook type:** dialog.
Drop a [webhook action](./action-webhooks) into a dialog node to check something the user said against your backend before the conversation continues. Update context with the result, and use a regular condition node downstream to branch on it.
```ts title="api/check-account.ts"
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// 1, 2 — verify signature + validate body (omitted for brevity)
const accountNumber = req.body.context.account_number;
const account = await API.lookupAccount(accountNumber);
if (!account) {
return res.json({
context: { account_valid: false },
});
}
return res.json({
context: {
account_valid: true,
account_balance: account.balance,
account_holder: account.holder,
},
});
};
```
### Use case: post message audit
**Webhook type:** post message.
Inspect the agent's planned reply, log it, and optionally replace it. Useful for compliance review, trailing analytics, or A/B testing different response styles without changing the dialog.
```ts title="api/post-message.ts"
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// 1, 2 — verify signature + validate body (omitted for brevity)
const { session_id, output, intents } = req.body;
await API.logTurn({
sessionId: session_id,
intent: intents[0]?.intent,
responseTypes: output.map((response) => response.type),
});
// Pass through unchanged — return only context.
return res.json({
context: {
last_intent: intents[0]?.intent ?? null,
},
});
};
```
To override the reply instead of passing through, return a `responses` array — the rules are the same as for dialog webhooks.
## Type reference
Drop-in type definitions are available in TypeScript, Python, and Go. Each file covers the request bodies for all four webhook types, the context object, the response shape per type, and the response action types you can return.
| Language | File |
| --- | --- |
| TypeScript | [`moveo-webhooks.ts`](/types/moveo-webhooks.ts) |
| Python (Pydantic v2) | [`moveo_webhooks.py`](/types/moveo_webhooks.py) |
| Go | [`moveo_webhooks.go`](/types/moveo_webhooks.go) |
### Using the types
Import the request and response types you need, and parameterize them with an interface describing the custom variables your AI Agent collects:
```ts
DialogWebhookRequest,
DialogWebhookResponse,
} from './moveo-webhooks';
interface OrderVars {
customer_id: string;
order_status?: 'pending' | 'shipped' | 'delivered';
}
const handler = async (
req: DialogWebhookRequest
): Promise> => {
// req.context.customer_id is typed as string
// req.context.user.display_name is available
return {
context: { order_status: 'shipped' },
};
};
```
Pydantic models validate the body at the boundary. Subclass `MoveoContext` to type your custom variables:
```py
from moveo_webhooks import (
DialogWebhookRequest,
DialogWebhookResponse,
MoveoContext,
)
class OrderContext(MoveoContext):
customer_id: str
order_status: str | None = None
# Inside your handler:
body = DialogWebhookRequest.model_validate(payload)
order_context = OrderContext.model_validate(body.context.model_dump(by_alias=True))
return DialogWebhookResponse(
context={"order_status": "shipped"},
).model_dump(exclude_none=True)
```
Decode into the request struct, embed `Context` if you need typed custom variables, and encode a response struct:
```go
// Copy moveo_webhooks.go into your module under, for example,
// internal/moveowebhooks, and import it from there.
type OrderContext struct {
mw.Context
CustomerID string `json:"customer_id"`
OrderStatus string `json:"order_status,omitempty"`
}
type orderRequest struct {
mw.RequestBase
Input mw.MessageInput `json:"input"`
Intents []mw.Intent `json:"intents"`
Entities []mw.Entity `json:"entities"`
UserMessageCounter int `json:"user_message_counter"`
Debug mw.Debug `json:"debug"`
Context OrderContext `json:"context"`
}
var req orderRequest
if err := json.Unmarshal(rawBody, &req); err != nil {
// handle error
}
resp := mw.DialogWebhookResponse{
Context: map[string]any{"order_status": "shipped"},
}
return json.Marshal(resp)
```
### Context
The session context, with the special `user` object and reserved system variables:
```ts title="moveo-webhooks.ts"
export interface MoveoContextUser {
readonly user_id: string;
readonly external_id?: string;
display_name?: string;
avatar?: string;
email?: string;
phone?: string;
address?: string;
language?: string;
timezone?: string;
location?: { city?: string; country?: string; region?: string; latitude?: number; longitude?: number };
browser?: string;
platform?: string;
device?: string;
ip?: string;
verified?: boolean;
verified_method?: 'jwt' | 'otp' | 'email' | 'qr';
verified_at?: string;
}
export type MoveoContext = Record> = TVars & {
user?: MoveoContextUser;
tags?: string[];
channels?: Record>;
global?: Record;
campaign?: { campaign_id?: string; subscriber_id?: string; sender_id?: string };
live_instructions?: string | Record | null;
// Read only — managed by Moveo and rejected when overwritten in a response.
'sys-channel'?: string;
'sys-session'?: string;
'sys-business'?: 'open' | 'closed';
'sys-user_message_counter'?: number;
'sys-unknown_counter'?: number;
};
```
### Request bodies
All four request types share a common envelope and add type-specific fields. `TVars` is your interface describing the custom variables the AI Agent collects.
```ts title="moveo-webhooks.ts"
export interface MoveoWebhookRequestBase = Record> {
channel: string;
channel_type: string;
session_id: string;
desk_id: string;
integration_id: string;
brain_id: string;
lang: string;
context: MoveoContext;
timestamp: number;
history?: MoveoHistoryMessage[]; // present only with X-Moveo-Include-History: true
}
export interface DialogWebhookRequest extends MoveoWebhookRequestBase {
input: MoveoMessageInput;
intents: MoveoIntent[];
entities: MoveoEntity[];
user_message_counter: number;
debug: { dialog_stack: { node_id: string; name: string }[] };
}
export interface FirstMessageWebhookRequest extends MoveoWebhookRequestBase {
input: MoveoMessageInput;
business_closed: boolean;
}
export interface PreMessageWebhookRequest extends MoveoWebhookRequestBase {
input: MoveoMessageInput;
business_closed: boolean;
}
export interface PostMessageWebhookRequest extends MoveoWebhookRequestBase {
input: MoveoMessageInput;
intents: MoveoIntent[];
entities: MoveoEntity[];
user_message_counter: number;
output: MoveoAgentAction[]; // broader than MoveoResponseAction — see below
debug: { dialog_stack: { node_id: string; name: string }[] };
}
```
### Response actions
What your endpoint can put inside a `responses` array. Dialog and post message webhooks accept these; first message and pre message webhooks ignore them.
```ts title="moveo-webhooks.ts"
export type MoveoResponseAction =
| { type: 'text'; texts: string[]; options?: { label: string; text: string }[] }
| { type: 'image' | 'video' | 'audio' | 'file'; url: string; name?: string; size?: number }
| { type: 'event'; trigger_node_id: string }
| { type: 'webview'; name: string; label: string; url: string; height?: 'tall' | 'compact' | 'full'; trigger_node_id?: string }
| { type: 'carousel'; cards: MoveoCarouselCard[]; action_id: string }
| { type: 'reset' };
```
### Agent actions
The post message webhook's `output` field is broader than `MoveoResponseAction` — the agent can plan additional action types (handover, url, tag, reminder, internal webhook calls) that you cannot return from your own endpoint:
```ts title="moveo-webhooks.ts"
export type MoveoAgentAction = (
| MoveoResponseAction
| { type: 'handover'; external: boolean }
| { type: 'url'; url: string }
| { type: 'tag'; tags: string[] }
| { type: 'reminder'; reminder_seconds: number; trigger_node_id: string }
| { type: 'webhook'; webhook_id: string; fallback: MoveoAgentAction[] }
) & {
action_id?: string;
metadata?: Record;
};
```
### Response bodies
The shape your endpoint returns, per webhook type:
```ts title="moveo-webhooks.ts"
export interface DialogWebhookResponse {
context?: Partial>;
responses?: MoveoResponseAction[];
}
export interface PreMessageWebhookResponse {
context?: Partial>;
input?: MoveoMessageInput; // rewrite the user input before the agent sees it
}
export type FirstMessageWebhookResponse = PreMessageWebhookResponse;
export interface PostMessageWebhookResponse {
context?: Partial>;
responses?: MoveoResponseAction[]; // if present, replaces the agent's planned reply
}
```
## Next steps
- [Webhooks](./webhooks) — concept overview, types, UI configuration
- [Dialog webhooks](./action-webhooks) — how to wire a dialog webhook into a workflow
---
## Build an MCP server
This guide walks through building a custom MCP server that Moveo can connect to as a tool provider for an AI agent. It covers the implementation, the tool-design choices that determine whether the agent calls your tools correctly, and the operational practices that keep the server reliable in production.
The examples use Next.js App Router with TypeScript, but the patterns translate to any HTTP framework.
:::note
For configuring an MCP server in the Moveo UI (adding a server, managing tools, resyncing) and for runtime behavior numbers, see [MCP servers](./mcp-servers).
:::
## What you'll build
By the end of this guide you will have:
1. A route that exposes an MCP endpoint over Streamable HTTP.
2. One tool with a Zod-validated input schema and a description that the agent uses correctly.
3. An authentication strategy you can pick from: no auth, header-based, URL-based, or OAuth.
4. A working URL you can paste into Moveo to connect the agent.
## Prerequisites
- Node.js 18 or newer
- A TypeScript project (Next.js, Express, Fastify, or any HTTP framework)
- A public-facing HTTPS URL (production: Vercel, Cloud Run, Fly.io; local development: ngrok or similar)
## Install dependencies
```bash
npm install mcp-handler @modelcontextprotocol/sdk zod
```
`mcp-handler` is a thin wrapper that hosts an MCP server over Streamable HTTP and provides an `withMcpAuth` helper for OAuth. `@modelcontextprotocol/sdk` is the official MCP SDK. `zod` validates tool inputs.
## Create the route
Create `app/api/your-server/mcp/route.ts`:
```typescript
export async function POST(request: Request): Promise {
const handler = createMcpHandler(
(server) => {
server.registerTool(
searchOrders.name,
{
title: searchOrders.name,
description: searchOrders.description,
inputSchema: searchOrders.inputSchema.shape,
},
searchOrders.handler
);
},
{
serverInfo: { name: 'your-server', version: '1.0.0' },
},
{
basePath: '/api/your-server',
disableSse: true,
}
);
return handler(request);
}
```
A few details that matter:
- **`disableSse: true`** — Moveo only connects over Streamable HTTP. The legacy SSE transport is [rejected at the URL-validation step](./mcp-servers#enter-the-server-url).
- **`basePath`** — must match the route path so the MCP handler resolves the correct endpoint.
- The setup callback is where you register every tool the server exposes.
## Define a tool
Create `app/api/your-server/mcp/tools/search-orders.ts`:
```typescript
export const searchOrders = {
name: 'search_orders',
description: 'Search the order database by order number or customer email.',
inputSchema: z.object({
query: z.string().describe('Order number or customer email to search for'),
limit: z.number().int().min(1).max(20).default(5),
}),
handler: async (args: { query: string; limit: number }) => {
const orders = await fetchOrders(args.query, args.limit);
if (orders.length === 0) {
return {
content: [
{ type: 'text' as const, text: `No orders found for "${args.query}".` },
],
};
}
const text = orders
.map((o) => `Order #${o.id} — ${o.status}, ${o.total} ${o.currency}`)
.join('\n');
return { content: [{ type: 'text' as const, text }] };
},
};
```
That's a working tool — but the description is too thin to make the agent call it reliably. The next section covers the tool-design choices that actually move the needle.
---
## Tool design
A tool's name, description, and input schema are part of the system prompt the agent sees. Whether the agent calls the right tool at the right time depends much more on these strings than on the model behind the agent. Treat them as prompt copy.
### The four surfaces the agent sees
Every tool exposes four prompt surfaces. Each is read by the model on every turn.
1. **Tool name** — short identifier the agent uses to invoke the tool.
2. **Tool description** — free text. The agent's primary signal for *when* to use the tool.
3. **Input schema** — JSON Schema with field-level descriptions. The agent reads each field's description to fill in arguments.
4. **Tool result** — what the tool returns. The agent uses this to compose a reply or chain into the next tool.
Edit all four like you'd edit a guideline.
### Tool names
```typescript
// Good
'search_orders'
'cancel_appointment'
'send_invoice'
'get_customer'
// Bad
'do_thing' // no information for the agent
'OrderSearch' // wrong case
'query' // generic, collides across tools
'fetch_data' // no domain
'order' // not a verb — is this get? search? create?
```
1. Use lowercase `snake_case`. Most MCP SDKs require it; the model also handles it more reliably.
2. Lead with a verb. The verb signals action.
3. Use singular for "get one" and plural for "list/search". `get_order` returns one; `search_orders` returns many.
4. Avoid generic names like `query`, `fetch`, `lookup`, `data`. They collide across tools and force the model to read every description.
5. Match the user's vocabulary. If your support team says "ticket" and your database says "issue", name the tool around the user-facing word.
6. Keep names stable. Renaming a tool flips the server [status](./mcp-servers#status-indicators) to **Outdated** and forces a [resync](./mcp-servers#resync-tools). Old guidelines that referenced the old name break.
### Tool descriptions
The description is where the agent learns when to call the tool. The model is forced to choose between similarly-named tools by reading these few sentences. Make them count. The same string also appears as a tooltip in the Moveo UI when an operator hovers a tool in the [Edit panel](./mcp-servers#edit-a-server) — write it for both audiences.
A reliable structure is **WHAT, WHEN, HOW, RETURNS, NOT**:
```typescript
description: `Search the order database by order number or customer email.
WHAT: Returns matching orders with their status, total, and last-updated date.
WHEN:
- Customer asks about a specific order they placed
- Customer mentions an order number, email, or "my order"
- Customer asks about delivery status of an existing order
HOW:
- query: order number (numeric, 6+ digits) or customer email address
- limit: defaults to 5; raise only if the customer explicitly asks for more
RETURNS: Up to N orders, leading with the most recent. Empty list if no match.
NOT: For shipping policy or returns, use the knowledge base. For creating new orders, use \`create_order\`. For order line items, use \`get_order_details\`.`
```
The **NOT** section is the highest-leverage. Whenever two tools collide in the agent's mind, fix it by writing a *better NOT* in one description, not by adding rules to a guideline.
Other tips:
1. Start the description with the verb. The model often reads only the first line under time pressure.
2. Include domain vocabulary the user will use. If users say "service appointment", put that phrase in the description even if your code calls it `service_booking`.
3. State side effects. If the tool sends an email or charges a card, say so explicitly. Otherwise the agent might call it for exploration and surprise the user.
4. Keep it under ~200 words. Long descriptions waste context, and the model often skims.
### Input schemas
The agent reads the schema to know what arguments to send. It honors types, enums, and `describe` strings. Make the schema do as much work as possible.
```typescript
// Good
inputSchema: z.object({
query: z.string().min(1)
.describe('Order number or customer email to search for'),
status: z.enum(['active', 'cancelled', 'pending', 'completed'])
.optional()
.describe('Filter results to a single status'),
limit: z.number().int().min(1).max(20).default(5)
.describe('Maximum number of results'),
})
// Bad
inputSchema: z.object({
q: z.string(), // no description, ambiguous name
filters: z.record(z.any()), // free-form, no constraints
options: z.object({ // deep nesting
pagination: z.object({
offset: z.number(),
page_size: z.number(),
}),
}),
})
```
1. **Describe every field.** A field with no description is a coin flip.
2. **Use enums for known sets.** Free-form strings invite typos.
3. **Set sensible defaults.** The agent will call the tool with fewer arguments and fewer mistakes.
4. **Mark required fields explicitly.** The model treats a missing required field as a hard error — which is what you want when the user hasn't provided the information yet.
5. **Keep it flat.** Deeply nested objects confuse the model.
6. **Validate at the edges.** Add `min`/`max`, `pattern`, `format` constraints the model can read. Even though Moveo [validates arguments](./mcp-servers#tool-invocation) before forwarding, the agent uses these hints when constructing the call.
7. **Don't expose internal IDs.** If your tool needs an `account_id` the user has never typed, the agent can't fill it. Read it from the [Moveo session context](#what-moveo-sends-to-your-server) instead.
8. **Use units in field names.** Prefer `delay_seconds` over `delay`, `price_cents` over `price`. The model picks up on units in field names and rarely converts incorrectly.
### Tool results
The string the tool returns is appended to the conversation as if the tool just spoke. Write it for the agent to summarize — not for an end user to read directly.
```typescript
// Good — leads with the answer, formatted for paraphrasing
return {
content: [{
type: 'text' as const,
text: `Found 3 orders for jane@example.com:
**Order #4521** — shipped, $89.00 USD, updated Mar 2
**Order #4498** — delivered, $145.50 USD, updated Feb 28
**Order #4399** — refunded, $32.00 USD, updated Feb 14
Ask which one the customer is asking about.`,
}],
};
// Bad — JSON dump
return {
content: [{
type: 'text' as const,
text: JSON.stringify(orders),
}],
};
```
1. **Lead with the answer.** Don't bury it under metadata.
2. **Use markdown sparingly.** Bold for emphasis, lists for enumerations. Tables sometimes confuse smaller models.
3. **Cap volume.** Return at most 5–10 results. The agent can ask the user to narrow down.
4. **Include enough for paraphrasing.** If the agent will ask "is this the right one?", the result needs to contain the disambiguating fields.
5. **Tell the agent what to do next when ambiguous.** "Multiple matches — ask the customer for the order number" inside the result text is more effective than relying on guidelines.
6. **Use the result, not the description, for things that change.** Inventory counts, prices, and status belong in the result. The description is static.
### Error messages
When something goes wrong, return a tool result with `isError: true` and a clear message.
```typescript
// Good — actionable, plain language
return {
content: [{
type: 'text' as const,
text: 'Order #4521 not found. The order number may be wrong, or it could belong to a different account. Ask the customer to confirm the number.',
}],
isError: true,
};
// Bad — leaks implementation, not actionable
return {
content: [{
type: 'text' as const,
text: '404 NOT_FOUND: SELECT * FROM orders WHERE id=4521 returned 0 rows',
}],
isError: true,
};
```
1. **Tell the agent what happened in plain language.** Not error codes.
2. **Tell the agent what to do next.** This becomes the agent's natural reply.
3. **Distinguish recoverable from terminal errors.** "Service is temporarily unavailable, retry in 30 seconds" is recoverable. "This account is closed" is not.
4. **Don't leak implementation.** Stack traces, internal hostnames, SQL errors are noise to the model and risk to your operation.
5. **Match the user's language.** If the conversation is in Spanish, errors should be in Spanish.
### Disambiguating between tools
Two tools that look similar from the agent's perspective will be confused. Diagnose with these questions:
1. **Are the names verb-distinct?** `get_order` vs. `search_orders` is good. `get_order` vs. `find_order` is a coin flip.
2. **Do the WHEN sections actually differ?**
3. **Does each description name the other?** "Use this for one order by ID; use `search_orders` when the user gives a name or email instead" cross-references reliably.
4. **Could it be one tool with a mode parameter?**
```typescript
// Two close-cousin tools — the agent has to pick the right one
{
name: 'find_order_by_id',
description: 'Look up an order by its numeric ID.',
inputSchema: z.object({ id: z.string() }),
}
{
name: 'find_order_by_email',
description: 'Find orders for a customer by email address.',
inputSchema: z.object({ email: z.string().email() }),
}
// One tool with a mode — the agent picks from a known enum
{
name: 'find_order',
description: 'Find orders by ID or by customer email.',
inputSchema: z.object({
query: z.string().describe('Order ID or customer email'),
by: z.enum(['id', 'email']).describe('How to interpret the query'),
}),
}
```
### Iteration loop
Tool prompts are like guideline copy: ship a draft, watch the model use it, refine.
1. **Run the agent in the test panel** with realistic user messages that should trigger the tool.
2. **Watch the trace** for two failure modes:
- The agent does not call the tool when it should. The description's WHEN section is too narrow or the name is wrong.
- The agent calls the tool when it shouldn't. Add a NOT clause that rules out the case it just got wrong.
3. **Watch for fishing.** Repeated calls with slight argument variations mean the model doesn't trust the result format. Make the result more decisive.
4. **Watch for hallucination.** If the agent describes calling the tool ("Let me search the orders…") without actually calling it, the description is unclear about whether the tool needs to be invoked vs. mentioned. Tighten WHAT to "Returns…" rather than "Helps with…".
5. **Refine the tool, not the prompt.** When in doubt, the fix lives in the tool definition. Guidelines that say "remember to call `search_orders`" are a smell — the description should make the call self-evident.
### Anti-patterns
These keep recurring. Audit your tools for them.
- **Tool name as an action.** `do_thing`, `process_request`, `handle_input`.
- **Description as documentation.** Long parameter docs, "see also" links, deprecation notices.
- **Free-form strings where enums belong.** A `status` field that takes any string. The agent will invent values.
- **Identical names with different shapes.** `get_user` on two different MCP servers, with different schemas. Moveo does not let the agent disambiguate by server. Rename one.
- **Returning JSON to the agent.** The agent reads the result as text. Return prose or markdown that summarizes the JSON, not the JSON itself.
- **One mega-tool with `mode` covering 12 use cases.** Fan out into 2–4 specific tools instead.
- **Side effects with no warning.** A tool named `lookup_customer` that secretly creates a CRM contact. Either rename or split.
---
## Referencing tools from guidelines
Once your tool is connected in Moveo, the people writing the agent's guidelines can mention it inline. In any guideline editor (Overview, Features, Custom Instructions, Objections), typing `@` opens a picker that lists every enabled tool. Selecting one inserts an inline badge.
A realistic guideline reads like business prose with tool references woven in:
> When the customer asks about a specific order or mentions an order number, use `@search_orders` to find it. If multiple orders match, ask the customer to confirm which one before continuing.
>
> If the customer wants to cancel, only use `@cancel_order` after confirming the order number out loud — never cancel based on a partial match.
Two practical implications for tool design:
1. **Names appear verbatim in guidelines.** A clean name like `search_orders` reads naturally; `do_search_v2_final` does not. Renames break every guideline that referenced the old name.
2. **Tools can be enabled per-guideline.** Disabling a tool in a guideline removes its references automatically. Build small, focused tools that can be selectively enabled — large catch-all tools become unwieldy. The operator selects which tools are enabled per server in the [Edit panel](./mcp-servers#edit-a-server).
The agent reads both the guideline copy and the tool description. The guideline tells it the *workflow*; the description tells it *what the tool does*. Keep them aligned: if the guideline says "search orders by email or order number", the description's WHEN section should match.
---
## Authentication
Pick the simplest authentication that meets your security requirements. Moveo's MCP servers UI supports four modes; this section shows how to implement the server side of each.
### No authentication
If your tools are read-only and your endpoint URL is hard to enumerate, public access is acceptable. The route shown above accepts any caller.
In Moveo, when you add the server, the **Authentication mode** is detected as **None** and the connection is verified automatically. See [No authentication](./mcp-servers#no-authentication) in the UI walkthrough.
### Header authentication
Validate a static credential that Moveo passes on every request:
```typescript
export async function POST(request: Request): Promise {
const apiKey = request.headers.get('x-api-key');
if (apiKey !== process.env.MCP_API_KEY) {
return new Response('Unauthorized', { status: 401 });
}
const handler = createMcpHandler(/* ... */);
return handler(request);
}
```
In Moveo:
1. Add the server with the URL of your route.
2. Discovery returns 401 because no header is set yet.
3. Choose **Header authentication** and add a header row: key `x-api-key`, value ``.
4. Select **Connect**.
For the full UI flow, see [Header authentication](./mcp-servers#header-authentication) in the MCP servers walkthrough.
Header auth fits server-to-server integrations where you can rotate a static secret on a regular schedule. Common conventions:
| Convention | Header |
|------------|--------|
| Bearer token | `Authorization: Bearer ` |
| Custom API key | `X-Api-Key: ` |
| Vendor-specific | `X--Token: ` |
### URL-based authentication
Embed a token directly in the URL path:
```typescript
// app/api/your-server/mcp/[token]/route.ts
export async function POST(
request: Request,
{ params }: { params: { token: string } }
): Promise {
if (params.token !== process.env.MCP_URL_TOKEN) {
return new Response('Not Found', { status: 404 });
}
const handler = createMcpHandler(
(server) => { /* register tools */ },
{ serverInfo: { name: 'your-server', version: '1.0.0' } },
{
basePath: `/api/your-server/mcp/${params.token}`,
disableSse: true,
}
);
return handler(request);
}
```
In Moveo, paste the URL with the embedded token. Discovery succeeds because the URL itself is the credential, so the **Authentication mode** is detected as [**None**](./mcp-servers#no-authentication).
URL-based auth is convenient for per-tenant URLs — give each customer their own token-embedded URL and the server can route to the right tenant from the path. It is **not recommended** for long-lived production secrets because the token typically appears in HTTP access logs, CDN caches, and observability tools.
### OAuth
For full OAuth 2.0 with PKCE, wrap the handler with `withMcpAuth`:
```typescript
export async function POST(request: Request): Promise {
const handler = withMcpAuth(
createMcpHandler(/* ... */),
verifyToken,
{
required: false,
resourceMetadataPath:
'/.well-known/oauth-protected-resource/',
}
);
return handler(request);
}
```
`verifyToken` is your function that takes the incoming `Request` and a Bearer token, and returns either an `AuthInfo` object on success or `undefined` to reject. A typical implementation verifies against the authorization server's JWKS:
```typescript
const JWKS = createRemoteJWKSet(new URL('https://issuer.example.com/oauth2/jwks'));
export async function verifyToken(req: Request, bearerToken?: string) {
if (!bearerToken) return undefined;
try {
const { payload } = await jwtVerify(bearerToken, JWKS, {
issuer: 'https://issuer.example.com',
});
return {
token: bearerToken,
clientId: payload.sub || '',
scopes: payload.permissions || [],
};
} catch {
return undefined;
}
}
```
Provide an OAuth Resource Metadata endpoint at the path you specify in `resourceMetadataPath`, returning the authorization server's discovery URL. Moveo follows that metadata to negotiate the rest of the flow, including dynamic client registration if your provider supports RFC 7591. For the user-facing flow — popup, dynamic registration, manual client credentials fallback — see [OAuth authentication](./mcp-servers#oauth-authentication).
If your server uses OAuth, support refresh tokens and document any scopes you require. Moveo stores access and refresh tokens for the connection but cannot recover from a revoked refresh token without a fresh authorization flow.
## What Moveo sends to your server
On every tool call, Moveo includes correlation headers so you can log, route, and rate-limit per tenant:
| Header | Description |
|--------|-------------|
| `x-moveo-account-id` | Account that owns the conversation |
| `x-moveo-account-slug` | Account slug |
| `x-moveo-brain-id` | Identifier of the AI agent making the call |
| `x-moveo-desk-id` | Desk identifier |
| `x-moveo-session-id` | Conversation session |
| `x-moveo-external-id` | External user identifier |
| `x-moveo-request-id` | Request correlation ID |
| `x-moveo-user-agent` | Moveo user-agent string |
In addition, conversation context is passed in the MCP request `_meta` field. From inside a tool handler, access it via the `extra` parameter:
```typescript
handler: async (args, { extra }) => {
const moveoContext = extra._meta?.['moveo/context']?.context;
const language = extra._meta?.['moveo/context']?.lang;
const channel = extra._meta?.['moveo/context']?.channel;
// ...
}
```
The `context` object holds the agent's session variables. Set them from the agent side using a [live-instructions webhook](./build-a-webhook#use-case-live-instructions) before the tool call.
## Update Moveo session context from a tool
Tools can write back to the agent's session variables by including a `_meta` field in the response:
```typescript
return {
content: [{ type: 'text' as const, text: 'Found 3 orders.' }],
_meta: {
'moveo/context': {
context: {
last_search_query: args.query,
last_search_count: orders.length,
},
},
},
};
```
The new variables are merged into the session and become available to subsequent tool calls and guidelines (where they can be referenced as `$last_search_query`).
## Deploy and connect from Moveo
1. Deploy your server to a public HTTPS URL.
2. In Moveo, navigate to your AI agent → **Workflows** → **MCP servers** → **Add MCP server**.
3. Paste the full URL of your route (for example, `https://your-server.example.com/api/your-server/mcp`).
4. Pick the matching authentication mode and complete the auth step.
5. Select the tools to expose and save.
For the full configuration walk-through in the Moveo UI, see [MCP servers](./mcp-servers).
## Test locally
Use a tunnel like [ngrok](https://ngrok.com/) to expose `localhost` over HTTPS, then connect from Moveo with that URL.
For automated testing without Moveo, send a JSON-RPC `tools/list` request directly:
```bash
curl -X POST https://your-server.example.com/api/your-server/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```
A successful response lists the registered tools with their input schemas.
## Operating your MCP server in production
Tool calls happen inside live conversations. The runtime numbers (timeouts, retries, validation, cache TTL) are documented under [Runtime behavior](./mcp-servers#runtime-behavior). The practices below are how you build for them.
### Respect the connection budget
Moveo's [connection and discovery](./mcp-servers#connection-and-discovery) handshake is bounded by a 30-second timeout. If your server depends on cold-start work — warming a database connection, fetching auth metadata, loading a model — do that lazily rather than blocking the handshake. The first request can pay the warmup; the handshake should not.
### Keep tool calls fast
Tools are called inside a live conversation. Long-running work should either complete in a few seconds or run asynchronously and return a status the agent can poll. Avoid synchronous tool calls that take longer than the user is willing to wait.
### Implement timeouts on the server side
Wrap any outbound call your tool makes (HTTP requests, database queries, third-party APIs) with its own timeout that is **shorter** than the [Moveo tool-call budget](./mcp-servers#tool-invocation) (65 seconds). Never let an unbounded operation hang the call.
### Make tool calls idempotent
Moveo [retries](./mcp-servers#tool-invocation) connection-level failures and HTTP 5xx/429 once with exponential backoff. Tool-level errors that you return with `isError: true` are passed back to the agent without retrying — that's a deliberate signal. Idempotent tools (same input → same effect) let Moveo retry transport failures safely, and let the agent re-issue a call without duplicating side effects.
### Add retries inside the tool for transient failures
If your tool depends on flaky downstream services, retry inside the server with bounded attempts and exponential backoff. Surface a single, clear error to Moveo only when retries are exhausted.
### Version tool definitions deliberately
Changes to a tool's description or input schema flip the server [status](./mcp-servers#status-indicators) to **Outdated**. Plan changes so users can [resync](./mcp-servers#resync-tools) at a predictable time, and avoid removing a tool without a deprecation window — guidelines that referenced the removed tool will lose their references.
## Next steps
- [MCP servers](./mcp-servers) — connect your built server to Moveo and manage it
- [Local tools](./local-tools) — built-in tools that don't require an external server
- [Live instructions](./build-a-webhook#use-case-live-instructions) — set session context that MCP tools can read
---
## Compliance profiles
Compliance profiles help align your AI Agent with regulatory requirements for outbound campaigns. When a compliance profile is active, the platform applies protections designed to respect legal restrictions, such as blocking contact when regulations require it and respecting time-of-day and frequency limits.
Each campaign is assigned a compliance profile that determines which protections are applied.
:::warning Important
Compliance protections take precedence over custom instructions and [guidelines](./knowledge.md#guidelines).
:::
:::caution
Compliance profiles are designed to assist with regulatory compliance, but they are not a substitute for legal counsel. You are responsible for ensuring your campaigns comply with all applicable laws and regulations.
:::
:::note
These profiles are actively evolving. Protections may be added and parameters may change.
:::
## How it works
When a compliance profile is assigned, contact attempts are checked against the profile's protections before they are sent. If a protection is triggered:
- **Contact is stopped** when the regulation requires it — for example, if the subscriber has filed for bankruptcy or has requested to cease communications.
- **Contact is delayed** when timing or frequency restrictions apply — for example, quiet hours or frequency caps.
Blocked contacts and their reasons are visible on the campaign's [Performance tab](../campaigns/performance.md), under **Barriers to progress**.
## Setting a compliance profile
You select a compliance profile during [campaign creation](../campaigns/campaigns.md):
1. Go to **Campaigns** and click **+ Create** (or edit an existing campaign)
2. In the campaign setup step, select a **Compliance profile** from the dropdown
3. Continue with the rest of the campaign configuration
## Available profiles
Across the debt collection profiles, a phone number or email address identified as not belonging to the consumer is not contacted again. This reflects FDCPA §804 (third party) and TCPA called-party consent (first party).
### Default
Applies no regulatory protections. Suitable for testing or non-regulated campaign use cases.
:::danger
This profile does not enforce debt collection regulations. Do not use for real subscriber contact in regulated industries.
:::
---
### US debt collection (first party)
For US first-party debt collection — when the original creditor collects on their own debts.
This profile includes protections for:
- **Bankruptcy Code** — Automatic stay protections
- **SCRA** — Active-duty military servicemember protections
- **Rosenthal Act** (California) — Contact frequency limits for California residents
- **940 CMR 7.04** (Massachusetts) — Contact frequency limits for Massachusetts residents
State-specific frequency caps are applied based on the subscriber's state of residence.
---
### US debt collection (third party)
For US third-party debt collection — collection agencies and debt buyers. This profile covers federal FDCPA and Reg F requirements, bankruptcy and military protections, and state-level restrictions for California and Massachusetts.
**Federal regulations:**
- **FDCPA:**
- Cease and desist (§805(c)) and refusal to pay — permanently stops contact on all channels when a subscriber requests it in writing.
- Attorney representation (§805(a)(2)) — restricts direct contact when a subscriber is represented by an attorney.
- Disputes (§809) — stops collection on disputed debts pending verification.
- Coerced debt (§809) and identity theft (§809, FCRA §1681c-2) — permanently stops contact.
- Inconvenient contact (§805(a)(1)) — delays contact proposed outside the subscriber's stated preferred times or days.
- **Reg F** — Enforces the 7-call-per-7-day frequency cap (§1006.14(b)): no more than 7 voice call attempts per 7 days per debt, and no calls within 7 days of a connected conversation. Enforces quiet hours (§1006.6(b)): contact is delayed if proposed outside 8:00 AM – 9:00 PM in the subscriber's local time. Covers deceased subscribers (§1006.6(a)(4)): contact is permanently stopped when a subscriber is confirmed deceased.
- **Bankruptcy Code** — Respects the automatic stay (11 U.S.C. §362). When a subscriber has filed for bankruptcy, all contact is permanently stopped.
- **SCRA** — Protects active-duty military servicemembers (50 U.S.C. §3901). When active-duty status has been confirmed, contact is permanently stopped pending review of applicable SCRA protections.
**State-specific regulations:**
- **California** — Enforces the Rosenthal Act's prohibition on unreasonable contact frequency. No more than 7 voice call attempts per 7 days for California residents.
- **Massachusetts** — Enforces 940 CMR 7.04(1)(f). No more than 2 communications (voice calls and SMS combined) per 7 days to a personal number for Massachusetts residents. Email is excluded. Unanswered calls count toward the limit.
State-specific frequency caps apply **in addition** to the federal frequency cap and are automatically enforced based on the subscriber's state of residence.
---
### Brazil debt collection (third party)
For third-party debt collection in Brazil. This profile covers requirements under the Consumer Defense Code (Código de Defesa do Consumidor) and stricter state-level rules.
**National rules:**
- **Cease communications:** contact is permanently stopped when a consumer asks to stop being contacted.
- **Contact hours:** contact is delayed if proposed outside Monday to Friday, 9:00 AM to 7:00 PM, or Saturday, 10:00 AM to 1:00 PM. Sundays are not contacted.
- **Public holidays:** contact is delayed on national public holidays.
- **Frequency cap** (CDC Art. 71): no more than 3 contact attempts per day, and no contact within 1 day of a connected conversation.
**State-specific rules:**
Several states enforce stricter contact hours, applied automatically based on the consumer's state of residence:
- **Rio de Janeiro** (Lei 7.868/18) and **Espírito Santo** (Lei 10.626/17): Saturday contact is not allowed.
- **Paraná** (Lei 22.130/24) and **Amazonas** (Lei 4.644/2018): weekday contact ends at 6:00 PM.
---
### Greece debt collection (third party)
For third-party debt collection in Greece. This profile covers requirements under Greek Law 3758/2009 on debtor-information companies (as amended).
This profile includes protections for:
- **Grace period:** contact does not begin until 10 days after a debt becomes overdue.
- **Contact hours:** contact is delayed if proposed outside 9:00 AM to 8:00 PM on working days.
- **Public holidays:** contact is delayed on national public holidays.
- **Frequency limits:** up to 7 voice call attempts per day, and no more than one verified contact with the debtor every 2 days. Reaching the wrong party does not count toward the verified-contact limit.
---
## Conversation-level protections
Beyond the outbound checks above, the AI agent applies compliance guardrails during live conversations:
- **Stopping collection** when the consumer asks to cease communications, disputes the debt, reports identity theft or fraud, indicates the debt was coerced, states they have filed for bankruptcy, says they are represented by an attorney, reports the account holder is deceased, or identifies as an active-duty servicemember.
- **Responding to safety signals**: if the consumer expresses self-harm or suicidal thoughts, the agent stops immediately and responds with concern.
- **Avoiding prohibited topics**, such as credit reporting, litigation, wage garnishment, or asset seizure.
- **Protecting third parties**: the agent does not disclose debt details to anyone who is not the consumer.
In Brazil, the agent also informs consumers who report financial hardship of their right to request consolidated renegotiation under the over-indebtedness law (Lei 14.181/2021).
:::tip
Additional compliance profiles are being developed. If your use case requires a profile that is not listed, contact your account manager or reach out to [support](mailto:support@moveo.ai).
:::
---
## Context and variables
## Overview
In Moveo, store temporary information during a conversation using **context variables**.
These variables apply only to a specific conversation and are automatically deleted once the
conversation ends. Context is a collection of key-value pairs that help AI Agents make decisions,
store state, and enhance dialog interactions.
Context variables can be set at different levels:
- **Environment level** (see [Context Bundles](../environments/context-bundles.md))
- **Agent level** (within AI Agents and dialogs)
Additionally, context can store user-related information, such as their name, email, or other
relevant data.
## Types of context variables
### Dialog variables
Create and store variables within a dialog using [questions](./operations/questions.md).
These variables are flexible and can be named as needed.
### User variables
User-related information is stored in specific system-defined variables, including:
- **`$user.display_name`** – User's name
- **`$user.email`** – User's email address
- **`$user.user_id`** or **`$user.external_id`** – Unique user ID (depends on the communication
channel)
Some user variables, such as user IDs, are automatically assigned by the system, while others
require manual input via **questions** or **forms** at the start of a conversation.
:::warning
User variables **cannot be set directly**. To assign a value using a
[**Set Variable** action](./operations/set-variables.md), select the appropriate key (e.g.,
`$user.display_name`).
For webhook responses, refer to the [Webhook reference](./action-webhooks#sending-replies).
:::
### System variables
Moveo provides system-generated variables that contain essential metadata about the conversation:
| Variable | Description |
| --------------------------- | ----------------------------------------------------------------- |
| `$sys-channel` | Communication channel of the conversation |
| `$sys-unknown_counter` | Number of times a [fallback](./triggers/unknown.md) was triggered |
| `$sys-business` | Indicates if the conversation occurs within business hours |
| `$sys-desk` | Identifies the conversation environment |
| `$sys-session` | Unique conversation ID |
| `$sys-user_message_counter` | Number of messages sent by the user |
:::note
The **`$sys-unknown_counter`** variable is **zero-indexed**, meaning the first unknown
response occurrence is stored as `0`.
:::
### Bundle variables
Import variables from **[Context Bundles](../environments/context-bundles.md)** associated with different
environments. These variables follow the format: `{{$global.bundle.variable}}`.
### Tags
[Tags](./operations/tag.md) assigned by the AI Agent during a conversation are stored in
**`$tags`** as a list. For example, if the assistant assigns `location` and `hours` tags, `$tags`
will contain `['location', 'hours']`.
This variable is useful for:
- Filtering conversations in **[Analytics](../analytics/overview.md)**
- Triggering specific actions using **[Rules](../environments/rules.md)**
- Enhancing human-agent interactions (agents can manually assign tags)
To add a new tag, use the **`Add Tag`** dialog action.
### Live instructions
The `live_instructions` variable allows real-time updates to the AI Agent, guiding its behavior
dynamically based on external input.
## Using context in dialogs
Context variables enable various dialog functionalities, such as:
- **Setting new variables**
- **Updating existing ones**
- **Deleting variables**
- **Making decisions using conditions** ([Learn more](./operations/conditions.md))
For example, you can check whether a user has provided their email and prompt them accordingly if
it's missing.
### Ways to set context variables
- **[Questions](./operations/questions.md)** – Collect information during a dialog.
- **[Webhooks](./webhooks.md)** – Update variables in real time based on external data.
- **[Set Variable action](./operations/set-variables.md)** – Directly assign values in dialogs.
## Using context variables
Reference variables in the dialog by using `{{$variable}}`.
For example:
```plaintext
Hello {{$user.display_name}}, how can I assist you today?
```
Refer to the documentation for more guides on handling context variables effectively.
---
## Dialogs
Dialogs are a feature of [AI Agents](../ai-agents/overview.md). Their purpose is to define fixed
workflows that the AI agent can follow in a conversation. A dialog is composed of several different
blocks, which are connected to each other. Each of these block have different functionalities and
have different roles.
Each dialog consists of [**trigger**](#triggers) and [**action**](#actions) nodes.
## Triggers
Every [dialog](./dialogs.md) starts with a single trigger. Moveo.AI supports the following triggers:
| Type | Description |
| :-------------------------------- | :------------------------------------------------------------------------------------ |
| [Intent](./triggers/text.md) | Triggered on text messages, when the AI agent recognizes an intent |
| [Event](./triggers/event.md) | Triggered internally from a different dialog node |
| [Fallback](./triggers/unknown.md) | Triggered when Moveo cannot match any of the dialog nodes given the recognized intent |
### Add a trigger
Add a new trigger by using Moveo's drag-and-drop functionality.
### Uses of triggers
Moveo has two different functionalities for triggers:
- They can be used as the parent trigger ($r\_0$, `nodes[0]`) in a dialog.
- They can be used as child triggers to provide a different response. See what happens for an
[intent trigger](./triggers/text.md#how-to-use-an-intent-trigger) and a
[fallback trigger](./triggers/unknown.md).
#### Enhance with AI
Toggle "Enhance with AI" in the trigger node’s sidebar to enrich responses with relevant contextual
information.
## Actions
Each time the user sends a message, the AI agent activates one or more [triggers](#triggers). It can
then respond in a variety of forms.
Actions include plain text, links, menus, and options. Add one or
more actions below a [trigger](#triggers) by dragging and dropping them.
### Types of actions
Moveo.AI supports the following responses, operations, and extensions:
#### Responses
| Response | Description |
| :---------------------------------- | :-------------------- |
| [Text](./responses/text.md) | Reply with a text |
| [Image](./responses/image.md) | Send an image |
| [Carousel](./responses/carousel.md) | Reply with a carousel |
| [Webview](./responses/webview.md) | Display a webview |
| [Video](./responses/video.md) | Send a video |
| [File](./responses/file.md) | Send a file |
| [Survey](./responses/survey.md) | Display a survey |
| [URL](./responses/url.md) | Send a URL |
#### Operations
| Operation | Description |
| :--------------------------------------------- | :-------------------------------------- |
| [Question](./operations/questions.md) | Ask a question to the user |
| [Jump to](./operations/event.md) | Trigger a specific node |
| [Condition](./operations/conditions.md) | Create a logic tree |
| [Handover](./operations/handover.md) | Transfer the conversation to an agent |
| [Tag](./operations/tag.md) | Label the conversation with a tag |
| [Pause](./operations/pause.md) | Pause the conversation |
| [Set variables](./operations/set-variables.md) | Set a variable equal to a value |
| [Reset variables](./operations/reset.md) | Reset specific or all context variables |
| [Resolve](./operations/resolve.md) | Close the conversation |
#### Extensions
| Extension | Description |
| :----------------------------------------- | :--------------------------- |
| [Webhook](./responses/webhook.md) | Call a predefined webhook |
| [Google Sheet](./responses/googlesheet.md) | Store data in a Google Sheet |
| [Email](./responses/email.md) | Send an email |
### Add an action
Add one or more actions below a [trigger](#triggers) by using Moveo's drag-and-drop functionality.
## Folders
A **folder** is a group of dialogs. Its purpose is to create a clean and organized AI Agent,
so that you can coordinate better and be more efficient. It's like organizing clothes in a closet's
shelves, instead of putting them all in one cupboard. To (re)name a folder, you can double-click its
name and enter the new one.
### Moving around dialogs
Drag and drop a dialog from any folder to another. Drag a
dialog to the area at the bottom of the list to create a new folder, or click on any dialog and then
on the **Create dialog** button to create a dialog under the folder you are at.
## Export and import a dialog
1. Select the dialog you want to export.
2. Click on the contextual menu in the top right corner.
3. Select **Export dialog** or **Import dialog**.
:::note
The exported dialog will be a JSON file.
:::
## Limits
Each new dialog turn in Moveo is designed to efficiently handle up to 80 trigger nodes and completes
within a maximum timeframe of 17 seconds. This setup ensures optimal performance and user experience
during interactions. In practice, these limits are rarely reached unless an unintended infinite loop
is introduced through the dialog's event structure.
### Loop Detection
To safeguard against such scenarios, Moveo employs real-time loop detection mechanisms. These
mechanisms monitor the creation of dialog event loops, typically occurring due to incorrectly
configured `jumpTo` actions that inadvertently create cyclic dependencies between dialogs. For
instance, a dialog named "Dialog Affirmative" jumps to "Dialog UserInfo", which in turn jumps back
to "Dialog Affirmative", forming a loop.
While some loops might be intentionally designed to achieve specific conversational flows, most are
accidental and can disrupt the user experience. If Moveo detects potential looping behavior, it
issues a warning message pointing out the actions in the dialogs that created the loop. This
notification serves as a prompt to review and, if necessary, revise the dialog configuration to
eliminate the unintended loop. However, if the loop is part of your design and functions as
intended, you may disregard this warning.
### Troubleshooting
When naming an intent trigger, keep in mind that you are not allowed to use more than 45 characters.
Whenever you use a condition, you must add at least one rule and attach a response (action) or you
will not be able to save your changes.
The field inside an intent trigger cannot be empty. If it is empty, you will not be able to save the
changes. Consider converting the intent trigger to an event trigger if you encounter this issue.
To attach a new file in a dialog, ensure that the file is accessed through a URL. If you want to use
a photo or video, make sure the file is accessed through a URL. For carousels, the title's maximum
length is 32 characters and the subtitle's is 80 characters. Each card supports a maximum of 3 buttons,
with up to 6 cards total. The Carousel's title, Button's Label, and Postback are mandatory fields.
Always remember that when you save your changes, they are not visible to the end user. To make them
visible, you must **Publish** them.
---
## Entities
Entities are terms or objects that provide context for an [intent](../ai-agents/intents.md)
(question category). An entity is the tool that lets you drill down to the options (values) you want
your end user to choose from.
## Values
Values are the options that derive from an entity. These choices dig further into specific
information your AI Agent needs to resolve any issue. Values can also provide more context, allowing
you to delve deeper into specific information.
## Synonyms and Patterns
In the **Entity | Value | Synonym/Pattern** triad, synonyms and patterns represent the last layer.
### Synonyms
Use synonyms to declare different ways the user can refer to each value. The following table
shows a possible implementation of an entity that uses synonyms.
#### Entity **`@payment_methods`**
| Values | Type | Synonyms/Patterns |
| :------: | :-----: | :----------------------------------: |
| **card** | Synonym | `visa` `mastercard` `credit` `debit` |
| **bank** | Synonym | `bank transfer` |
| **web** | Synonym | `PayPal` |
### Patterns
Patterns control the way information is captured. Patterns are written in the form
of [regular expressions](https://en.wikipedia.org/wiki/Regular_expression) with very
specific structures like dates, telephone numbers, email addresses, credit card numbers, ZIP codes,
and more.
The following table shows a possible implementation of an entity that uses patterns:
#### Entity **`@contact_info`**
| Values | Type | Synonyms/Patterns |
| :--------: | :-----: | :---------------: |
| **e-mail** | Pattern | `\S+@\S+` |
| **phone** | Pattern | `\d{10}` |
## Add a New Entity
1. While in your AI Agent, click on the **Entities** tab.
2. Click on the **+** icon and change the name and description of your entity.
3. Add the entity values along with their synonyms or patterns.
:::note
Each value can contain either synonyms or patterns, not both.
:::
## Import an Entity
To import an entity, click on the import icon on the top right to select a local CSV file. The CSV
file **must** have the following format:
- Four columns with headers `Entity`, `Type`, `Value`, `Synonyms/Patterns`.
- Optional: Under `Entity`, include the name of your imported entity.
- Under `Type`, write either `synonym` or `pattern`.
- Under `Value`, include the value of the entity.
- Under `Synonyms/Patterns`, include the comma-separated synonyms or patterns.
Once you upload the file, the values with their synonyms and/or patterns are visible. Save to add
the entity to your AI Agent.
Download an example
CSV
file containing an entity.
### Troubleshooting
An entity can only take one value in an end user's sentence. This means that if a single sentence
contains two or more values of an entity, only **one** of the values will be matched.
In the example below, the entity `@payment_methods` contains two values (`card`, `cash`). If the
user's sentence contains both of those values, then only one value will be matched to the entity.
More specifically, only the last value in the sentence will be matched to the entity. In this
example, the entity `@payment_methods` only takes the value `cash`, since it is the last one
referenced in the sentence.
In general, it is **not** good practice to anticipate that an entity will have multiple values in a
user's sentence. If this is anticipated, you would need to create separate entities.
While you edit and try giving new names in Entities, you are allowed to use only alphanumeric or
underscore characters.
---
## Intents
**Intents** are specific purposes or goals that a user has in mind when interacting with a
conversational AI system. Intents represent the underlying intention behind a user's input. They can
include inquiries about store hours, product availability, sales, as well as frequently asked
questions, guidelines, procedures, and actions.
## Overview
To plan the scope of your AI agent, it's important to think about the types of questions you want it
to be able to answer. For instance, if you want your assistant to handle questions from users
wanting to track their order, you can create an intent called `#order_tracking`. The `#` prefix
helps distinguish the name as an intent.
Once you have identified the questions you want your assistant to address, it's time to start
creating the corresponding intents. Aim to have around 6-10 natural language examples for each
intent, some of which can also be [generated automatically](#auto-generation) if needed.
### Use case
Check out the following example:
> I'd like to **book a reservation** at the **Italian restaurant** on **Friday night**.
In this example, the user's intention is to book a reservation, so a possible
intent is `#book_a_reservation`. The place and the time are information that may differentiate the
AI agent's response, so you can handle cases like this by creating two
[entities](./entities.md), `@place` and `@time`.
## Create an intent
To create an intent, follow these steps:
1. Open your AI agent and select **Conversation**.
2. Click on **Intents**.
3. Press the **Create intent** button.
4. Rename your intent with a descriptive name by double-clicking on the intent name.
5. Add some natural language examples ([training phrases](#training-phrases)) that are related to
the intent you want to create.
## Training phrases
The number of training phrases needed for an intent to achieve the best results can vary depending
on the complexity of the intent and the natural language patterns of your users. However, a general
rule of thumb is to include around 6-10 training phrases for each intent you want your assistant to
recognize.
Having a sufficient number of diverse training phrases can help Moveo learn to accurately classify
the intent, even if the user inputs different phrasing or wording. However, it is also important to
ensure that the training phrases cover a broad range of variations to avoid overfitting the model to
specific examples.
It is also important to note that the quality of the training phrases is more important than the
quantity. Training phrases that accurately represent the natural language patterns of your users
will help the model achieve better results. Additionally, it is recommended to continuously monitor
the performance of the intent and adjust the training data as necessary to ensure optimal results.
### Auto-generation
Once you input your initial set of examples, Moveo will use them to suggest additional examples that
are relevant to your intent. You can then accept or reject these suggestions based on their
suitability. The following example illustrates this process: After entering the first two training
phrases, Moveo generates new phrases, and you can choose which ones to incorporate into your intent
by accepting them.
## Intent performance
When building intents for your AI agent, it is important to consider the intent performance. While
around 6-10 natural language examples per intent are considered optimal, you should maintain a
balance between the number of phrases and the overall performance. The performance bar on the right
sidebar can give you a good idea of how well your intent will perform, because it takes into
consideration the number of training phrases you have provided for the intent, as well as how they
compare to the other intents in the AI agent.
## Confidence Threshold
Adjust the confidence threshold of an AI Agent depending on your needs at any time. This
threshold accepts a value between 0 and 1, representing the minimum confidence level your AI
Agent should have to answer a question it is not exactly trained on.
For example, for a typo like "Helor there," your AI Agent should have a high level of confidence to
respond with the `#greetings` intent, assuming you have added an expression like "Hello there" to
this intent. Conversely, for a phrase like "ffdfdgd," the assistant should have a low level of
confidence in replying.
:::note
An AI Agent set at a 0.70 confidence threshold would respond to the "Helor there"
message and trigger the [unknown](./triggers/unknown.md) intent for the "ffdfdgd" message.
:::
The confidence threshold is located in the **Advanced** section of your AI Agent.
## Connect a flow
After you create your intent, you can immediately connect it to a new [dialog](./dialogs.md) by clicking
on **Connect**. Pick a name for your new dialog, as well as the folder you want to classify it.
Then, write the reply of the assistant, click **Create** and modify the dialog to your needs.
## Good and bad practices
| Do's :heavy_check_mark: | Don'ts :x: |
| :------------------------------------------------------------------------: | :--------------------------------------------------------------------------: |
| Do make sure the intent is specific enough. | Don't make the intent and its expressions too general or too vague. |
| Do ensure the intent has a clear purpose. | Don't create intents that overlap or are redundant. |
| Do use clear and concise language. | Don't use ambiguous language and **unclear** jargon. |
| Do try to maintain a balance in the number of training phrases per intent. | Don't add training phrases, in which the only variation is upper/lower case. |
| Do try to merge subsets of the same flow into one. | Don't use similar training phrases to different intents. |
### Create a specific and precise intent
To create a successful intent, it's important to make sure that it is specific enough to capture the
user's intention without being too general or vague. For example, if you want your AI agent to help
users check the status of their order, a good intent name might be `#check_order_status`. This name
is specific enough to accurately represent the user's intention, while also being clear and easy to
understand. On the other hand, an intent name like `#ask_about_orders` is too general and may not
accurately capture the user's intention. Similarly, when adding training phrases to your intent,
make sure they are specific and relevant to the intent's purpose, rather than being too broad or
ambiguous.
### Create clear and purposeful intents
When creating intents for your AI agent, it's important to ensure that each intent has a clear and
specific purpose. This will make it easier for the assistant to understand and respond to user
requests accurately. However, you should also avoid creating intents that overlap or are redundant,
as this can cause confusion for both the user and the assistant. For example, if you have an intent
called `#check_order_status`, you should not create a separate intent called `#view_order_details`
as these two intents are likely to have overlapping expressions.
### Use clear and concise language
Use simple and clear language for the training phrases of your intents. Avoid **ambiguous** jargon
and aim to familiarize the AI agent with your users' language.
- :heavy_check_mark: **Good examples**:
- When will my order arrive?
- How much does this product cost?
- :x: **Bad examples**:
- ETA of package
- What's the MSRP of this product?
### Use effective training phrases
You should aim to keep a consistent number of training phrases per intent, ideally 6-10. Having too
few or too many training phrases can lead to confusion or ambiguity for the AI agent. Avoid
duplicating training phrases that only vary in capitalization. For instance, instead of using
**Where is my order?** and **WHERE IS MY ORDER?** as separate training phrases, you can use a
different phrase conveying the same meaning, like **What is the status of my delivery?**. This
provides a more diverse range of inputs for the AI agent to recognize, resulting in a more accurate
and robust system.
### Merge different subflows into one
Consider combining similar thought processes into a single intent for better clarity. For example,
instead of treating **Pay with card**, **Pay with cash** and **Pay with a coupon** as separate
flows, it's strongly suggested to consolidate these cases into one flow, **Payment methods**.
Given that these cases share similarities and have overlapping training phrases, combining them can
help streamline the process and improve the confidence with which the assistant can answer a
question on this topic. Additionally, you can include the supported
**payment methods** as an [entity](./entities.md).
In this case, you should remove the intents handling the card, cash, and coupon cases, and move them
all into one intent called `#payment_methods`. This intent may include expressions such as:
- How can I pay?
- What are the available payment methods?
- In which ways may I pay off my account?
- Is it possible to pay with cash?
- Can I pay my account with my card?
- I want to use a coupon for the payment.
## Export and import intents
Export and import intents using CSV files. The process is the same for both operations:
### To import an intent:
1. Click on the import icon on the top right to select a local CSV file
2. The CSV file **must** have the following format:
- Two columns with headers `Intent` and `Expression`
- Optional: Under `Intent`, write the name of your imported intent
- Under `Expression`, write the expressions referring to the imported intent
3. Once you upload the file, save to add the intent to your AI agent
### To export an intent:
1. Click on the export icon on the top right to download the intent as a CSV file
2. The exported file will follow the same format as described above
3. You can then use this file to import the intent into another AI agent
Download an
[example intent](https://media.moveo.ai/media/accounts/65251a75-c3c5-4e51-86b9-21bc1905ae69/daaf9c9a-6c2b-46d0-ae41-ddcd22ff5623.csv) to see the correct format.
## Off-topic messages
Your AI agent, once trained, has knowledge about the topics you teach it. However, it also knows
when it doesn't know something. Moveo classifies all user messages into two groups: those that fit
within an existing intent that it knows, and those that fall under the `#offtopics` category, which
is a default category that cannot be deleted. You can also add specific phrases to this _system_
intent that you want your agent to recognize as off-topic messages.
:::tip
Do not connect an [intent trigger](./triggers/text.md) to the `#offtopics` intent, but rather
handle the cases where it is triggered with a [fallback](./triggers/unknown.md).
:::
---
## Knowledge & Guidelines
Knowledge and Guidelines work together to create intelligent, contextual AI agents. **Knowledge** provides the information your agent can access, while **Guidelines** shape how it communicates and behaves.
## [Knowledge base](../knowledge-base/overview.md)
A knowledge base is your agent's collection of information that it relies on to answer questions and provide support. When a user asks a question, the agent searches connected knowledge bases, retrieves the most relevant fragments, and uses this information along with guidelines to generate a response.
This RAG (Retrieval Augmented Generation) approach ensures accurate, grounded responses based on your actual content.
For setup instructions, see [Knowledge agent quick start](./quickstart.md).
## Guidelines
Guidelines are instructions that define your AI agent's personality, behavior, and response patterns.
### Personalization
The **Personalization** field links your agent's **first message webhook** — the webhook that runs once at the start of each conversation to fetch data about the user and inject it into the conversation context. Those context variables are what [dynamic personalization](#dynamic-personalization) reads (name, account type, tenure, and so on).
- Personalization always maps to the **first message** webhook, and an agent has at most one.
- If none exists yet, click **Create** to add one — it's linked here automatically.
- Other webhook types (pre message, post message, dialog, authentication) run at different points and aren't personalization webhooks. Manage them on the [Webhooks](./webhooks.md) page; they don't appear in this field.
### Writing effective guidelines
The quality of your guidelines directly impacts agent performance. Here's how to write guidelines that work:
#### 1. Be specific and clear
```md
When users ask about pricing, always mention:
1. Starting price is $29/month
2. 14-day free trial available
3. Annual billing saves 20%
4. Enterprise plans available for 50+ users
Format prices with currency symbol first (e.g., $29 not 29$).
```
```md
Tell users about our pricing when they ask.
```
#### 2. Handle objections strategically
```md
Price Objection Response Framework:
1. Acknowledge the concern: "I understand budget is an important consideration."
2. Highlight value: "Our customers typically save 10+ hours per week."
3. Reduce risk: "That's why we offer a 14-day free trial."
4. Provide options: "We also have a starter plan at $19/month."
Never dismiss price concerns or say "it's worth it" without explanation.
```
#### 3. Set clear boundaries
```md
Topics to avoid:
- Political opinions or commentary
- Medical or legal advice
- Competitor pricing without context
- Promises about future features not yet released
If asked about these topics, politely redirect:
"I'm focused on helping you with [your product/service]. For [topic],
I'd recommend consulting with a qualified [professional type]."
```
#### 4. Include examples
```md
When explaining our return policy:
User: "Can I return this after 30 days?"
Response: "Our standard return window is 30 days from purchase. If you're
slightly past that date, I can check if we can make an exception. May I
have your order number?"
Always offer to help even when the standard policy doesn't apply.
```
### Predefined fields by agent type
Each agent type has different predefined guideline fields optimized for its use case. Fill out the **Goal** field first to establish your agent's primary objective, then add supporting context in the other fields.
Customer Support agents use **Objections** and **Custom instructions** fields.
**Custom instructions:**
```md
Deliver clear and knowledgeable assistance in every interaction.
Always begin by acknowledging the customer's concern and showing understanding of their situation.
Guide them through solutions in a step-by-step manner, ensuring they feel supported throughout the process.
When possible, offer educational resources, FAQs, or tutorials that empower customers to solve issues independently in the future.
Turn challenges into positive experiences that strengthen trust and loyalty.
```
**Objections:**
```md
## I've already tried that and it didn't work
I'm sorry that didn't resolve your issue. Let me look into this more closely and find an alternative solution for you.
```
Early Engagement agents use **Goal**, **Overview**, **Features**, **Loyalty**, **Objections**, and **Custom instructions** fields.
**Goal:**
```md
Build meaningful relationships with potential customers by understanding their needs and guiding them toward the right solutions.
```
**Overview:**
```md
We help businesses connect with their customers through personalized engagement strategies, proactive outreach, and value-driven conversations.
```
**Features:**
```md
Personalized recommendations, needs assessment, product demonstrations, resource sharing, and relationship building through ongoing communication.
```
**Loyalty:**
```md
Engaged customers become brand advocates who return for repeat purchases and recommend our products to others.
```
**Objections:**
```md
## I'm just browsing for now
That's perfectly fine! Is there anything specific you're looking for that I can help point you in the right direction?
```
**Custom instructions:**
```md
Focus on creating a welcoming and engaging first impression to build trust early in the conversation.
Take the initiative to understand the customer's needs, goals, or challenges by asking open-ended questions.
Offer relevant information, product insights, and helpful resources before the customer makes a decision.
Avoid being pushy — instead, aim to guide the customer to establish a long-term relationship.
```
Product Adoption agents use **Goal**, **Overview**, **Features**, **Loyalty**, **Objections**, and **Custom instructions** fields.
**Goal:**
```md
Guide customers through a seamless onboarding experience that helps them start using the product effectively and confidently.
```
**Overview:**
```md
Our product helps customers get started quickly with intuitive setup wizards, guided tutorials, and personalized onboarding paths tailored to their needs.
```
**Features:**
```md
Interactive tutorials, progress tracking, milestone celebrations, personalized tips, quick-start guides, and in-app help resources.
```
**Loyalty:**
```md
Customers who complete onboarding successfully are more likely to become long-term, engaged users who advocate for our product.
```
**Objections:**
```md
## I don't have time right now
The setup only takes a few minutes, and you can pause and resume anytime. Would you like me to highlight the essential steps first?
```
**Custom instructions:**
```md
Guide customers through a seamless onboarding experience that helps them start using the product effectively and confidently.
Provide clear, easy-to-follow steps that highlight key features and benefits.
Anticipate common challenges during setup and proactively offer guidance to prevent frustration.
Encourage engagement by celebrating milestones and progress.
Share actionable tips, best practices, and real-world examples that help customers quickly realize the value of the product and become long-term, confident users.
```
Upsell agents use **Goal**, **Overview**, **Features**, **Loyalty**, **Objections**, and **Custom instructions** fields.
**Goal:**
```md
Help customers discover premium features and upgrades that can enhance their experience and deliver additional value.
```
**Overview:**
```md
We offer tiered solutions that scale with customer needs, from essential features to comprehensive enterprise packages.
```
**Features:**
```md
Advanced analytics, priority support, extended storage, premium integrations, dedicated account management, and custom solutions.
```
**Loyalty:**
```md
Customers who upgrade often experience greater success with our product and become our most loyal, long-term partners.
```
**Objections:**
```md
## I'm happy with what I have
That's great to hear! Just so you know, when you're ready to scale or need additional features, our premium options are designed to grow with you.
```
**Custom instructions:**
```md
Actively look for moments when an upgrade or additional feature could genuinely improve the user's experience or results.
Understand their current usage, needs, and priorities before suggesting an upsell.
Highlight how higher-tier options deliver extra value, convenience, or capabilities that directly support their goals.
Focus on helping the customer see the benefits rather than pushing for a sale.
Always present upgrades as opportunities for growth, efficiency, or enhanced satisfaction.
```
Debt Collection agents use **Goal**, **Objections**, and **Custom instructions** fields.
**Goal:**
```md
Encourage the user to initiate payment for delinquent amounts by highlighting the potential benefits of resolving their debt promptly.
```
**Objections:**
```md
## I can't afford to pay right now
I understand finances can be tight. We have flexible payment plans that can work with your budget. Would you like me to walk you through your options?
```
**Custom instructions:**
```md
Approach every interaction with respect and professionalism.
Acknowledge the customer's situation and express a willingness to help them find the best solution.
Offer flexible repayment or settlement options when possible and explain terms, deadlines, and available assistance clearly.
Emphasize collaboration and reassurance — the goal is to resolve the debt smoothly while preserving a positive customer relationship and encouraging future engagement.
Divide the conversation into clear, simple steps:
1. Explain the reason for the conversation.
2. Present the available payment options and highlight any available discounts.
3. Present the installment payment option.
```
### Adding custom guidelines
In addition to the predefined fields, you can add custom guidelines for specific topics or scenarios. Each custom guideline has a title and body.
**To add a custom guideline:**
1. Navigate to your AI Agent's **Knowledge** tab
2. Click **Add guideline**
3. Enter a descriptive title (e.g., "Return Policy", "Pricing Questions")
4. Write the guideline content in the body
### Advanced guideline techniques
#### Dynamic personalization
Use context variables to personalize responses:
```md
If the user's account type is "Premium":
- Mention premium-only features
- Provide priority support language
- Reference their dedicated account manager
If the user is a new customer (account age < 30 days):
- Be extra helpful and patient
- Proactively offer onboarding resources
- Check in on their progress
```
#### Conditional responses
Create branching logic in your guidelines:
```md
For technical questions:
- If basic user: Provide simple, non-technical explanation
- If power user: Include advanced options and shortcuts
- If developer: Reference API docs and code examples
Identify user type by their question complexity and terminology used.
```
#### Multi-language considerations
```md
When responding in languages other than English:
- Maintain the same tone and professionalism
- Use formal address unless the culture prefers informal
- Be aware of cultural sensitivities
- Localize examples (currency, dates, measurements)
```
#### Channel-specific guidelines
Channel-specific guidelines let you customize how your AI agent responds on different communication channels. Each channel has unique characteristics — a voice call requires concise, spoken-friendly responses while an email can include detailed formatting and attachments.
The Guidelines page has two tabs:
- **Guidelines** — Your default guidelines that apply across all channels (Goal, Overview, Objections, Custom instructions, etc.)
- **Channel-specific** — Per-channel overrides for **Voice**, **Email**, and **Chat**
Channel-specific instructions are layered on top of your default guidelines during response generation. If a channel has specific guidelines, those instructions are included alongside the defaults to shape how the agent responds on that channel.
The available channels are **Voice**, **Email**, and **Chat**.
**To configure channel-specific guidelines:**
1. Navigate to your AI Agent's **Guidelines** page
2. Select the **Channel-specific** tab
3. Write guidelines for each channel (Voice, Email, Chat)
4. Click **Save**
:::tip
Channel-specific guidelines count toward your total guideline character limit. Keep an eye on the character counter when writing guidelines across multiple channels.
:::
### Testing and iterating guidelines
Your guidelines should evolve based on real interactions:
1. **Start simple** - Begin with core guidelines and add complexity gradually
2. **Monitor conversations** - Review actual interactions to identify gaps
3. **A/B test variations** - Try different guideline approaches
4. **Gather feedback** - Ask users if responses were helpful
5. **Update regularly** - Refine based on new products, policies, or learnings
:::tip Pro tip
Use the Insights feature to get AI-powered suggestions for improving your guidelines based on actual conversation patterns.
:::
### Common guideline mistakes to avoid
| Mistake | Why it's problematic | Better approach |
| ------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| Too vague | "Be helpful" doesn't guide specific behavior | "When users ask for help, first clarify their specific need, then provide step-by-step guidance" |
| Contradictory rules | Confuses the agent and creates inconsistent responses | Review all guidelines together to ensure alignment |
| Over-scripting | Makes responses robotic and inflexible | Provide frameworks and principles, not word-for-word scripts |
| Ignoring edge cases | Agent struggles with unusual requests | Include "If unsure..." fallback instructions |
| No personality | Creates generic, unmemorable interactions | Define specific tone, style, and even catchphrases |
### Combining knowledge and guidelines
The magic happens when knowledge and guidelines work together:
**Example scenario:** User asks "How do I reset my password?"
1. **Knowledge provides:** The actual reset process from your documentation
2. **Guidelines shape:** How to present this information (tone, detail level, additional offers)
**Result:** A response that's both accurate (from knowledge) and on-brand (from guidelines).
### Best practices summary
✅ **Do:**
- Write guidelines as if training a new team member
- Use specific examples and scenarios
- Update guidelines based on real conversations
- Test different approaches and measure results
- Keep guidelines organized and non-conflicting
❌ **Don't:**
- Write vague or generic instructions
- Create overly rigid scripts
- Ignore cultural and language considerations
- Forget to handle edge cases
- Neglect regular updates and improvements
## Next steps
- [Knowledge base overview](../knowledge-base/overview.md) - Create and manage your content
- [Setup](./setup.md) - Configure tone, response length, and reminders
- [Test your agent](./test.md) - Validate responses before deployment
- [Analytics](../analytics/overview.md) - Monitor agent performance
---
## Local tools
Local tools are built-in tools provided by Moveo that your AI agent can invoke directly from guidelines. They let the agent trigger workflows, compose rich responses, execute code, detect voicemails, and search the knowledge base on demand — without requiring external server configuration.
:::note
Local tools are different from [MCP servers](./mcp-servers). MCP servers connect to external tool providers, while local tools are internal to Moveo and ready to use out of the box.
:::
## Available tools
| Tool | Description | Channel support |
|------|-------------|-----------------|
| **Trigger workflow** | Hands off the conversation to a specific workflow. The workflow takes over the response — the AI agent does not respond separately. | All channels |
| **Compose rich response** | Lets the AI agent compose structured responses with buttons, carousels, images, and files. | Chat, web widget, and messaging channels only. Not available on voice, email, or SMS. |
| **Execute code** | Lets the AI agent run code for math calculations and complex operations. | All channels |
| **Voicemail detection** | Detects voicemail systems and optionally leaves a message. | Voice channels only |
| **On-demand knowledge retrieval** | Lets the AI agent fetch relevant information from the knowledge base on demand. | All channels |
## Enable or disable a tool
Navigate to your AI agent → **Workflows** → **MCP servers**, then select the **Local tools** tab.
Each tool has a toggle switch. Activate a toggle to make that tool available to the AI agent.
:::warning
Disabling a tool that is referenced in your guidelines removes all its references automatically. Review your guidelines after disabling a tool that was central to the agent's behavior.
:::
When you disable a tool that is already referenced in guidelines, a warning dialog appears:
- The dialog explains that all tool references will be removed from guidelines
- Select **View guideline** to review the affected guidelines before confirming
- Select **Disable** to proceed, or **Cancel** to keep the tool enabled
## Reference a tool in guidelines
You can reference local tools in any guideline editor — Goal, Overview, Features, Loyalty, Objections, or Custom Instructions.
### Insert a tool reference
1. Open a guideline editor
2. Type `@` to open the suggestion menu
3. Select a tool from the list
The tool appears as an inline badge in the editor (for example, `@compose_rich_response`, `@execute_code`, or `@search_knowledge_base`).
### Insert a trigger workflow reference
The **Trigger workflow** tool requires you to select a specific workflow:
1. Type `@` and select **Trigger workflow**
2. A workflow picker opens automatically
3. Select the target workflow from the list
The badge displays as `@trigger_workflow(workflow name)`, where the workflow name updates automatically if you rename the workflow.
:::tip
If the `@` menu is empty, no tools are enabled. Select the link in the empty state prompt to go to the Local tools settings and enable them.
:::
## Runtime behavior
When the AI agent encounters a tool reference in guidelines during a conversation, it invokes the tool automatically.
### Trigger workflow
The conversation hands off to the selected workflow. The workflow owns the response from that point — the AI agent does not receive a result back and does not respond separately.
### Compose rich response
The AI agent composes a structured response with elements like text with buttons, carousels, images, or files. The response is sent directly to the user.
:::caution
This tool only works on channels that support rich payloads (chat, web widget, messaging). Enabling it has no effect on voice, email, or SMS channels.
:::
### Execute code
The AI agent runs code to perform complex operations such as math calculations. The result is used in the agent's response.
### Voicemail detection
The AI agent detects whether a voicemail system has answered and can optionally leave a message.
:::caution
This tool only works on voice channels. Enabling it has no effect on other channels.
:::
### On-demand knowledge retrieval
The AI agent can search the knowledge base for additional information during the conversation. The default knowledge base retrieval still happens automatically at the start of each turn, but when the prefetched results are not enough to answer the user's question, the agent can fetch extra information on demand.
## Delete a workflow referenced in guidelines
When you delete a workflow that is referenced by `@trigger_workflow` in guidelines, a warning appears:
- The dialog explains that the tool reference will be removed from guidelines
- Select **View guideline** to review the affected guidelines
- On confirmation, all `@trigger_workflow` references pointing to that workflow are removed automatically
## Troubleshooting
The @ menu shows no tools
No local tools are enabled. Go to your AI agent → **Workflows** → **MCP servers** → **Local tools** tab and enable the tools you need.
Tool references disappeared from guidelines
Tool references are removed automatically when you disable a tool or delete a workflow that the tool points to. Re-enable the tool and re-insert the references.
Compose rich response has no effect
This tool only works on channels that support rich payloads (chat, web widget, messaging). It has no effect on voice, email, or SMS channels.
Voicemail detection has no effect
This tool only works on voice channels. It has no effect on chat, web, email, SMS, or messaging channels.
---
## Next steps
- [MCP servers](./mcp-servers) — connect external tools via the Model Context Protocol
- [Workflows](./dialogs) — build conversation workflows that tools can trigger
---
## MCP servers
MCP servers extend your AI agent with external tools through the Model Context Protocol (MCP). Once connected, the agent can use the server's tools during conversations to query databases, call APIs, or interact with third-party services — without you having to write any custom integration code.
:::note
MCP servers connect external tool providers. For tools built into Moveo (workflow triggers, rich responses, code execution, voicemail detection, on-demand knowledge), see [Local tools](./local-tools). To build your own MCP server — including tool design and prompting practices — see [Build an MCP server](./build-an-mcp-server).
:::
## Overview
An MCP server exposes a set of tools over the Model Context Protocol. After you connect a server, Moveo discovers the tools it offers, you choose which ones to enable, and the agent can call them while talking to a user.
### Authentication modes
Moveo automatically detects the authentication mode of the server you connect.
| Mode | When it applies | What you provide |
|------|-----------------|------------------|
| **None** | Server is publicly accessible | Just the URL |
| **Header** | Server expects credentials in HTTP headers (for example, an API key) | Header key and value pairs |
| **OAuth** | Server uses OAuth 2.0 with PKCE | Connect via popup; client credentials registered automatically when the server supports RFC 7591, otherwise entered manually |
If you are building the server yourself, see [Authentication](./build-an-mcp-server#authentication) for how to implement each mode.
### Transport
Moveo connects over **Streamable HTTP**. The legacy SSE transport is deprecated and rejected at the URL-validation step. For the route setup on the server side, see [Create the route](./build-an-mcp-server#create-the-route).
## Prerequisites
Before adding an MCP server, ensure you have:
- An MCP server endpoint URL that supports Streamable HTTP
- Credentials for the server's authentication mode (if any)
## Add an MCP server
Navigate to your AI agent → **Workflows** → **MCP servers**, then select **Add MCP server**.
{/* TODO: Replace static images in this section with a single Arcade walkthrough showing URL entry → discovery → authentication → tool selection → save. */}
To connect a server:
1. Enter the server URL.
2. Authenticate using the mode Moveo detects.
3. Select which tools the agent can use.
### Enter the server URL
Enter your MCP server URL. When you tab out of the field, Moveo contacts the server, detects the authentication mode, and shows a status indicator next to the URL.
:::warning
SSE transport is deprecated. If your URL ends with `/sse`, remove that suffix and use the base endpoint instead.
:::
### Authenticate
The next step depends on the authentication mode Moveo discovered.
#### No authentication
If the server is public, Moveo confirms the connection automatically and moves on to tool selection. No further input is needed.
{/* TODO: Arcade — show a discovery completing on a public MCP server with the green checkmark and immediate tool list reveal. */}
#### Header authentication
For servers that expect credentials in HTTP headers (for example, an API key passed as `Authorization: Bearer ` or `X-Api-Key: `):
1. Enter a name for the server.
2. In the **Custom headers** section, add one or more header key/value pairs.
3. Use the eye toggle to mask or reveal a value.
4. Select **Connect**. Moveo calls the server with your headers to verify access and retrieve the tool list.
:::tip
Header values are stored as secrets. Anyone with edit permission can update them, but they are masked by default in the UI.
:::
{/* TODO: Arcade — show the header rows being added, eye toggle masking the value, then a successful Connect that reveals tools. */}
For how to validate the header on the server side, see [Header authentication](./build-an-mcp-server#header-authentication) in the implementation guide.
#### OAuth authentication
For OAuth-protected servers:
1. Enter a name for the server.
2. If the server supports **dynamic client registration (RFC 7591)**, Moveo registers a client automatically and shows a confirmation. Otherwise, enter the **client ID** and **client secret** issued by the authorization server. The **authorization URL** and **token URL** are filled in from server discovery, but you can override them.
3. Select **Connect** to start the OAuth flow.
4. A popup opens to the authorization server. Sign in and authorize Moveo.
5. The popup closes automatically on success and Moveo retrieves the tool list.
{/* TODO: Arcade — show the OAuth flow end-to-end: dynamic registration confirmation, Connect button, popup auth, return with tools loaded. */}
:::note
Moveo uses PKCE (RFC 7636) for every OAuth flow. The callback URL shown in the panel is the redirect URI to whitelist on your authorization server when dynamic registration is not available.
:::
For the server side — JWKS verification, the OAuth Resource Metadata endpoint, and refresh tokens — see [OAuth](./build-an-mcp-server#oauth) in the implementation guide.
### Select tools
After authentication succeeds, Moveo lists every tool the server exposes. All tools are selected by default.
1. Use **Select all** to enable all tools, or **Select none** to clear selections.
2. Hover over a tool to see its description.
3. Select **Add** to save the server with the chosen tools enabled.
The tool names and descriptions you see here are set by the server. For guidance on writing them so the agent uses the tools correctly, see [Tool design](./build-an-mcp-server#tool-design).
---
## Manage MCP servers
The MCP servers table lists every configured server with its current status.
### Table columns
| Column | Description |
|--------|-------------|
| **Name** | Server name and number of enabled tools |
| **URL** | Server endpoint |
| **Created by** | User who created the server |
| **Last used** | When the server was last called |
| **Status** | Connection and sync status |
| **Enable** | Toggle to activate or deactivate the server |
| **Actions** | Edit, resync, or delete |
### Status indicators
| Status | Meaning |
|--------|---------|
| **Verified** | Connected; tools and authentication are in sync |
| **Outdated** | Tool definitions changed on the server and need to be resynced |
| **Error** | Moveo cannot reach the server with the current credentials |
### Edit a server
Select a row in the table or choose **Edit** from the actions menu to modify a server.
{/* TODO: Arcade — show opening the edit panel, renaming, toggling individual tools, then Update. */}
The edit panel lets you:
- **Rename** the server.
- **View the URL** (read-only, with a copy button). The URL cannot be changed after creation; delete the server and create a new one to point at a different endpoint.
- **Update custom headers** — only when the server uses [header authentication](./build-an-mcp-server#header-authentication).
- **Toggle individual tools** on or off. Hover over a tool to see its description and last-used time. Tool descriptions are set on the server side — see [Tool descriptions](./build-an-mcp-server#tool-descriptions).
When you open the edit panel, Moveo refetches the latest tools from the server. Tools added on the server side appear here so you can enable them.
:::warning
If the server status is **Outdated**, you must resync before saving. The **Update** button stays disabled until the resync completes.
:::
Select **Update** to save changes.
### Resync tools
When an MCP server changes its tool definitions, the server status switches to **Outdated**. Resync brings your local tool definitions back in line with the server.
1. Select **Resync** from the actions menu or from the edit panel.
2. The dialog shows a diff:
- **Updated** — the tool's description or input schema changed.
- **Deleted** — the tool no longer exists on the server.
3. Select **Resync** to apply the changes.
{/* TODO: Arcade — show the Outdated badge, opening Resync, the diff dialog, and the badge flipping to Verified. */}
:::note
Resync only updates or removes existing tools. **New tools added on the server do not appear in the resync dialog.** To enable a newly added tool, open the edit panel — the tool list there is always refetched live.
:::
For guidance on evolving tools without breaking guidelines that reference them, see [Version tool definitions deliberately](./build-an-mcp-server#version-tool-definitions-deliberately).
### Enable or disable a server
Use the toggle in the **Enable** column to activate or deactivate an MCP server. A disabled server stays configured, but the agent cannot call any of its tools.
### Delete a server
From the actions menu, select **Delete** to remove a server. This action cannot be undone, and any guideline that referenced the server's tools loses those references. For how guidelines reference tools, see [Referencing tools from guidelines](./build-an-mcp-server#referencing-tools-from-guidelines).
---
## Runtime behavior
Once a server is verified and enabled, Moveo invokes its tools during conversations the same way it invokes local tools. A few details are worth knowing as a server author or operator.
### Connection and discovery
- Connection establishment, tool discovery, and the connection test that runs when you add or edit a server are bound by a **30-second timeout**. A server that does not complete the MCP handshake in that window is reported as unreachable. To stay inside this window, see [Respect the connection budget](./build-an-mcp-server#respect-the-connection-budget).
- Moveo negotiates **Streamable HTTP** first and falls back to SSE only when the server returns 404 or 405 on the Streamable HTTP endpoint. New servers should set `disableSse: true` — see [Create the route](./build-an-mcp-server#create-the-route).
### Tool invocation
Tools are invoked at conversation time. Moveo bounds each invocation by a timeout and surfaces the result back to the agent for it to incorporate into its reply.
- **Connect timeout** — 3 seconds to establish the HTTP connection.
- **Read timeout** — 65 seconds for the server to return the tool result. To stay inside this budget, see [Implement timeouts on the server side](./build-an-mcp-server#implement-timeouts-on-the-server-side).
- **Retries** — Connection-level failures and the HTTP statuses 5xx and 429 are retried once by default with exponential backoff (up to 10 seconds). Tool errors returned with `isError: true` are **not** retried — they are passed back to the agent as a deliberate signal it can act on. To make retries safe, see [Make tool calls idempotent](./build-an-mcp-server#make-tool-calls-idempotent).
- **Tool definition cache** — Discovered tool schemas are cached for 2 minutes. After a resync in the UI, expect a brief window before every running conversation sees the updated schemas. Plan schema changes accordingly — see [Version tool definitions deliberately](./build-an-mcp-server#version-tool-definitions-deliberately).
- **Argument validation** — Moveo validates each tool call against the tool's input schema before sending it to the server. Invalid arguments are returned to the agent as a structured error for self-correction; your server is not contacted in that case. Schemas with clear field descriptions and enums get fewer invalid calls — see [Input schemas](./build-an-mcp-server#input-schemas).
### Error codes
When a connection or tool call fails, Moveo records one of the following error codes:
| Code | Meaning |
|------|---------|
| `connection_timeout` | Server did not respond within the timeout window |
| `unauthorized` | Server returned HTTP 401 — credentials are missing, invalid, or expired |
| `not_found` | Server returned HTTP 404 |
| `connection_refused` | TCP connection was refused (server not listening) |
| `http_` | Other HTTP status returned by the server |
| `connection_failed` | Catch-all for other transport failures |
---
## Troubleshooting
SSE endpoint error
The SSE transport is deprecated. If your server URL ends with `/sse`, remove that suffix and use the base endpoint:
- **Wrong:** `https://example.com/mcp/sse`
- **Correct:** `https://example.com/mcp`
Discovery times out
Moveo waits up to 30 seconds for the server to complete the MCP handshake. If discovery times out:
1. Confirm the server is reachable from the public internet.
2. Make sure the server completes its initial handshake quickly — defer any cold-start work until the first tool call. See [Respect the connection budget](./build-an-mcp-server#respect-the-connection-budget).
3. Check that the URL points at the Streamable HTTP endpoint, not a marketing or documentation page.
OAuth connection fails
If OAuth authorization fails:
1. Verify the server supports OAuth and is properly configured. See [OAuth](./build-an-mcp-server#oauth) for the server-side setup.
2. If dynamic client registration fails, enter client credentials manually.
3. Make sure your authorization server allows the Moveo redirect URI shown in the panel.
4. Confirm the scopes the server requires are available on the access token.
Header authentication fails
If a header-authenticated server returns **Error** after Connect:
1. Check the header names exactly. Common patterns: `Authorization: Bearer `, `X-Api-Key: `. See [Header authentication](./build-an-mcp-server#header-authentication) for server-side validation.
2. Confirm the credential is valid and has not been rotated.
3. Reopen the edit panel and re-enter the value — masked values are not visible after save.
Tools not appearing after resync
Resync only updates or removes existing tools. New tools added on the server do not appear in the resync dialog. Open the edit panel and select the new tools from the live tool list.
Server shows "Error" status
The server cannot be contacted. Verify:
1. The server is running and accepting connections.
2. Any required authentication credentials are still valid.
3. The endpoint did not move to a new URL.
If the issue persists, delete the server and add it again.
---
## Next steps
- [Build an MCP server](./build-an-mcp-server) — implementation, tool design, and operating practices
- [Local tools](./local-tools) — built-in tools your agent can use without an external server
- [Dialog Webhooks](./action-webhooks) — trigger custom logic during conversations
- [Webhooks](./webhooks) — overview of all webhook types and how to configure them
---
## Message path
'@site/src/components/Img';
To better understand how a message travels through Moveo to generate a reply, it's important to
explore the full path it follows across the system. Each stage in this process plays a critical role
in ensuring the conversation is handled accurately and efficiently. From the moment a user reaches
out via an [integration](../integrations/overview.md), to the [rules](../environments/rules.md) that determine the
next steps, and finally to the [AI Agent](./overview.md) that processes and replies to the
message,each component contributes to a smooth and intelligent conversational experience.
## Sending a message
A conversation typically begins when a user reaches out via an **integration**. In other words, the
user initiates the conversation.
The channel used by the user depends on the channels configured in your account. This same channel
will be used to send the reply after the message is processed by the system.
When a user sends a message, they are contacting an **integration** associated with a specific
[**environment**](../environments/overview.md). This **integration** is responsible for receiving the message,
processing it through the system, and sending a reply back to the user.
## Rules
Once the message is received by the environment's **integration**, it is evaluated by the set of
[**rules**](../environments/rules.md) configured in that environment.
At this stage, the system checks which **actions** should be taken based on the
[**conditions**](../environments/rules.md#apply-the-condition) defined in the rules. For example, one possible
action is assigning an **AI Agent** to the conversation. Other available actions can be found
[**here**](../environments/rules.md#then).
The most common actions related to message handling are:
- Assigning an [**AI Agent**](./overview.md).
- Assigning a [**department**](../chat/departments.md).
:::note
A **human agent** can manually take over a conversation at any time, regardless of whether
an **AI Agent** or **department** has been assigned.
:::
It's possible to have multiple **rules** that assign an **AI Agent**. In such cases, the system will
assign the **first AI Agent whose rule matches**.
Assigning a **department** works differently. Unlike **AI Agent** assignment, **departments can be
assigned even when an AI Agent is already handling the conversation**. A **human agent** will be
assigned to the conversation if:
- The **AI Agent** triggers a [**handover**](./operations/handover.md) to a **human
agent**.
- No matching **rule** assigns an **AI Agent**.
## AI Agent reply
Once the message reaches the **AI Agent**, the system begins processing it through the following
steps:
1. **Standalone**: A specialized **NLP model** enhances the original message by generating a
standalone version. This version includes contextual information to clarify the user's intent.
2. **Intent**: After the standalone message is created, the system searches the configured
[**intents**](./intents.md) and selects the one with the highest confidence. It then
triggers the corresponding [**dialog**](./dialogs.md). If the system is not confident
enough, the message is passed to the **response synthesizer**.
3. **Response synthesizer**: This model generates a reply based on the user's message and
**conversation history**.
## Conversation start
By default, the first user message goes through the same path as any other. If a node is selected under [Conversation start](./setup.md#conversation-start) in the AI Agent's settings, the first turn skips intent classification entirely: the conversation always begins at that node, regardless of what the first message says, and the greetings intent does not fire.
## Authentication
[Authentication](../authentication/authentication-overview.md) is a subagent action placed inside a dialog node. When the conversation reaches that node, the **Authentication Agent** — an LLM-powered subagent — takes over the message path: each user message goes to it instead of intent classification until the flow ends. Once the user passes (or fails), the conversation continues from the configured success or failure node.
When the node holding the Authentication action is also the [conversation start node](./setup.md#conversation-start) — the most common setup — the Authentication Agent owns the session from the first turn and generates the first message itself.
---
## Model strategy
A **model strategy** defines which language models power your AI Agent. You build a **default**
ordered chain of model steps, and you can optionally override it for individual channels. The AI
Agent tries each step in the chain in order and falls back to the next one if a step is unavailable,
so a single misconfigured or temporarily unreachable model never takes the agent offline.
You configure the model strategy from your AI Agent's **Advanced** page, where it replaces the
single language model selector.
## How the fallback chain works
A chain is an ordered list of models that run in order — if one fails, the next takes over. When the
AI Agent generates a response, it works through the chain from top to bottom:
1. It starts with the first model in the chain.
2. If that model is unavailable, it moves on to the next one.
3. It keeps going until a model succeeds.
The first model is your primary choice, and the models below it act as **fallbacks**. Reorder them
at any time to change which model the agent reaches for first.
## Model types
When you add a model, the picker groups the available options into three types. You can mix
different types across the models in the same chain.
- **Moveo-built (free)** — Maestro, Moveo's own built-in model. This is the default option and
carries no extra model cost.
- **Moveo-hosted (paid)** — Third-party models hosted by Moveo (for example, a `gpt` model). Choose
one of these when you want a specific model without managing your own provider credentials.
- **Your language models** — Models from providers you have connected to your account (BYOLLM). To
make your own models available here, connect them first by following the
[Language Models](../platform/language-models.md) guide.
Each step uses either a Moveo model or one of your own language models — not both.
## Default chain and per-channel overrides
Your **default** chain applies to every channel. On top of it, you can configure overrides for
specific channels when you want different models depending on where the conversation happens:
- **Chat**
- **Email**
- **Voice**
A channel without an override **inherits the default** chain. When you start overriding a channel,
it is seeded from the current default so you can adjust from there, and you can **reset** a channel
at any time to go back to inheriting the default.
- A chain can have up to **3 models** (a primary model plus fallbacks).
- **Voice supports a single model only** — it does not use fallbacks, because voice interactions are
latency-sensitive. When Voice inherits the default, it uses only the default's first model.
:::tip
Use higher-quality models on channels where response quality matters most, and faster models on
latency-sensitive channels such as Voice.
:::
## Reasoning effort
Some models support a **reasoning effort** setting that controls how much the model deliberates
before answering. Where a model supports it, you can set the reasoning effort per model — **None**,
**Low**, **Medium**, or **High** — letting you balance response quality against speed and cost. If a
model doesn't support reasoning, the setting is shown as unavailable.
:::caution
High reasoning effort on Voice typically pushes response latency past four seconds. For voice, prefer
**Medium** or **Low**.
:::
## Edit the chain
You can adjust a chain at any time:
- **Add a fallback** and choose its model.
- **Change** a model or its reasoning effort.
- **Remove** a model you no longer need.
- **Reorder** the fallbacks by dragging them — the new order takes effect immediately.
## Test a model
Before committing a model to your chain, you can try it out. In the **Test AI Agent** panel, open
the **Model** tab and choose a specific model and reasoning effort for the conversation. This
overrides the configured chain for that test conversation only, so you can compare how different
models respond without changing your live configuration. Use **Clear override** to go back to the
configured chain.
## Empty and unavailable states
- **Cleared models** — If you clear the models, all channels fall back to the default Maestro model.
- **Unavailable model** — If a model in a chain has been deleted or is otherwise unavailable, it is
marked as unavailable and the AI Agent skips it and continues to the next one. Review the chain and
replace the affected model to restore your intended configuration.
---
## Conditions
This document explains how conditions work within the [dialog](../dialogs.md) system. Conditions
determine which actions to execute based on the current context, user input, and conversation
history. The system supports two types of conditions: rule-based conditions using context variables
and tags, and guideline-based conditions evaluated by AI models.
## Overview
Conditions in the dialog system determine which actions to execute based on the
**[current context](../context.md)**, **user input**, and **conversation history**. The system
supports two types of conditions:
- **Rule-based conditions**: Evaluated using deterministic logic with
[context variables](../context.md#types-of-context-variables) and entities
- **Guideline-based conditions**: Evaluated using AI models to understand natural language
guidelines
## Condition evaluation flow
When a [node](../dialogs.md#add-a-trigger) has conditions, the system evaluates them in the
following order:
1. **Conditions are evaluated from left-to-right** in their original order as defined in the JSON
2. **"Else" conditions are automatically moved to the end** regardless of their position
3. **Only the first matching condition** (in left-to-right order) is selected and executed
4. **All other matching conditions are ignored** - only one condition's actions are executed
## Rule-based conditions
Rule-based conditions use deterministic logic to evaluate context variables, entities, and user
input. They are suitable for precise matching scenarios and support three match strategies:
- **`all`** - All rules must be true for the condition to match
- **`any`** - At least one rule must be true for the condition to match
- **`else`** - Always matches when no other conditions match (fallback)
### Supported operators
| Operator | Description | Example |
| ------------------ | --------------------------------- | -------------------------------- |
| `equal` | Exact value match | `$user.name == "John"` |
| `not_equal` | Value does not match | `$user.verified != false` |
| `greater` | Numeric greater than | `$seats > 2` |
| `less` | Numeric less than | `$amount < 1000` |
| `greater_or_equal` | Numeric greater than or equal | `$seats >= 1` |
| `less_or_equal` | Numeric less than or equal | `$amount <= 500` |
| `contain` | String contains substring | `$user.email contains "gmail"` |
| `not_contain` | String does not contain substring | `$user.email not_contain "spam"` |
| `exist` | Variable/entity exists | `$user.phone exists` |
| `not_exist` | Variable/entity does not exist | `$payment_method not_exist` |
### Context variables
Context variables are referenced using the $ prefix:
### Entity references
Conditions with entities will match if the user input contains a matching entity. This can be either
in the input that triggered the intent node, or if there is a question in a previous step of the
same dialog that validates the entity.
From user input are referenced using the `@` prefix.
## Guideline-based conditions
Guideline-based conditions use AI models to evaluate natural language guidelines against the
conversation context. They are flexible and can understand complex scenarios that are difficult to
express with rigid rules.
The **Condition Evaluator** is an AI model that:
- Analyzes the dialog history, context variables, and user input
- Returns matching conditions based on natural language understanding
### Used data
The Condition Evaluator sends the following to the AI model:
- **Context Variables**: All relevant context data (user info, session data, etc.)
- **Live Instructions**: Special variables to dynamically change the AI Agent's behavior
- **Dialog History**: Recent conversation turns
- **User Question**: The current user input
- **Guideline Conditions**: All available conditions as multiple choice options
## Mixed conditions
Nodes can contain both rule-based and guideline-based conditions. The system evaluates them
separately and combines the results.
### Use case: Loan request – Rule vs guideline conditions
This example shows how to combine rule-based and guideline-based conditions to handle a user
requesting a loan.
1. A **rule-based condition** checks if the variable `$loan_status` is equal to `"unpaid"`. If true,
it blocks the loan request and shows a message asking the user to settle their debt first.
2. If the rule-based condition does not match, a **guideline-based condition** is evaluated next. It
uses an AI model to detect if the user expresses willingness to repay the loan (e.g., "I can pay
monthly"). If matched, the system allows the user to proceed.
3. If neither condition matches, an **else condition** acts as a fallback. It's used when the user
doesn't show a clear intent to repay, and blocks the request.
## Condition priority
The system will evaluate the conditions and execute the actions for the first condition that
matches. When multiple conditions match:
- **Left-to-right ordering** - Conditions are evaluated in the order they appear
- **First match wins** - The first matching condition is executed
## Best practices
### Rule-based conditions
- Use for precise, deterministic logic
- Use `exist`/`not_exist` for optional data
- Template values with `{{$variable}}` for dynamic comparisons
### Guideline-based conditions
- Use for complex, nuanced scenarios
- Write clear, specific guidelines
- Avoid ambiguous language
- Test with various conversation scenarios
### General
- Always include an `else` condition as fallback
- Order conditions by priority (most specific first)
- Monitor condition evaluation performance and accuracy
---
## Jump to
Events are a core function of Moveo. Unlike the classic tree-branch format, Moveo uses small
tree-like dialogs and flows. This approach allows you to reuse any of your dialogs and trace back to
an event trigger without having to build or write them again.
**Jump** actions enable you to jump into different dialogs and serve as shortcuts to other points in
the dialog.
## Use of a Jump action
| Jump action | Event trigger |
| :-----------------------------------------------------------: | :---------------------------------------------------------: |
| | |
In the above example, the jump action (left) triggers the dialog that has an event trigger as its
parent node (right).
---
## Handover
Moveo allows you to transfer the conversation to a live agent when necessary. This can be useful if
the AI Agent does not understand the user's questions or if the user brings up a sensitive topic.
To perform a handover, add the handover action in the dialog. All
conversations where the AI Agent has left the chat and have not been assigned to an agent are available in the
**Live chat** menu, under the **Unassigned** section.
## Zendesk department routing
Choose which **Zendesk** department handles the conversation when the handover action is
triggered. To do this, copy the department ID from the **Zendesk integration** settings and paste it
into the `department_routing` field of the handover action in the dialog.
| Zendesk Departments | Dialog |
| ----------------------------------------------------------------------- | ----------------------------------------------------------------- |
| | |
## Facebook Messenger handover
Hand the conversation over to **Facebook Messenger** inbox by enabling the
respective field in the dialog.
## Voice handover
When configuring handover for voice agents on [Twilio Voice](../../integrations/twilio-voice.md) or [Telnyx Voice](../../integrations/telnyx-voice.md), the active call leg is transferred to a destination you specify in the handover action's settings. Provide either:
- An **E.164 phone number** (e.g., `+12025551234`), or
- A **SIP URI** (e.g., `sip:agent@example.com`)
### Transfer method
Choose how the active call is transferred:
- **Standard transfer (default)** — Moveo stays on the call and connects the caller to the agent. Recording continues. Works with a phone number or a SIP destination.
- **SIP REFER** — Moveo hands the call to your phone system and drops off; recording continues on your side. Requires a **SIP destination**, and the incoming call must have **arrived over SIP** — a caller who reached you over a phone line cannot be transferred with SIP REFER.
See [Voice call transfer](../../integrations/voice-call-transfer.md) for how each method works, a comparison, and when to use which.
:::tip Pause before handover
Add a [`Pause`](./pause.md) action of 1–2 seconds immediately before `Handover` so the caller hears the AI Agent's last sentence in full before the call is transferred.
:::
### Custom SIP headers
When the destination is a **SIP URI**, you can attach custom SIP headers to the transfer through the **Attributes** field of the handover action. Each attribute is a key–value pair sent as a SIP header on the outgoing call leg, allowing the receiving system to route or label the call based on context from the AI Agent.
Allowed header names:
- Any `X-*` custom header, except headers starting with the prefix your provider reserves: `X-Twilio` on Twilio Voice and `X-Telnyx` on Telnyx Voice.
- The following standard SIP headers: `User-to-User`, `Remote-Party-ID`, `P-Preferred-Identity`, `P-Called-Party-ID`.
Headers outside the allow-list are silently dropped before the transfer. The combined size of all header names and values, after URL encoding, must not exceed 1024 characters.
Attributes are ignored when the destination is a phone number — SIP headers only apply to SIP URI destinations.
Example handover attributes for a SIP destination:
| Key | Value |
| --------------- | -------------------------------- |
| `X-Customer-Id` | `12345` |
| `User-to-User` | `priority=high;origin=ai-agent` |
### Limitations
- **Web (browser-based) voice calls do not support handover.** The transfer is rejected by the provider because a browser-origin call has no caller ID to use on the transferred leg. Gate the `Handover` action in your workflow so it does not run on browser calls.
- **Standard transfer keeps both legs billed.** The original inbound leg stays open while the new outbound leg to the destination is dialled, so both are billed. With **SIP REFER**, Moveo leaves the call path once the transfer succeeds and is not part of the onward call.
- **Recording on a Standard transfer continues into the transferred call.** With **SIP REFER**, Moveo's recording stops at the handoff (the onward call is between the caller and your system). See [Voice call transfer](../../integrations/voice-call-transfer.md).
- **No automatic retry.** If the destination is busy, does not answer, or rejects the transfer, the call drops. There is no built-in fallback — handle this in your brain workflow if needed.
### Zendesk voice handover setup
An example of a successful implementation for voice handover is shown below, using Twilio Voice as the provider. It uses two separate numbers configured in Zendesk.
The same pattern applies with [Telnyx Voice](../../integrations/telnyx-voice.md): forward the calls to the Telnyx number connected to the integration, and Moveo transfers the call to the agent number on handover.
To configure these numbers in Zendesk, navigate to **Admin settings → Channels → Talk → Lines**.
#### Number configuration
Number 1: "Forwarding Number" (user entry point)
Number 2: "Agent Number" (handover target)
This is the primary number the user calls to initiate a conversation.
It is configured in Zendesk with an overflow rule
This rule immediately forwards all incoming calls to the Twilio number associated with the Moveo integration
This is a separate Zendesk number.
It is configured to route calls directly to a specific department or group of available agents
#### Handover flow
1. **Call initiated**: The user dials the forwarding number (#1)
2. **Moveo connects**: The Zendesk overflow rule instantly forwards the call to the Moveo Twilio integration. The user begins their conversation with the Moveo voice assistant
3. **Handover triggered**: When a handover event is triggered (via dialog configuration), the Moveo platform executes the next step
4. **Twilio API transfer**: Moveo makes a Twilio API call on the active call leg. This API call instructs Twilio to dial and transfer the user to the agent number (#2)
5. **Call received in Zendesk**:
- If agents are available: The call is routed to the configured department, and available agents are notified to pick up the call
- If no agents are available: The call is dropped. However, Zendesk provides native options to manage this scenario, such as:
- Sending the user to voicemail
- Automatically creating a ticket for the abandoned call
- Offering the user a callback when an agent becomes available
---
## Inactivity reminder
The **Inactivity reminder** action sets a timer that triggers a reminder event node after a period of user inactivity. Use this to re-engage users who stop responding during a conversation.
## How it works
When a user becomes inactive (stops sending messages), the inactivity timer counts down. After the specified duration, the system triggers a **reminder event node** that executes your configured flow.
## Configure an inactivity reminder
1. Open your dialog in the editor
2. Add an **Inactivity reminder** action to your flow
3. Set the timeout duration (in seconds or minutes)
4. Create a **reminder event node** in the dialog
5. Build the reminder flow under this node
## Common use cases
### Re-engage during checkout
Send a reminder if a user pauses during payment:
> "Still there? I noticed you paused during checkout. Need help completing your order?"
### Prompt for missing information
Nudge users to provide required details:
> "I'm waiting for your email address to continue. You can type it whenever you're ready."
### Offer assistance
Check if the user needs help:
> "It looks like you might be busy. Feel free to come back anytime, or let me know if you need help!"
## Canceling the timer
The inactivity timer automatically cancels when:
- The user sends a new message
- The conversation ends or closes
- A new inactivity reminder is set (replaces the previous one)
## Next steps
- [Handover action](./handover.md) - Transfer conversations to human agents
- [Tag action](./tag.md) - Add tags for conversation routing
- [Questions](./questions.md) - Collect information from users
---
## Pause
Predetermine how fast or slow Moveo responds to the user. Moveo's default
response time is one second, but this can be changed to other values, such as three or eight
seconds. This changes the elapsed time for the next message from Moveo, and the only visible change
to the user is that the animated 💬 lasts longer.
:::note
Network issues or large files like videos can affect your AI Agent's elapsed time.
:::
The pause is very useful not only if your previous message was a bit long for the user to have time
to read it, but the pause also gives your AI Agent character and makes it more human.
The pause has two fields:
- **`duration`**: The pause duration (in seconds).
- **`show_typing`**: Show a typing indicator during the pause.
A good example of a pause implementation is shown below. The AI Agent sends two large texts to the
user. Without the pause, the texts come one immediately after another, leaving no time for the user
to read them and at the same time flooding their screen.
## Voice integrations
For voice integrations such as [Twilio Voice](../../integrations/twilio-voice.md) and
[Telnyx Voice](../../integrations/telnyx-voice.md), `Pause` has a
different role. It delays the next action in the response, but it does **not** prevent the caller
from interrupting the AI Agent during text-to-speech playback.
The recommended use of `Pause` on voice is **immediately before** a [`Resolve`](./resolve.md) or
[`Handover`](./handover.md) action, so the AI Agent's last sentence is heard in full before the
call ends or transfers:
```
[ Text: "Transferring you to an agent now." ]
[ Pause: 1s ]
[ Handover ]
```
Guidelines:
- **1 second** is enough for most desktop and VoIP callers.
- **2 seconds** is safer for mobile callers on cellular networks with higher jitter.
:::note Why the pause is needed
The telephony provider signals "audio dispatched" before the caller has actually finished hearing
it. There can be 200–300 ms of audio still in flight through the carrier and the caller's device
when the next action would otherwise fire, which clips the tail of the last sentence. The pause
gives that audio time to play out.
:::
---
## Questions
Questions enable your AI Agent to collect information from users through conversational Q&A. The system intelligently extracts answers from context when possible, reducing repetitive questions and creating a natural flow.
Add questions below any [text](../triggers/text.md) or [event](../triggers/event.md) trigger. Your AI Agent can request single or multiple pieces of information within a dialog.
## Understanding context variables
When your AI Agent asks a question, the user's answer is saved to a [context variable](../context.md) that persists throughout the conversation session.
**Save As field:**
The **Save As** field defines the context variable name where the answer is stored. You can use simple names like `email` or `phone`, or use dot notation (`.`) to organize variables in JSON structure: `user.email`, `booking.date`, `payment.amount`.
:::note
If a context variable is already filled, the AI Agent may skip the question automatically unless configured otherwise.
:::
**Example question configuration:**
**User message example:**
## How auto-fill works
Auto-fill attempts to extract answers before prompting the user. The ability to extract from conversation history depends critically on whether you configure a validation guideline.
### With validation guideline (LLM-based)
When a validation guideline is configured, the AI can extract information from **anywhere in the conversation history** only if is **not** a mandatory question:
- **Analyzes full conversation**: Reviews all previous messages, not just the current one
- **Understands context**: Can extract information mentioned several messages ago
- **Intelligent inference**: Understands natural language like "tomorrow", "my email is...", etc.
- **Context variable access**: Can use previously stored context variables
**Example scenario (WITH guideline):**
```
Message 1
User: "Hi, my email is sarah@example.com"
Agent: "Nice to meet you! How can I help?"
Message 2
User: "I'd like to schedule a demo"
Message 3
User: "What times are available?"
Agent: "We have slots at 2pm and 4pm"
Message 4
User: "I'll take the 2pm slot"
[Question node triggers with validation guideline: "Extract user's email"]
Agent: "Perfect! Demo booked for 2pm. Confirmation sent to sarah@example.com"
```
☝️ The email was mentioned in **Message 1**, but the question triggered in **Message 4**. With a validation guideline, the AI found it in the history.
:::warning
If the question was a mandatory one, the user would be prompted to answer it. Even if they already mentioned it earlier in the conversation.
:::
### Without validation guideline (rule-based)
Without a validation guideline, auto-fill is **limited to the current user message only**:
- **Context variable access**: If the context variable already has a value, it will skip the question. (Only if the question is not mandatory)
- **No conversation history**: Cannot look at previous messages
- **No natural language understanding**: Requires exact format (no "tomorrow", just "2025-03-15")
- **Current message only**: If the entity isn't in the current message, auto-fill fails
The variable type,
**Same scenario (WITHOUT guideline):**
```
Message 1
User: "Hi, I'm Sarah and my email is sarah@example.com"
Agent: "Nice to meet you, Sarah! How can I help?"
Message 2
User: "I'd like to schedule a demo"
Message 3
User: "What times are available?"
Agent: "We have slots at 2pm and 4pm"
Message 4
User: "I'll take the 2pm slot"
[Question node triggers WITHOUT validation guideline]
Agent: "What's your email address?" ← Auto-fill FAILED - email not in current message - User is prompted
```
☝️ Without a guideline, the system only checks **Message 4** for an email entity. Since it's not there, auto-fill fails and the user gets prompted.
:::tip
**For intelligent auto-fill from conversation history, always configure a validation guideline.** Without it, questions can only auto-fill from entities detected in the current user message, not from earlier context.
:::
**When auto-fill is skipped:**
- The question is marked as **Mandatory** (see below)
- No relevant data exists (in history with guideline, or current message without guideline)
- The system requires explicit user confirmation
## Ask only
Select **ask only** for simple data extraction without validation constraints.
**Required fields:**
- **Ask**: The question to ask the user.
- **Save input in variable**: The context variable key where the answer is saved.
## Check and ask
Select **Check and ask** to add validation rules to your questions.
**Required fields:**
- **Ask**: The question to ask. Optionally set a **reprompt** message if the user's input fails validation.
- **Validation**: Choose one of the following validation types:
- [Entity](../entities): Checks for a specific entity in the user's message.
- **Input type:** Validates the response format:
- Text
- Email
- Number
- Integer
- Phone
- URL
- Date
- Time
- Datetime
- Currency
- Percentage
- Boolean
Each validation type automatically validates format and normalizes values to a standard format. This ensures consistent data storage, enables reliable integrations with external systems, and simplifies downstream processing in your workflows.
**Why use validation types:**
- **Email**: Ensures valid format for email delivery systems, normalizes to lowercase for database consistency
- **Phone**: Validates international format, removes formatting for SMS/call integrations
- **URL**: Extracts clean URLs for link processing, ensures valid format for web requests
- **Date/Time/Datetime**: Standardizes to ISO formats for calendar integrations, scheduling systems, and database storage
- **Number/Integer**: Ensures numeric calculations work correctly, prevents type errors in APIs
- **Currency**: Standardizes monetary values for payment processing and financial calculations
- **Percentage**: Converts to decimal format (0.0-1.0) for mathematical operations
- **Boolean**: Normalizes to true/false for conditional logic and integrations
- **Text**: Cleans whitespace for consistent display and storage
The validation behavior depends on whether you configure a validation guideline:
**With validation guideline (LLM-based):**
The AI understands natural language and converts it to standard format before validation.
| Validation Type | Input Example | Normalized Output | Purpose |
|-----------------|---------------|-------------------|---------|
| **Email** | "Steve@Gmail.com" | "steve@gmail.com" | Lowercase for consistency |
| **Phone** | "+1 (415)-432-5355" | "+14154325355" | Remove formatting for SMS APIs |
| **URL** | "Visit https://moveo.ai now" | "https://moveo.ai" | Extract URL from text |
| **Date** | "03/15/2025" or "tomorrow" | "2025-03-15" | ISO format for databases |
| **Time** | "2:30 PM" | "14:30:00" | 24-hour format for scheduling |
| **Datetime** | "March 15, 2025 at 2:30 PM" | "2025-03-15T14:30:00" | ISO 8601 for calendar APIs |
| **Number** | "one and a half" or "1.5" | 1.5 | Float for calculations |
| **Integer** | "twenty" or "20" | 20 | Integer for counting |
| **Currency** | "100 dollars" | "USD 100.0" | Standard format for payments |
| **Percentage** | "20%" | 0.2 | Decimal fraction (0.0-1.0) |
| **Boolean** | "yes" / "true" / "1" | true | True/false for logic |
| **Text** | " Hello World " | "Hello World" | Trim whitespace |
**Without validation guideline (rule-based):**
Only accepts pre-formatted inputs. Natural language requires validation guidelines.
| Validation Type | Accepted Input | Normalized Output | Rejected Input |
|-----------------|----------------|-------------------|----------------|
| **Email** | "steve@gmail.com" | "steve@gmail.com" (lowercase) | Invalid email format |
| **Phone** | "+1 (415)-432-5355" | "+14154325355" | Invalid phone format |
| **URL** | "https://moveo.ai" | "https://moveo.ai" | Invalid URL format |
| **Date** | "03/15/2025" or "2025-03-15" | "2025-03-15" | ❌ "tomorrow" |
| **Time** | "2:30 PM" or "14:30" | "14:30:00" | Invalid time format |
| **Datetime** | "2025-03-15T14:30:00" | "2025-03-15T14:30:00" | Invalid datetime format |
| **Number** | "1.5" or "1,5" | 1.5 | ❌ "one and a half" |
| **Integer** | "20" | 20 | ❌ "twenty" |
| **Currency** | "USD 100.0" | "USD 100.0" | ❌ "100 dollars" |
| **Percentage** | 0.2 or "0.2" | 0.2 | ❌ "20%" |
| **Boolean** | "yes" / "true" / "1" | true | "maybe" |
| **Text** | " Hello World " | "Hello World" | (accepts any text) |
:::warning
Natural language inputs like "tomorrow", "twenty", or "100 dollars" **require a validation guideline**. Without a guideline, questions only accept pre-formatted values like "2025-03-15", "20", or "USD 100.0".
:::
- **Guideline** (Optional): Custom validation instructions in natural language. An LLM validates the user's response using this guideline.
:::note
The guideline option is not available when using entity validation.
:::
**Customizing clarification messages:**
When a user provides invalid or ambiguous input, the AI Agent generates a clarification message explaining why the input was rejected. You can influence this message through the validation guideline.
For example, if your guideline includes instructions like "Must be a future date within 90 days. If invalid, remind the user about the 90-day limit", the agent will incorporate this context into its clarification responses.
- **Save input in variable**: The context variable key where the validated answer is saved.
:::note
Entity validation creates a second variable with the suffix `_value` added to your defined key. This variable stores the entity's actual value.
:::
## Mandatory questions
The **Mandatory** checkbox controls whether auto-fill is attempted and how the agent handles information collection.
**When mandatory is OFF (default):**
- The system tries auto-fill first using conversation context
- Only prompts the user if auto-fill fails
- May move forward if the user doesn't provide valid input or changes topic.
**When mandatory is ON:**
- Skips auto-fill entirely (see [data access](#data-access-during-question-processing) for details)
- Always asks the user explicitly, even if the answer exists in context
- Continues asking until a valid answer is provided
**Use mandatory questions for:**
- Sensitive information requiring explicit confirmation (payment details, credit card numbers)
- Legal or compliance requirements (explicit consent, terms acceptance)
- Situations where inference could be incorrect (e.g., "Which email should we use?" when multiple exist)
- Critical workflow steps that cannot be skipped
:::tip
Use mandatory questions sparingly. Auto-fill provides better user experience by reducing repetitive questions.
:::
## Data access during question processing
The AI Agent has access to different information depending on the question type:
**Regular questions:**
- Full conversation history (all previous messages)
- All context variables from earlier in the conversation
- Current user message
- Session metadata (date, time, language)
**Mandatory questions:**
- Limited context (only recent conversation for continuity)
- Current user message
- No access to context variables for auto-fill
This design ensures mandatory questions require explicit user input rather than inferred answers from context.
## How the agent responds to user input
When processing a question, the AI Agent analyzes the user's response and classifies it into response types that control the conversation flow.
| Response Type | Available For | What It Means | Agent Behavior | Example |
|--------------|---------------|----------------|----------------|---------|
| **SUCCESS** | All questions | Answer successfully extracted and validated | Saves the value to the context variable and continues | User: "john@example.com" → Variable filled, workflow continues |
| **CLARIFICATION** | Regular questions | Answer is ambiguous or incomplete | Generates a clarification message explaining the issue | User: "50 euros" when asking for dollars → Agent: "I need the amount in dollars, not euros" |
| **DETAILS_REQUESTED** | Regular questions | User asks for more information before answering | Provides context then re-asks the question | User: "Why do you need my email?" → Agent explains, then asks again |
| **TOPIC_CHANGE** | Regular questions | User changed the subject | Handles topic change, may return to question later | User: "Actually, I want to cancel" → Agent pivots to cancellation |
| **MEMORY_UPDATE** | Regular questions | User is correcting a previous answer | Updates the earlier context variable | User: "Actually my email is jane@example.com, not john@example.com" |
| **FAILURE** | All questions | Cannot extract valid answer | States that information is needed to proceed | User provides invalid input → Agent explains requirement and re-asks |
**Key behaviors:**
- **Regular questions**: Support all response types including topic changes and memory updates
- **Mandatory questions**: Only support SUCCESS and FAILURE response types—the agent always re-asks until valid input is provided
- **CLARIFICATION vs FAILURE**: For regular questions, CLARIFICATION generates helpful follow-up messages; for mandatory questions, FAILURE is used instead
- **MEMORY_UPDATE**: Users can naturally correct mistakes without breaking conversational flow (regular questions only)
- **TOPIC_CHANGE**: Prevents forcing answers when users have urgent needs (regular questions only)
:::note Conversation Tip
Design question prompts to handle clarification naturally. If asking for a date, mention the expected format: "When would you like to schedule? (e.g., March 15 or next Monday)"
:::
## Validation guideline best practices
Keep validation guidelines short and specific—the AI uses these to validate user input. Focus on constraints and format requirements.
**Example 1: Date validation**
```
Validation Type: Date
Validation Guideline: "Must be a future date within the next 90 days"
```
*Why it works:* Clear constraint, specific timeframe, easy to validate.
**Example 2: Phone validation**
```
Validation Type: Phone
Validation Guideline: "US phone numbers only, must include area code"
```
*Why it works:* Specifies format and regional requirement concisely.
**Example 3: Text validation**
```
Validation Type: Text
Validation Guideline: "Full legal name as it appears on government ID"
```
*Why it works:* Sets clear expectation for format and formality level.
:::note
Keep validation guidelines under 15 words when possible. Focus on what makes an answer valid rather than lengthy explanations.
:::
## Questions in your workflow
**Integration tips:**
- Questions execute in sequence—the agent asks them one at a time
- If validation fails, the agent automatically uses the "Reprompt" message
- Slot values can be used in downstream nodes with `{{"{{$variable_name}}"}}` syntax
- Context variables persist throughout the session—no need to ask twice
- For optional information, consider using conditional logic instead of questions
- The agent naturally handles topic changes and clarifications—design for conversational flow, not rigid forms
---
## Replay
## Overview
The **Replay** action allows you to send a message on behalf of the user within a conversation. You
can choose to replay the user's last message or define a custom one. This message is visible only in
the conversation logs and the live chat (if applicable).
## Use Cases
### Routing Conversations
Since replayed messages are treated as user messages, you can leverage this action to match
conditions in [rules](../../environments/rules.md). This allows you to route the conversation to a
different AI Agent, escalate it to a human agent, or trigger another action within the rules system.
See [this guide](../../environments/rules-route-agent.md) for details on routing conversations.
### Triggering a Synthetic Response
If the replayed message (whether the last user message or a custom one) does not match any intent,
but your AI Agent has **Knowledge** enabled, a synthetic response will be triggered. This ensures
that the user receives an appropriate answer even if their original message is not explicitly
covered in the AI’s dialog setup.
---
## Reset
Your AI Agent remembers users' responses but can also reset any value in a flow when needed. This
means that if you were going to ask for the user's phone number, but they have already provided it,
your AI Agent won't ask for it again.
A reset removes either all the [context variables](../context) or specific ones.
For example, if a user types something incorrectly by mistake, give them the opportunity to
correct it. Use a reset to remove the variable where the user stored their
information, then prompt them to enter it again.
Choose between resetting **all** or **specific** variables.
1. When you select **All variables**, all the [variables in the dialog](../context) are reset.
User, bundle variables, and tags are not reset.
2. When you select **Specific variables**, you must specify all the variables you want to reset.
With this option, you can also reset user variables, except for `$user.user_id`.
:::note
System variables are not eligible for reset.
:::
---
## Resolve
Close a conversation automatically through the **resolve** action inside the AI Agent.
When the user triggers a resolve action, the AI Agent performs the following actions:
1. The assistant closes the conversation, always respecting the **Keep alive** setting at the
environment level. This setting determines the duration, in seconds, after which resolved
conversations expire and any additional user messages create a new conversation.
2. The assistant displays the post-conversation survey if the user and the assistant have exchanged
more than three messages.
3. If you are using Zendesk Sunshine Conversations, the assistant passes control to the next
integration in the switchboard without showing a survey.
## Voice integrations
For voice integrations such as [Twilio Voice](../../integrations/twilio-voice.md) and
[Telnyx Voice](../../integrations/telnyx-voice.md), `resolve` hangs up the call. The platform ends
the call within a couple of seconds, whatever the environment's
[keep alive](../../guides/timeouts.md#keep-alive) value.
Add a [`Pause`](./pause.md) action of **1–2 seconds** immediately before `Resolve`, so the bot's
final sentence is fully heard by the caller before the line drops.
```
[ Text: "Thanks for calling. Goodbye." ]
[ Pause: 1s ]
[ Resolve ]
```
---
## Set variables
The **Set variables** action creates or modifies variables during a conversation. Use variables to store information, track state, and personalize responses.
## How to set a variable
1. Open your dialog in the editor
2. Add a **Set variables** action to your flow
3. Enter the variable name (key)
4. Set the value (text, number, or reference to another variable)
5. Save your changes
## Variable types
| Type | Example | Use case |
|------|---------|----------|
| Text | `"premium"` | User preferences, status flags |
| Number | `42` | Counters, quantities, scores |
| Boolean | `true` | Feature flags, confirmation states |
| Reference | `{{$user.email}}` | Copy value from another variable |
## Common use cases
### Track conversation state
```
variable: $step_completed
value: "payment"
```
### Store user preferences
```
variable: $preferred_language
value: "Spanish"
```
### Copy from user context
```
variable: $customer_email
value: {{$user.email}}
```
## Best practices
- **Use descriptive names** - Choose clear names like `order_total` instead of `val1`
- **Keep scope in mind** - Variables persist for the entire conversation
- **Initialize values** - Set default values to avoid undefined references
- **Document your variables** - Maintain a list of variables used in your dialogs
## Accessing variables
After setting a variable, access it in:
- **Text responses**: `Hello, {{$customer_name}}!`
- **Conditions**: Check if `$customer_tier` equals `"premium"`
- **Webhooks**: Include variables in request payloads
- **URL responses**: `https://example.com?user={{$user.user_id}}`
## Next steps
- [Context variables](../context.md) - Learn about the context system
- [Questions](./questions.md) - Collect and store user input
- [Conditions](./conditions.md) - Use variables in conditional logic
---
## Tag
Add tags to the conversation to track when a certain dialog has been triggered. This feature
is useful for obtaining helpful and insightful [analytics](../../analytics/overview.md). All the
tags of a conversation are stored in a context variable called `$tags`.
The tag action supports the following operations:
1. **Add tags** (`add`): Add new tags to the conversation (default).
2. **Remove tags** (`remove`): Remove one or more existing tags from the conversation.
3. **Remove all tags** (`clear`): Clear all tags from the conversation.
---
## AI Agents
AI Agents are the intelligent core of Moveo's platform, designed to understand and respond to user
queries using modern AI technologies. They leverage knowledge-based systems (RAG - Retrieval
Augmented Generation) combined with customizable guidelines to deliver accurate, contextual
responses to your users.
## Knowledge-first approach
Moveo AI Agents primarily operate using a **knowledge-based system** that combines two key
components:
### 1. Knowledge (What your agent knows)
The [knowledge base](../knowledge-base/overview.md) contains curated sets of
information from various sources:
- **FAQs** - Direct answers to common questions
- **Documents** - PDFs, Word docs, and other files
- **Websites** - Crawled web content
- **Knowledge bases** - Structured information repositories
Your AI Agent uses this knowledge to understand context and find relevant information to answer user
queries using RAG (Retrieval Augmented Generation) technology.
### 2. Guidelines (How your agent responds)
[Guidelines](../ai-agents/knowledge.md#guidelines-prompting) are instructions that shape how your AI Agent communicates
and behaves. They include:
- **Custom guidelines** - Specific instructions for your use case
- **Product information** - Details about your offerings
- **Response style** - Tone, format, and personality
- **Handling objections** - Strategies for common concerns
- **Business rules** - Compliance and operational requirements
Think of guidelines as prompting instructions that teach your AI Agent not just what to say, but how
to say it in alignment with your brand and business needs.
## How AI Agents respond
When a user sends a message, your AI Agent:
1. **Searches its knowledge** - Finds relevant information from the connected knowledge base
2. **Applies guidelines** - Uses your custom instructions to shape the response
3. **Generates an answer** - Creates a contextual, accurate response using the configured LLM
This knowledge-first approach means you can build powerful AI Agents by:
- Uploading your content (FAQs, documentation, product info)
- Writing clear guidelines
- Testing and refining
No coding or complex workflows required for most use cases.
## When to use Dialogs (Advanced)
While knowledge and guidelines handle most conversational needs, [Dialogs](./dialogs.md)
are available for specific automation requirements:
- **API integrations** - Connect to external services via
[webhooks](./responses/webhook.md)
- **Multi-step workflows** - Guide users through complex processes
- **Conditional logic** - Create branching paths based on user input
- **Task automation** - Execute specific actions (send emails, update databases)
Dialogs are optional and complement the knowledge-based approach when you need deterministic,
structured workflows.
## AI Agent types
AI Agents can be of different types, each optimized for a specific use case with predefined guideline fields tailored to that purpose.
:::tip
Complete the predefined guidelines to get the best out of your AI Agent.
:::
### Seller agents
These agent types share the same guideline fields: **Goal**, **Overview**, **Features**, **Loyalty**, **Objections**, and **Custom instructions**.
- **Early Engagement**
Build meaningful relationships with potential customers by understanding their needs and guiding them toward the right solutions. Engage customers early to answer questions and offer information before they commit.
- **Product Adoption**
Guide customers through a seamless onboarding experience that helps them start using the product effectively and confidently. Provide clear steps, celebrate milestones, and share best practices.
- **Upsell**
Help customers discover premium features and upgrades that enhance their experience. Focus on identifying moments when an upgrade could genuinely improve the user's results.
### Specialized agents
These agent types have guideline fields optimized for their specific use case.
- **Customer Support**
Provide customer support, addressing inquiries, troubleshooting, and FAQs. Uses **Objections** and **Custom instructions** fields.
- **Debt Collection**
Help manage overdue payments with flexible options and professional communication. Uses **Goal**, **Objections**, and **Custom instructions** fields.
## Next steps
- [Knowledge agent quick start](./quickstart.md) - Build your first AI agent in 10 minutes
- [Knowledge & Guidelines](./knowledge.md) - Configure what your agent knows and how it responds
- [Setup](./setup.md) - Fine-tune tone, response length, and reminders
- [Dialogs](./dialogs.md) - Create advanced workflows with conditional logic
---
## Knowledge agent quick start
Build your first knowledge-based AI agent in under 10 minutes. This guide walks you through creating an agent that can answer questions using your content - no coding or complex workflows required.
## What you'll build
A fully functional AI agent that:
- Answers questions using your uploaded content
- Responds in your brand's voice and style
- Handles common customer queries automatically
- Can be deployed to multiple channels
## Step 1: Create your AI Agent
1. Navigate to **AI Agents**
2. Click **+ Create AI Agent**
3. Choose a descriptive name (e.g., "Customer Support Agent")
4. Select your agent type based on your use case:
- **Customer Support** - For FAQs, troubleshooting, and help content
- **Product Adoption** - For onboarding and feature guidance
- **Early Engagement** - For building relationships and pre-purchase conversations
- **Upsell** - For promoting premium features and upgrades
- **Debt Collection** - For managing overdue payments and settlements
5. Select a language for your AI Agent
6. Click **Create**
:::tip
The agent type provides pre-configured guidelines optimized for specific use cases. You can customize these later.
:::
## Step 2: Create and populate your knowledge base
The knowledge base is your agent's information source. Create one with your content:
### Create the knowledge base
1. Navigate to **Knowledge**
2. Click **+ Create**
3. Name your knowledge base (e.g., "Product Documentation")
4. Select the primary language
5. Click **Create**
### Add your content
Perfect for FAQs and common questions:
1. Click **+ Add FAQ**
2. Enter the question and answer
3. Click **Save**
Example:
```
Question: What are your business hours?
Answer: We're open Monday-Friday 9AM-6PM EST.
For urgent issues, our emergency support is available 24/7.
```
Upload existing documentation:
1. Click **Upload Documents**
2. Select your files (PDF, DOCX, TXT)
3. Click **Upload**
Supported formats:
- PDF files
- Word documents (.docx)
- Text files (.txt)
- Markdown files (.md)
Import content from your website:
1. Click **Add Website**
2. Enter your website URL
3. Configure crawl settings (optional)
4. Click **Start Crawling**
The system will automatically extract and index your web content.
:::note
Knowledge bases automatically chunk content into fragments for optimal retrieval. Each fragment is approximately 400 words.
:::
## Step 3: Connect knowledge base to your agent
1. Open your AI Agent
2. Navigate to the **Guidelines** tab
3. In the **Knowledge base** section at the top of the page, select your knowledge base from the dropdown
4. Click **Connect**
Your agent now has access to all the content in your knowledge base.
:::warning
If the Knowledge Base is not visible, make sure it has the **same** language as your AI Agent.
:::
## Step 4: Configure guidelines
Guidelines shape how your agent communicates. Based on your agent type, you'll see predefined guideline fields optimized for that use case.
1. In your AI Agent's **Guidelines** tab, fill out the predefined fields (Goal, Overview, Objections, etc.)
2. For more specific topics, write them in **Custom instructions** or click the **+** button to add a new guideline in this section.
:::tip
Start with the **Goal** field to establish your agent's primary objective, then fill out the other fields to provide supporting context.
:::
For detailed guidance on writing effective guidelines, see [Knowledge & Guidelines](./knowledge.md#guidelines).
## Step 5: Test your agent
1. Click the **Test** button in the top-right corner
2. The test console opens on the right side
3. Type a question that your content covers
4. Press Enter to see your agent's response
### Testing tips
Try different types of questions:
- Direct questions from your FAQs
- Questions requiring information synthesis
- Edge cases and unclear queries
- Questions outside your content scope
:::tip
If responses aren't optimal, refine your guidelines or add more specific content to your knowledge base.
:::
## Step 6: Configure your language model (Optional)
For advanced users who want to use a specific LLM:
1. Navigate to your AI Agent's **Advanced** tab
2. Select your preferred **LLM Provider** (Moveo.AI, OpenAI, Anthropic, etc.)
3. Choose the specific **Model** (e.g., GPT-4, Claude 3.5)
4. Save your changes
The default Moveo.AI models work great for most use cases.
## Next steps
Your knowledge agent is ready! Here's what you can do next:
### Deploy to channels
- [Web channel](../integrations/web/getting-started.md) - Add to your website
- [WhatsApp](../integrations/whatsapp.md) - Connect to WhatsApp Business
- [Facebook Messenger](../integrations/facebook-messenger.md) - Integrate with Facebook
### Enhance your agent
- [Add more content](../knowledge-base/overview.md) - Expand your knowledge base
- [Live instructions](./build-a-webhook.md#use-case-live-instructions) - Dynamic user data
### Monitor performance
- [Analytics](../analytics/overview.md) - Track agent effectiveness
- [Insights](../analytics/insights.md) - AI-powered improvement suggestions
## Common questions
**Q: How much content do I need?**
A: Start with 20-30 FAQs or 10-15 pages of documentation. You can always add more as you learn what users ask.
**Q: Can I use multiple knowledge bases?**
A: Yes! Connect multiple knowledge bases to cover different knowledge domains.
**Q: How do I handle questions the agent can't answer?**
A: Add a fallback guideline like "If you don't know the answer, say: 'I don't have that information, but I can connect you with our support team.'"
**Q: When should I use dialogs instead?**
A: Use dialogs only when you need specific workflows like API integrations, multi-step forms, or conditional logic. Most conversational needs are handled by knowledge + guidelines.
## Troubleshooting
If your agent isn't responding as expected:
1. **Check knowledge base content** - Ensure relevant information exists
2. **Review guidelines** - Make instructions clear and specific
3. **Test variations** - Try different phrasings of questions
4. **Check language settings** - Ensure agent and knowledge base languages match
5. **Review the Insights tab** - Get AI-powered suggestions for improvements
---
## AI Response
An **AI Response** lets the agent generate a reply on demand at a specific step in a dialog,
instead of sending a fixed, scripted message. When the conversation reaches the step, the agent
writes a tailored response that fits the user and the current context.
## When to use it
Reach for an AI Response instead of a [text response](./text.md) when a single, fixed message
isn't enough:
- The reply needs to adapt to what the user said or to their context.
- The answer depends on information the agent looks up at that moment, such as content from your
[knowledge base](../../knowledge-base/overview.md) or data from a connected tool.
- You want the agent to handle a step in its own words while still following your guidance.
The AI Response always respects your agent's overall instructions. You can optionally add
step-specific guidance that applies only to this step.
## AI Response guidelines
The only setting is an optional **AI Response Guidelines** field — a rich text editor where you
guide how the agent should respond when this step runs.
Within the editor you can:
- Type `@` to reference the agent's tools and point it at a specific tool for this step.
- Type a dollar sign (\$) to reference [context variables](../context.md) and personalize the
response.
If you leave the field empty, the agent still replies — grounded in its general instructions and
knowledge — without any step-specific guidance.
:::tip
Keep guidelines focused on this step only. Broad, agent-wide guidance belongs in your agent's
general instructions, not in every AI Response step.
:::
## Using tools and knowledge
While generating the reply, the agent can search your [knowledge base](../../knowledge-base/overview.md),
call connected [MCP tools](../mcp-servers.md), and trigger a workflow — all as part of the same
response. This lets a single step both fetch the information it needs and answer with it.
The response is produced by the model configured in your [model strategy](../model-strategy.md).
---
## Carousel response
The carousel is an ideal response format when you need to display multiple items in one view.
Carousels can contain up to six cards, each consisting of the following fields:
- **`title`**: The title of the card.
- **`subtitle`**: A short description or subtitle for the card.
- **`media`**: An image or video to display in the carousel. It includes the following sub-fields:
- `type`: Specifies whether the media is an `image` or `video`.
- `url`: The URL of the media.
- **`default_action`** _(Optional)_: An action triggered when the media is clicked, with the
following sub-fields:
- `type`: Can be `postback`, `url`, `webview`, or `phone`.
- `value`: The value associated with the action type.
- **`buttons`**: Each card must have at least one and up to three buttons, formatted as follows:
- `label`: The text displayed on the button.
- `type`: Can be `postback`, `url`, `webview`, or `phone`.
- `value`: The value associated with the button type.
:::note
Postback responses provide the same result as [options](./text#options).
:::
---
## Email
Send email notifications to keep your team updated with the latest
information or events within your AI Agent, or send a confirmation to your customers—all with an email response.
## Fields
Each email response contains the following four fields:
- **From**: The sender of the email, fixed to no-reply@moveo.ai
- **To**: The (one or more) receivers of the email, which you can set to either an email address or
a variable.
- **Subject**: The subject of the email, which also appears in the dialog.
- **Body**: The contents of the email. The body field supports **markdown** formatting for rich text
emails, using HTML tags might **not** work as expected.
```markdown
Hi {{first_name}},
Your order **#{{order_number}}** has been shipped! 📦
You can track it here: [Track Order]({{tracking_url}})
Thanks for shopping with us,
**The {{company_name}} Team**
```
:::tip
To make the message more personalized for the user, refer to
[context variables](../context.md).
:::
## Implementation
The following image shows an example of an email response implementation.
## Troubleshooting
- **Line breaks are not working**: Use `\n` to create line breaks.
- **Not receiving emails**: Contact us at [support@moveo.ai](mailto:support@moveo.ai).
---
## File response
Your end user can download a file with the file response.
Either add the URL of the file or upload it directly.
The file response contains the following fields:
- **`url`**: The URL of the file. Note that when you upload a file, the `url` automatically fills
with the file's URL.
- **`name`**: The name you want to show the user.
---
## Google Sheet
Keep records of conversation data, generate reports, make notes, and perform any other
functionality served by a spreadsheet with the Google Sheet add-on inside Moveo.
## Choose a spreadsheet
1. Open your Google Sheet and click on the
icon on the top right corner
of your screen.
2. Add Moveo's service account `moveosheets@fiery-protocol-326906.iam.gserviceaccount.com` with
**editor** access to the list.
## Dialog
The Google Sheet action contains the following three fields:
- `spreadsheet_id`: The ID of the Google Sheet, which you can find in the URL of the form
`https://docs.google.com/spreadsheets/d/{SPREADSHEET_ID}/edit#gid=0`.
- `sheet_id`: The name of the sheet in which you want the AI agent to write.
- `inputs`: A list of the context variables that the assistant appends on the first empty row of the
sheet. You can find an example below:
---
## Image response
Instead of text, you can respond with an image.
Either add the URL of the image or upload it directly.
Each image response contains two fields:
1. **`url`**: The URL of the image. Note that when you upload an image, the `url` automatically
fills with the image's URL.
2. **`name`**: The name you give to the image, which is only shown when the image cannot load.
---
## Responses
Each time the user sends a message, the AI Agent activates one or more
[triggers](../triggers/overview.md). It can then respond in a variety of forms.
There are different kinds of responses such as plain text, links, menus, and options. You can add
one or more responses below a [trigger](../triggers/overview.md) by dragging and dropping
them.
## Types of actions
Moveo.AI supports the following responses, operations, and extensions:
### Responses
| Response | Description |
| :------------------------------ | :---------------------------------- |
| [Text](./text.md) | Reply with a text |
| [AI Response](./ai-response.md) | Generate a tailored reply on demand |
| [Image](./image.md) | Send an image |
| [Carousel](./carousel.md) | Reply with a carousel |
| [Webview](./webview.md) | Display a webview |
| [Video](./video.md) | Send a video |
| [File](./file.md) | Send a file |
| [Survey](./survey.md) | Display a survey |
| [URL](./url.md) | Send a URL |
### Operations
| Operation | Description |
| :---------------------------------------------- | :------------------------------------------------ |
| [Question](../operations/questions.md) | Ask a question to the user |
| [Jump to](../operations/event.md) | Trigger a specific node |
| [Condition](../operations/conditions.md) | Create a logic tree |
| [Handover](../operations/handover.md) | Transfer the conversation to an agent |
| [Tag](../operations/tag.md) | Label the conversation with a tag |
| [Pause](../operations/pause.md) | Pause the conversation |
| [Set variables](../operations/set-variables.md) | Set a variable equal to a value |
| [Reset variables](../operations/reset.md) | Reset specific or all context variables |
| [Resolve](../operations/resolve.md) | Close the conversation |
| [Replay](../operations/replay.md) | Transfer the conversation to a different AI Agent |
### Extensions
| Extension | Description |
| :------------------------------- | :--------------------------- |
| [Webhook](./webhook.md) | Call a predefined webhook |
| [Google Sheet](./googlesheet.md) | Store data in a Google Sheet |
| [Email](./email.md) | Send an email |
## Add a response
Add one or more actions below a [trigger](../triggers/overview.md) by using Moveo's drag-and-drop
functionality.
---
## Passthrough
:::note Enterprise only
This feature is only available for accounts on the Enterprise plan. Want access?
[Contact our sales team to learn more](https://moveo.ai/book-a-demo).
:::
The passthrough feature allows you to send custom payloads directly to messaging channels without
Moveo's standard message processing. This extends the capabilities of your
[AI Agent](../overview.md) by leveraging platform-specific features to their full potential.
## Overview
When you need to utilize platform-specific features or send specialized message formats, the
passthrough feature enables you to bypass Moveo's standard message processing and send payloads
directly to the channel.
## Supported channels
The passthrough feature is currently available for the following messaging channels:
- Viber
- WhatsApp
- Sunshine Conversations
## Schema
To use the passthrough feature, add a `passthrough` field to your text or carousel response. The
field contains a list of objects with the following structure:
| Field | Type | Description |
| ------- | ------ | -------------------------------------------------------------------------------------------- |
| channel | string | The target messaging channel (`"whatsapp"`, `"sunco"` (Sunshine Conversations) or `"viber"`) |
| payload | string | A JSON stringified string containing the channel-specific message format |
:::important
Ensure your payload matches the target channel's message format requirements.
:::
**Example Structure:**
```json
{
"passthrough": [
{
"channel": "string",
"payload": "string" // JSON stringified payload
}
]
}
```
## Platform-specific implementations
### Sunshine Conversations
For Sunshine Conversations (Sunco), the passthrough feature integrates with their native passthrough
API. The payload is placed in the `override` field of the WhatsApp message. See the
[Sunshine Conversations passthrough documentation](https://docs.smooch.io/guide/whatsapp/#passthrough-api)
for detailed examples.
## Examples
The following example demonstrates sending a custom WhatsApp message using passthrough. On all other
channels, the AI Agent sends only the text "Hello!".
```json
{
"type": "text",
"text": "Hello!",
"passthrough": [
{
"channel": "whatsapp",
"payload": "{\"type\":\"template\",\"template\":{\"namespace\":\"XXXXXXXX_XXXX_XXXX_XXXX_XXXXXXXXXXXX\",\"element_name\":\"hello_world\",\"language\":{\"policy\":\"deterministic\",\"code\":\"en_US\"},\"components\":[{\"type\":\"header\",\"parameters\":[{\"type\":\"image\",\"image\":{\"link\":\"https://image.jpg\"}}]}]}}"
}
]
}
```
## Best practices
1. Always validate your channel-specific payloads against the platform's documentation.
2. Test passthrough messages in a development environment first.
3. Keep track of platform-specific features and limitations.
4. Consider fallback options for channels that don't support certain message types.
## Limitations
- The passthrough feature is only available through the API.
- Each channel has specific message format requirements and limitations.
- Messages sent via passthrough bypass Moveo's standard message processing and validation.
## Channel documentation
For detailed message format specifications, refer to these platform-specific resources:
- [WhatsApp Business API documentation](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages)
- [Viber REST API documentation](https://developers.viber.com/docs/api/rest-bot-api/#message-types)
- [Sunshine Conversations passthrough documentation](https://docs.smooch.io/guide/whatsapp/#passthrough-api)
---
## Survey response
The survey response is essentially a [webview](./webview.md) that makes it easy for users to provide
their thoughts and opinions on your AI Agent's performance. You can either use the default
satisfaction survey, as shown in the following demonstration, or
[create your own](../../guides/survey.md).
## Fields
A survey contains the following fields:
- **`url`**: A valid and public URL to the survey webview. Its default value is the default
satisfaction survey, hosted at
[https://webviews.moveo.ai/common/survey](https://webviews.moveo.ai/common/survey).
- **`name`**: The text shown at the top of the box.
- **`label`**: The text that appears on the button.
- **`height`**: The height of the survey webview window.
---
## Text response
'@site/src/components/Img';
The most common response to a question is a text response. It is mainly used to inform the user or
guide them.
## Use of a text response
The following images show the implementation of a simple intent trigger-response model.
When the user sends a message like "Hello, when are you open?", the AI agent replies with the text
response specified within the dialog node.
## Options
Give **options** to the user in the form of buttons.
Under a text response, optionally add one or more options to facilitate the conversation
with the user and lead them to predetermined sections. For example, you could suggest a continuation
of the above conversation by introducing a _Location_ and an _Appointment_ request as options.
Options consist of **`label`** and **`text`** fields. The `label` is what the user sees as an
option, and the `text` is what you want to send to Moveo upon the user's click.
The following example shows an implementation of options in a `#store_hours` intent. When the user
clicks on the _Location_ button, Moveo receives the text "Where are you located?" and answers
accordingly.
## Alternative text
Write alternative text responses within the same response to avoid being repetitive.
When triggered, the AI agent randomly selects one of the texts you give it as options.
## Customization
Moveo's rich text editor allows you to customize your text responses using Markdown. You can add
emphasis to your text using **bold** or _italics_, create [hyperlinks](#customization) to relevant
content, and even insert emojis 😃 to convey emotions. This feature gives you the flexibility to
tailor your responses to your audience and make them more engaging and effective.
---
## URL response
Respond with a URL instead of text. This opens the link directly in the user's browser or messaging app.
## Why use URL responses
Use a URL response rather than adding a URL inside a text response. This approach:
- Prevents encoding errors with special characters
- Handles context variables in query parameters correctly
- Provides a cleaner user experience on messaging platforms
- Allows tracking and analytics on link clicks
## How to add a URL response
1. Open your dialog in the editor
2. Add a new response node
3. Select **URL** as the response type
4. Enter your URL in the input field
## Using context variables
Include context variables in your URL to create dynamic links:
```
https://example.com/order?id={{$order_id}}&user={{$user.email}}
```
The system replaces variables with their values before sending the URL to the user.
## Common use cases
| Use case | Example URL |
|----------|-------------|
| Order tracking | `https://store.com/track?order={{$order_id}}` |
| Password reset | `https://app.com/reset?token={{$reset_token}}` |
| Documentation | `https://docs.example.com/{{$topic}}` |
| External forms | `https://forms.example.com?prefill={{$user.email}}` |
## Next steps
- [Text responses](./text.md) - Standard text messages
- [Image responses](./image.md) - Send images to users
- [Context variables](../context.md) - Learn about using variables in responses
---
## Video response
Instead of a text response, you can reply with a video.
Either add the URL of the video or upload it directly.
The video response contains the following fields:
1. **`url`**: The URL of the video. Note that when you upload a video, the `url` field automatically
fills with the video's URL.
2. **`name`**: The name you give the video, which is only shown when the video cannot load.
---
## Webhook
## Overview
A [webhook](../webhooks.md) allows you to use another program, platform, or database. By connecting
to it, your end user can perform various actions directly from the AI Agent chat without ever having
to leave it. These actions include:
- Booking appointments
- Making purchases, handling returns, and processing refunds
- Filling out web forms
- Sending emails
- Retrieving end user information
- Updating a Google Sheet with necessary data
## Use of webhook response
A webhook contains the following two fields:
- **WEBHOOK**: The selected webhook from the list of webhooks in the AI Agent
- **FALLBACK**: The text to send to the user if the webhook call fails
---
## Webview response
'@site/src/components/Img';
## Overview
A webview can be used when it is necessary to collect a large amount of information from the user.
It offers a similar experience to a common website, where the user interacts with a static HTML
page. This is typically used to complete a form, register for an event, or any other applicable
scenario.
:::note
A webview can **only** be used with Webchat, Facebook Messenger, and Viber, and **must** be hosted
on a public URL.
:::
See the step-by-step guide on [how to create a webview](./webviews).
## Fields
A webview contains the following fields:
- **`url`**: A valid and public URL to the webview
- **`name`**: The text shown at the top of the box
- **`label`**: The text that appears on the button
- **`trigger_node`**: The trigger node that the flow returns to when the user closes the webview
- **`height`**: The height of the webview window
:::note
The height option is only available in Facebook Messenger, Webchat, and Zendesk Sunshine.
:::
---
## Webviews
## Templates
- If you want to jump straight into some template code, go to our
[integration-guides repository on GitHub](https://github.com/moveo-ai/integration-guides).
- You can test
[a template AI Agent that uses a form webview](https://web-client.moveo.ai/preview?integrationId=28b47bb5-63cd-4ea8-a821-f1c0d242af3f).
## How to create your own webview
When the [Webview response node](./webview.md) is triggered, and the customer
presses the **Open Form** button, Moveo calls your webview URL and appends the necessary query
parameters.
For example, the URL `https://webviews.moveo.ai/Company/webview-name` would be called like:
`https://webviews.moveo.ai/Company/webview-name?channel=facebook&integration_id=1a234567-b8cd-9e0f-1234-g5h6ij78klmn&page_id=1234567890123456&session_id=ab1c23d4-5ef6-7gh8-i9hj-k0lm12345n6o&trigger_node_id=123456a7-bc89-01d2-345e-67f89g012h34&user_id=1234567890123456`
### Ensuring the origin of the webview request
In some cases, the webview may need to exchange context with the AI Agent. To ensure that the data
is secure in that event, create a pair of RS256 private and public keys by executing the following
commands:
```shellscript
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -outform PEM -pubout -out public.pem
```
Add the public key to your integration (example for Facebook):
- Go to the Integrations tab of your account.
- Select your environment and integration.
- Add the public key in the **YOUR PUBLIC KEY** field of the integration.
### Creating the webview
Here is a step-by-step example of creating a webview that uses a form to collect data from the user
and sends it back to Moveo.
1. Get the following query parameters from the URL:
| Parameter | Required | Description |
| ----------------- | :----------------: | --------------------------------------------------------- |
| `integration_id` | :heavy_check_mark: | The ID of the integration that triggered the webview |
| `session_id` | :heavy_check_mark: | The ID of the current conversation session |
| `user_id` | :heavy_check_mark: | The user's unique ID in Moveo |
| `channel` | :heavy_check_mark: | The integration channel (e.g. `web`, `facebook`, `viber`) |
| `trigger_node_id` | ➖ | The ID of the node that triggered the webview response |
| `page_id` | ➖ | The Facebook page ID (Facebook Messenger only) |
| `lang` | ➖ | The language code of the AI Agent, if set |
:::tip
The `user_id` is also available in the payload of any Moveo webhook call to your
backend — it is included under `context.user.user_id` in [event webhooks](../webhooks.md#first-message-and-pre-message-webhooks)
and can be passed explicitly as a context variable in [dialog webhooks](../action-webhooks.md).
This is useful if your webview is opened from a flow where a webhook has already run and you
want to correlate the two requests server-side.
:::
2. Collect data using a form or in any other way you wish.
3. Prepare the request body:
```ts
data = {
trigger_node_id, // required, UUID of the trigger node
context: {
// optional, any context variables you want to pass back to the AI Agent.
...contextFromForm,
},
};
```
The `context` field is merged into the conversation's context object and the variables
become available to the flow. See [Context and variables](../context.md) for details on how
context works and what system variables are already available.
4. Generate a signature (example in JavaScript)
```ts
const secret = Buffer.from( // your private RSA key
process.env.PRIVATE_RSA_KEY,
'base64'
).toString();
const payload = {
sub: , // Required
iss: 'www.webviews.moveo.ai', // Required
};
// The "expiresIn" option adds an "exp" claim to the payload.
sign(payload, secret, { algorithm: 'RS256', expiresIn: '4000ms' });
```
5. Send the data to Moveo by making an HTTP POST request to:
`https://channels.moveo.ai/v1/webview/${integration_id}`, using the following headers:
```ts
headers: {
Authorization: `Bearer ${signature}`,
'X-Moveo-Session-Id': sessionId,
'Content-Type': 'application/json',
}
```
A successful request returns HTTP `200 OK`. Error responses return a JSON body with
`error_code`, `error_message`, and `status_code` fields. Common error cases include an invalid or
expired JWT (`401`), a missing or expired session (`401`), or a missing `trigger_node_id`
(`400`).
6. Finally, close the webview by performing the following:
```ts
const closeWebview = () => {
if (channel === "facebook") {
return closeFacebookWebview();
}
return window.close();
};
```
### Additional utilities
For Facebook, check out the
[Messenger utility methods](https://developers.facebook.com/docs/messenger-platform/reference/messenger-extensions-sdk/)
to learn more about some methods you could use for your webview.
---
## Setup
This configuration framework fine-tunes the AI agent's behavior, tone, and response style to better
serve customers. Proper setup ensures that the AI agent enhances the user experience, drives
platform adoption, and aligns seamlessly with business goals.
## Company name
Each AI agent can be designed to serve different companies under the same account. This ensures a
tailored user experience that aligns with the branding, tone, and goals of each company.
## AI Agent goal
Define the specific objective of the AI agent to align with the desired outcomes. This ensures the
agent delivers targeted and accurate assistance to end-users.
:::tip
Setting a clear goal helps the AI agent support business priorities, improve user engagement,
and drive measurable outcomes.
:::
## Tone of voice
Set the communication style for the AI agent to ensure it matches your company's branding and user
experience.
### Available tone options
1. **Creative**: Engaging, fun, and expressive tone for interactive and informal user interactions.
2. **Neutral**: Balanced and clear communication suitable for general use.
3. **Matter-of-fact**: Straightforward, practical tone focused on delivering clear and direct
information.
4. **Professional**: Polite, formal, and competent style ideal for business and enterprise
environments. Matching the tone to your audience enhances user satisfaction, builds trust, and
ensures the AI agent communicates effectively.
:::info
Tone options may slightly differ based on the selected **AI Agent type** to better align
with its purpose.
:::
## Response length
Customize how detailed the AI agent's responses should be based on user interaction needs and the
complexity of your business. Tailoring response length optimizes user interactions, ensuring clarity
while balancing speed and detail based on your workflows and user needs.
### Available response options
1. **Short**: Minimal, concise replies covering only the essentials.
2. **Standard**: Balanced responses with clear and informative details.
3. **Comprehensive**: In-depth replies that provide additional context and thorough explanations.
## Conversation start
The **Conversation start** setting lets you pick the dialog node every new conversation begins
at — always, regardless of how the user opens the conversation. The opening becomes
**deterministic**: you design it once, in a regular dialog node, and every user gets the same entry
point.
Set **When a conversation starts, trigger:** to the node of your choice and save.
Common use cases:
- **Authentication at the start of the session** — the most common case. Place an
[Authentication action](../authentication/authentication-overview.md) in a node and have every
conversation start there.
- **Scripted welcome flows** — a fixed greeting, an introduction of the agent's capabilities, or a
routing menu.
- **Compliance disclaimers** — recording notices, terms the user must see before anything else.
- **Data collection up front** — questions or webhooks that populate context the rest of the
workflow depends on.
In the dialog builder, the chosen node is marked with a *"Conversation starts here"* icon in its
header.
## Global reminders
The Global Reminders feature allows you to configure automated follow-up messages when a user does
not respond within a set timeframe. These reminders ensure that conversations stay active and users
receive timely nudges to engage with the AI agent.
### Configuration options
- You can set up to **three (3) reminders**.
- Reminders must be configured in **ascending order** (i.e., the first reminder must be the shortest
interval, followed by longer intervals).
- Each reminder is linked to a **specific node** that will be triggered when the reminder is sent.
### Timers
Each reminder consists of:
- **Time Delay**: The amount of time (e.g., 5 minutes, 15 minutes, 30 minutes) after which the
reminder is sent if the user remains inactive.
- **Connected Node**: The system calls a predefined node (e.g., "Affirmative" in the screenshot)
when the timer expires.
- **Preview**: Clicking the **Preview** button allows you to view the dialog in which the selected
node is contained.
The following example shows a possible configuration:
- **Reminder 1**: Sent after **5 minutes** of inactivity, triggering the **Affirmative** node.
- **Reminder 2**: Sent after **15 minutes** of inactivity, triggering the **Affirmative** node.
- **Reminder 3**: Sent after **2 hours** of inactivity, triggering the **Goodbye** node.
**Preview:**
**Actions**:
- **Add Timer**: Allows you to configure additional reminders (up to a max of 3).
- **Delete Timer**: Removes an existing reminder.
- **Save**: Confirms and applies your reminder settings.
## Next steps
- [Knowledge & Guidelines](./knowledge.md) - Configure what your agent knows and how it responds
- [Advanced settings](./advanced.md) - LLM selection, prediction thresholds, and timeouts
- [Test your agent](./test.md) - Validate responses before deployment
- [Dialogs](./dialogs.md) - Create advanced workflows with conditional logic
---
## Simulations
Simulations are regression tests for your AI Agent. Describe a conversation in plain language,
describe what success looks like, and Moveo runs the whole multi-turn conversation for you. The
conversation goes through the same pipeline that serves your customers, and you get a pass or fail
verdict with written reasoning.
This turns agent changes from guesswork into something you can verify. Write 10 to 20 simulations
covering the behavior you care about most, run them after every change, and you know within minutes
whether you broke anything.
:::note Paid feature
Simulations require a paid plan. Trial accounts see an upgrade prompt instead of the feature.
:::
## How a simulation works
Each simulation runs as a three-part loop:
- **A simulated customer** plays the role you described in the scenario. It sends one message at a
time and stays in character.
- **Your AI Agent** answers through its real pipeline, using the same knowledge base, guidelines,
dialogs, tools, and webhooks it uses in production.
- **An evaluator** reads the finished conversation and grades it against your success criteria,
then explains its verdict.
The conversation ends when the simulated customer has nothing left to say, or when the turn limit is
reached.
## Create a simulation
1. Go to **AI Agents**.
2. Select the AI Agent you want to test.
3. Open **Simulations**.
4. Click **Create**.
5. Fill in the fields described in the following table.
6. Click **Create** to save it. When **Schedule** is **Not set**, you can click **Create & Run**
instead to save the simulation and run it immediately.
| Field | What to enter |
| --- | --- |
| **Title** | A name that describes the purpose of the test. Titles are unique per AI Agent. |
| **Scenario** | The situation, including the customer's goal and key details. |
| **Success criteria** | The actions or outcomes required for the agent to succeed. |
| **Channel type** | The format of the conversation: **Chat**, **Email**, or **Voice**. |
| **Schedule** | How often the simulation runs on its own. Leave it as **Not set** to run it manually. |
| **Category** | An optional label that groups and filters your results. |
As you type, Moveo reviews your draft and suggests improvements, such as tightening success criteria
that are too vague to grade. The suggestions are advisory and never block you from saving.
## Write an effective scenario
The scenario describes both what happens and who the customer is. The simulated customer plays that
role, so the more specific you are, the more realistic the conversation. Useful details include:
- **The customer's goal** — "wants to deposit money", "asking about loan rates", "closing their account".
- **Personality and emotional state** — "frustrated", "polite and elderly", "panicked after losing their card".
- **Language** — "writes entirely in Greek", "starts in English, then switches to Spanish".
- **Domain context** — "owes \$5,000", "long-time customer unhappy with a fee increase".
- **Conversation dynamics** — "after three messages they get impatient and ask for a human".
- **Adversarial behavior** — jailbreak attempts, social engineering, or heavy typos.
The simulated customer also receives a summary of your agent's configuration, including its name,
goal, and default language. Its messages therefore read as realistic against that specific agent.
## Write effective success criteria
The evaluator grades the conversation against your wording, so describe observable behavior rather
than a general impression.
The evaluator reads the full transcript **and** structured data collected during the run: which tools
the agent invoked, which webhooks fired, whether the conversation was handed over to a human, whether
the agent ever fell into an unknown or fallback response, and the final session context. That means
criteria can assert on far more than the words in a reply:
| What you want to check | Example criteria |
| --- | --- |
| A specific answer | "The agent states that the current interest rate is 4.2%." |
| A behavior | "The agent hands over when the customer explicitly asks for a human." |
| Language compliance | "The agent responds in Greek throughout." |
| Tool usage | "The agent calls `get_account_balance` before answering." |
| Webhook usage | "The agent triggers the know your customer (KYC) webhook before confirming the transfer." |
| Containment | "The conversation is never handed over to a human." |
| Coverage | "The agent never falls back to an unknown response." |
| Flow adherence | "The agent acknowledges, offers alternatives, and only closes if the customer insists." |
| Refusals | "The agent refuses to share internal system details." |
| Context variables | "The `user_tier` context variable holds the customer's tier by the end." |
:::tip Make criteria observable
"The agent responds well" cannot be graded, because nothing in the transcript proves it. Rewrite
vague criteria as a concrete action or outcome, such as "The agent retrieves the balance and offers a
payment plan."
:::
## Run simulations
Run simulations from the **Simulations** tab in any of these ways:
- Open the actions menu on a row and choose **Run** to run that one simulation.
- Select several rows with their checkboxes, then click the run button to run the selection.
- Click **Run all** to run every simulation on the AI Agent.
A notification confirms the run has started and tells you it is usually done within minutes. A second
notification arrives when the run finishes, even after you navigate elsewhere.
To stop a run that is still going, open its actions menu in the **Runs** tab and choose **Stop**.
Stopping cancels the remaining simulations and cannot be undone.
## Schedule runs
Set the **Schedule** field on a simulation to run it automatically:
| Cadence | When it runs |
| --- | --- |
| **Weekdays** | Monday to Friday at 09:00 UTC |
| **Weekly** | Every Monday at 09:00 UTC |
| **Monthly** | The first day of each month at 09:00 UTC |
Simulations that share a cadence run together in one scheduled run. Set the field back to **Not set**
to remove a simulation from its schedule.
## Read the results
The **Runs** tab lists every run with its date, status, success rate, number of simulations, number of
failures, duration, and what triggered it. Filter by status, trigger, or date range to narrow the list.
Open a run to see a summary of its success rate, failure count, and total simulations, followed by a
table of results. Each row shows one simulation and its result:
| Result | Meaning |
| --- | --- |
| **Success** | The agent met your success criteria. |
| **Fail** | The agent did not meet your success criteria. |
| **Error** | The simulation could not complete. |
| **Pending** | The simulation is queued. |
| **In progress** | The simulation is running. |
Click **Preview** on a row to replay the conversation turn by turn. The panel alongside it holds five
tabs:
- **Results** — the verdict and the evaluator's written reasoning, together with the scenario and pass
condition used for the run.
- **Details** — what the agent did on the selected turn.
- **Context** — the context variables at the selected turn.
- **Conversation** — the conversation ID, request ID, channel, turn count, and duration.
- **Insights** — click **Generate insights** to run the insights configured on your AI Agent against
this transcript.
The evaluator's reasoning points at specific turns, so a failure tells you what to fix: a guideline, a
dialog flow, a knowledge base document, or a tool.
:::note Results reflect the agent at run time
A run shows an **(outdated)** marker when the simulation changed after the run finished. Run it again
to grade your agent against the current wording.
:::
## Examples
| Title | Scenario | Success criteria | Channel |
| --- | --- | --- | --- |
| Frustrated handover | An impatient customer who has waited 10 minutes grows frustrated after two or three messages and demands a manager. | The agent acknowledges the frustration and hands over without trying to resolve further. | Chat |
| Card-loss panic | A panicked customer whose card was stolen urgently demands that it be blocked. | The agent treats the request as urgent, confirms identity quickly, and calls `block_card`. | Chat |
| Multilingual Greek | A Greek-speaking customer writes entirely in Greek to ask about loan rates. | The agent responds in Greek with accurate information from the knowledge base. | Chat |
| Hardball debtor | An aggressive customer who owes \$5,000 refuses to pay and threatens legal action. | The agent stays calm, empathizes, and presents installment options without being confrontational. | Chat |
| Email dispute | A customer sends a formal email disputing a \$150 charge from an unrecognized merchant. | The agent acknowledges the dispute, explains the investigation timeline, and starts the dispute flow. | Email |
---
## AI Agent training and testing
## Confidence Level
When the AI Agent is not 100% certain about a user's message, it makes an elaborate prediction based
on its smart AI algorithm and responds according to its confidence level.
:::note
The only way the AI Agent responds with 100% confidence is if the user's message exactly
matches an intent expression you have written.
:::
Review these predictions and use the [**Amend**](#add-new-training-phrases) functionality
inside the test to manually link the [intent](./intents.md) with the correct expression.
A very effective way to use training and increase the confidence level of your AI Agents is to
invest time in feeding them profession-specific language and jargon. This helps the AI Agent learn
and adapt to your needs.
With state-of-the-art [NLP](https://en.wikipedia.org/wiki/Natural_language_processing) algorithms,
machine learning, and a bit of guidance, your AI Agent will be able to engage in meaningful
end-to-end conversations with your users.
## Testing Your AI Agent
Click **Test** to interact with your AI agent and evaluate its responses. Pretend to
be an end user and check if the assistant answers your questions correctly.
Test your AI agent either within Moveo or with WhatsApp.
:::note
When testing with WhatsApp, you simulate the conversation using your phone number. This is different from [an integration with WhatsApp](../integrations/whatsapp), as it tests the
integration with our Moveo number. You must have a WhatsApp account with this number to test.
:::
## Amend
### Rephrasing
Before the user's message goes to the AI Agent, it passes through a specialized LLM that understands
and routes the message to a specific intent. During this process, the message can be rephrased to
improve understanding. However, this rephrasing may not always be accurate, leading to a lower
confidence level in matching the intent. In such cases, you can use the Amend feature to correct the
rephrased message.
:::warning
This rephrasing **WILL NOT** take effect immediately. It will be used to improve the
training data for future versions of our LLM.
:::
### Add New Training Phrases
In the replayed logs section, if an intent that should have a higher confidence level is not
triggered, you can use the Amend feature to add the user’s input as a new training phrase. This
helps the AI Agent better understand the user’s intent. If an intent already has a 100% match, the
Amend button will not be displayed.
### Amend the Response
If the source of the AI Agent's response is synthetic, you can amend the response to improve its
accuracy. As with [rephrasing](#rephrasing), this will not take effect immediately.
## Context
Add your own [context variables](./context.md), custom user information, or tags to the
session to test the AI Agent's behavior under specific circumstances.
---
## Event trigger
Event triggers are the links between different dialogs. They connect two or more dialogs
together. Moveo breaks down the obsolete tree-like bot structure and uses many small, independent
parts that interconnect with each other. The transition from one dialog to another is seamless.
## How to use an event trigger
Use the event trigger to create a reusable dialog flow. Link it to a specific moment in a
conversation using the **Jump to** action.
In the following example, the **Jump to** action (left) triggers the dialog that has an event
trigger as its parent node (right).
| Jump action | Event trigger |
| :--------------------------------------------------------: | :---------------------------------------------------------: |
| | |
---
## Triggers
Every [dialog](../dialogs.md) starts with a single trigger. Moveo.AI supports the
following triggers:
| Type | Description |
| :---------------------- | :------------------------------------------------------------------------------------ |
| [Text](./text.md) | Triggered by text messages |
| [Event](./event.md) | Triggered internally from a different dialog node |
| [Unknown](./unknown.md) | Triggered when Moveo cannot match any of the dialog nodes given the recognized intent |
## Add a trigger
Add a new trigger using Moveo's drag-and-drop functionality.
:::caution
Avoid using the same trigger words for multiple intents to prevent collisions.
:::
## Uses of triggers
Moveo has two different functionalities for triggers:
1. They can be used as the parent trigger (`$r_0$`, `nodes[0]`) in a dialog.
2. They can be used as child triggers to provide a different response. See what happens for an
[intent trigger](./text.md) and a
[fallback](./unknown.md).
---
## Intent trigger
Use intent triggers to start a dialog **directly** from a user's message.
When the AI Agent recognizes the intent behind the user's message, it activates the corresponding
trigger and starts the respective dialog. An intent trigger is always connected to an **intent**,
which signifies the activation of the trigger.
## How to use an intent trigger
An intent trigger is connected with the intent `#store_hours`. When a user sends a message like
"When are you open?", the AI Agent identifies the intent as `#store_hours` and starts the
corresponding dialog.
| Dialog | Chat |
| :----------------------------------------------------------: | :-------------------------------------------------------: |
| | |
## Multilevel dialog
An intent trigger can also serve as a **child** node in a dialog. This means that the AI Agent
activates the trigger only when it is already inside the dialog of a parent node. The following
example shows a case in which the intent `#affirmative` is used as a parent and a child node.
When `#affirmative` is the parent node, if the user types 'yes' the message 'I'm
listening!' comes up. However, when they ask about appointments and the AI Agent asks for
confirmation, given that `#affirmative` is a child node of the `#appointments` one, the response of
booking appointments comes up.
---
## Fallback
If your AI Agent doesn't recognize the user's intent, it activates the **fallback** trigger. This
can occur in the following situations:
- The AI Agent recognizes the intent with a [confidence level](../test#confidence-level) below the
threshold you have set.
- You have not connected the intent to a trigger that matches the dialogs you have already set up.
This can be done for intents like [`#offtopics`](../intents#off-topic-messages).
- The AI Agent does not recognize an appropriate answer to a [question](../operations/questions.md) (wrong type
or entity).
## Multilevel dialog
The fallback can also serve as a **child** node in a dialog. This means that the AI Agent
activates this trigger only when it is already inside the dialog of a parent node.
When the fallback is a child node, if the user types something that the AI Agent cannot understand
within a dialog, the message it gives the user is different than when the user is not in the dialog.
---
## Versions
Moveo allows you to create multiple versions of the same AI agent.
Imagine you are operating an AI agent in production, with users asking questions throughout the day.
If you want to implement new changes without making them visible to your users immediately, you can
use versions.
## Draft state
All changes you make are saved to the **draft** state of the AI agent. In [Test](test.md), you
always interact with the draft version of the AI agent. It works as one more version of the AI
agent, with the difference that already published versions will get locked and are not editable.
This means that you can also assign a conversation to a draft version if you set a
[rule](../environments/rules.md) to do so.
## Create a new version
To create a new version:
1. Go to the AI Agent you want to create a new version of.
2. Click the **Publish version**. button in the top right corner of the screen.
3. Write a short description of your changes.
4. Click the **Save**. button.
:::caution
The system allows up to **25 versions** at any time. To exceed this limit, delete a
previous version before creating a new one.
:::
## Manage a version
For any version of the AI agent, you can perform the following operations in the **Versions** menu:
1. **Restore**: Revert the AI agent to the selected version.
2. **Export**: Download a JSON file of the selected version.
3. **Delete**: Permanently delete the selected version.
## Assign the new version
After you create a new version and are ready to share it with your users, navigate to the
[**rules**](../environments/rules.md) and set in the **then** section the new version of the AI agent.
---
## Webhooks
## Introduction
Webhooks let your AI Agent call your own backend during a conversation. Whenever a webhook fires, Moveo sends an HTTP `POST` to a URL you provide; your endpoint can read the conversation context, run business logic, and respond with new context variables or replies for the agent to deliver.
Moveo supports six webhook types, each firing at a different point in the conversation:
| Type | When it fires |
| --- | --- |
| [Dialog](./action-webhooks) | A dialog node hits a webhook action |
| First message | Once per session, on the user's first message to a given AI Agent |
| Pre message | Before every user message is processed |
| Post message | After the agent has generated its reply |
| [Authentication validation](../authentication/authentication-webhooks#validation-webhook-contract) | The Authentication Agent submits a candidate answer for a question whose *Validate answer via* is set to Webhook |
| [Authentication pre-enter](../authentication/authentication-webhooks#pre-enter-webhook-contract) | Once, when entering the verification step — used to fetch ground-truth context |
The dialog and authentication types share the wizard UI but each authentication type has its own request / response contract — see [Authentication webhooks](../authentication/authentication-webhooks) for the body shapes, signature verification notes, and code samples.
A few rules:
- You can configure **multiple dialog, authentication validation, and authentication pre-enter webhooks** per AI Agent and reference each from any node or auth slot.
- You can configure **at most one** first message, one pre message, and one post message webhook per AI Agent.
- If a first message webhook is not configured, the pre message webhook (if any) is called for the first message instead.
This page covers configuring webhooks in the UI and the differences in their payloads. For implementation, code samples, and the full type reference, see [Build a webhook](./build-a-webhook).
## Set up a webhook
The setup is the same for all types. Navigate to your AI Agent → **Workflows** → **Webhooks** → **+ Create webhook**, pick the type from the three groups (Dialog / Event / Authentication), and fill in the form.
### Required fields
| Field | Description |
| --- | --- |
| Name | A label for the webhook. Must be unique within the AI Agent. |
| URL | The HTTPS endpoint Moveo will `POST` to. Non-HTTPS URLs and loopback or private addresses are rejected in production. |
| Verification token | A secret you choose. Moveo signs every request with HMAC SHA256 using this token, so your endpoint can verify the call originated from Moveo. Treat it like a password. |
| Type | One of dialog, first message, pre message, post message, authentication validation, or authentication pre-enter. |
### Custom headers
You can add up to 10 custom headers that Moveo will include on every call to your endpoint — for example, an API key your backend expects.
:::note Reserved headers
The following headers cannot be set as custom headers:
`Host`, `Connection`, `Content-Length`, `Transfer-Encoding`, `Origin`, `Referer`, `Range`, `Max-Forwards`, `Upgrade`, `TE`, `Trailer`, `X-Forwarded-*`, `Proxy-*`, `Access-Control-*`, `Sec-WebSocket-*`.
:::
There is one Moveo specific custom header you can opt into:
| Header | Effect |
| --- | --- |
| `X-Moveo-Include-History: true` | Adds the conversation history to the webhook payload under a `history` field. |
### Authenticating webhook calls
Anyone who knows your URL could send a `POST` to it. Authentication ensures your endpoint only acts on requests that genuinely came from Moveo.
Moveo signs every request with **HMAC SHA256** of the JSON body, using the verification token as the key. The signature is sent in the `X-Moveo-Signature` header. Your endpoint should recompute the signature and reject the request if it does not match. Code samples for verifying the signature are in [Build a webhook → Verify the signature](./build-a-webhook#verify-the-signature).
If you cannot use HMAC and need to allow list IPs at your network edge instead, Moveo's webhook calls originate from your account region's outbound IP addresses — see [Outbound IP addresses](../platform/outbound-ip-addresses) for the full list per region. IP allow lists are a fallback, not a replacement, because Moveo's egress IPs may change.
### Other options
| Option | Default | Description |
| --- | --- | --- |
| Enabled | On | Disable to stop the webhook from firing without deleting it. |
| Fail on error | Off | If on, a non-2xx response or timeout interrupts the conversation. If off, the agent continues with whatever context it has. |
## Payload differences per type
All four types share a common envelope and add type-specific fields on top. The fields below describe what your endpoint receives in the request body. Full TypeScript types are in [Build a webhook → Type reference](./build-a-webhook#type-reference).
### Common envelope
| Field | Type | Description |
| --- | --- | --- |
| `channel` | string | Channel name (`web`, `whatsapp`, `viber`, etc.) |
| `channel_type` | string | Channel category (e.g. `messaging`, `voice`) |
| `session_id` | string | Conversation session identifier |
| `desk_id` | string | Environment identifier |
| `integration_id` | string | Integration the conversation is happening on |
| `brain_id` | string | AI Agent identifier |
| `lang` | string | Conversation language code |
| `context` | object | All context variables collected so far, including `sys-*` system variables and the `user` object |
| `timestamp` | integer | Unix epoch in milliseconds |
| `history` | array | Optional. Included only when `X-Moveo-Include-History: true` is set as a custom header |
### Dialog webhook
Fires when a dialog node executes a webhook action. Adds:
| Field | Type | Description |
| --- | --- | --- |
| `input` | object | The user input that triggered the node, with `text` |
| `intents` | array | Recognized intents, sorted by confidence |
| `entities` | array | Entities extracted from the input |
| `debug.dialog_stack` | array | The path of dialog nodes leading to this action |
| `user_message_counter` | integer | How many user messages have been processed in the session |
The endpoint can return both context updates and a `responses` array (text, media, carousel, webview, etc.) that the agent delivers to the user.
### First message and pre message webhooks
Fire before the agent processes the user's input. Pre message fires every turn; first message fires only on the first message of a session for a given AI Agent. Adds:
| Field | Type | Description |
| --- | --- | --- |
| `input` | object | The incoming user input, with `text` and `attachments` |
| `business_closed` | boolean | `true` if the conversation is happening outside business hours |
The endpoint can return a `context` update and an `input` object. Use `input.text` to rewrite the user message before the agent sees it, or `input.trigger_node_id` to route straight to a specific dialog node (bypassing intent classification). It cannot reply on the agent's behalf.
```json
{
"channel": "web",
"session_id": "8563dcdf-64ef-4de2-a5ca-b96e0557e4e8",
"desk_id": "d3d08940-f0ef-42e0-993c-1bea065dcqwe",
"integration_id": "",
"brain_id": "d3d08940-f0ef-42e0-993c-1bea065dcqwe",
"lang": "en",
"context": {
"user": {
"user_id": "test-O44vJC-TuXiJXh8hkXvlZ",
"display_name": "Visitor 2020",
"verified": false
},
"sys-channel": "web",
"sys-business": "open",
"sys-user_message_counter": 1
},
"timestamp": 1761045302529,
"input": {
"text": "hi",
"attachments": []
},
"business_closed": false
}
```
### Post message webhook
Fires after the agent has generated its reply, before the reply is delivered to the user. Skipped if the interaction was interrupted mid flight. Adds:
| Field | Type | Description |
| --- | --- | --- |
| `input` | object | The user input that started this turn |
| `intents` | array | Intents recognized for this turn |
| `entities` | array | Entities recognized for this turn |
| `output` | array | The agent's planned reply, as an array of action objects. The set is broader than the responses your endpoint can return — see [agent actions](./build-a-webhook#agent-actions). |
| `debug.dialog_stack` | array | Path of dialog nodes traversed |
| `user_message_counter` | integer | Total user messages in the session |
The endpoint can return a `context` update and, optionally, a `responses` array. If `responses` is present, it replaces the agent's planned reply and is delivered as-is — no templating or context-variable substitution is applied.
## Test your webhook
Each webhook in the UI has a built in tester that sends a real request to your endpoint.
### Simple test
Click **Send test request** to fire a default payload. The right hand panel shows the HTTP status code, execution time, and response body.
### Update context variables from the test
When your endpoint returns context fields, you can click **Update context variables** to register them as known variables in the AI Agent. Once registered, they appear in the auto complete inside dialog nodes and other webhooks.
### Advanced test
The **Advanced test** section lets you edit the request payload before sending — useful for reproducing a specific session's context or trying edge cases.
## Use case examples
The following are the patterns customers use most often. Each one points to a worked implementation in [Build a webhook](./build-a-webhook).
- **Live instructions on session start.** Use a first message or pre message webhook to fetch user data from your CRM and inject it into the conversation as the `live_instructions` context variable. The agent reads it on every turn and personalizes its replies. Worked example: [Live instructions](./build-a-webhook#use-case-live-instructions).
- **Validate user input mid conversation.** Drop a dialog webhook action into a workflow node to check something the user said against your backend before the conversation continues. Update context with the result and branch on it downstream. Worked example: [Validate input](./build-a-webhook#use-case-validate-input).
- **Audit or override the agent's reply.** Use a post message webhook to inspect the agent's planned reply and either log it or replace it. Useful for compliance review and trailing analytics. Worked example: [Post message audit and override](./build-a-webhook#use-case-post-message-audit).
---
## Workflow Generator
The Moveo.ai Workflow Generator is a solution for building task-oriented virtual agents using large language models like [GPT-4](https://en.wikipedia.org/wiki/GPT-4). The main benefit of using the Workflow Generator is its ease of use. Create a dialog by describing the task in plain English.
The Workflow Generator takes care of the rest, automatically generating the necessary code and training data. This saves time and effort compared to traditional methods of building virtual agents. However, it is important to note that the virtual agent generated by the Workflow Generator will require verification and refinement to meet specific requirements and perform optimally.
The Workflow Generator offers a quick and easy way to create a first version of a dialog, complete with necessary intents and entities. This provides a solid foundation for you to make final touches and adjustments to meet your specific needs.
## Use
Create your own dialog using the Workflow Generator by performing the following steps:
1. Create an AI Agent or select an existing one.
2. Go to **Dialogs**, create a new dialog and select **Generate from description**.
3. Describe a task that you want the AI Agent to perform.
4. The AI Agent will come up with a new dialog, intent, and, if needed, one or more entities. Click **Accept** to confirm.
5. Test the AI Agent to check if everything works as intended, and make any changes you need for it to meet your needs.
## Example prompts
Experiment with the Workflow Generator using the following example prompts. Some prompts are straightforward and simple, while others are more complex and may require the AI Agent to ask the user questions and respond according to conditions.
### Simple prompts
#### Provide Contact Details
```
When a user asks about your contact details, tell them that our phone number is +1 4153243324 and our email address is info@company.com.
```
#### Handover to Agent
```
When a user wants to speak to an agent, tell him/her politely that a representative will be with him/her shortly and handover the conversation.
```
#### Show Office Locations
```
When a user asks about where our offices are, give her a carousel with our office locations.
```
#### Display Available Apps
```
When a user wants to download an application from the app store, show him a carousel with all the available apps.
```
#### Share Messenger QR Code and Link
```
When a user wants to talk via Facebook messenger, give him an image with the QR code and a deep link.
```
### Complex prompts
#### Cancel Appointment
```
When a user wants to cancel an appointment, ask for the user's booking id (10 digits) and ask her to confirm the appointment cancellation. If she says yes, then write to a google sheet with the user's booking id. Else, ask the user if you can help with anything else.
```
#### Modify Booking
```
When a user asks for a booking modification, get their 1. name 2. email 3. modification reason and 4. booking code (starts with WH followed by 5 digits). Then send an email to info@company.com with the modification request details and tell the user that we will contact them soon with updates on their request.
```
#### Handle Viber Requests
```
When a user says they want to talk in Viber, check if they are already in Viber. If they are, tell them you can see they are in Viber, otherwise send them a carousel.
```
#### Check Reduced Ticket Eligibility
```
When a user asks if they are eligible for a reduced ticket, ask them if they are in any of these groups: Unemployed, Elderly, Disabled, or Students. If they are Elderly or Disabled, tell them that they are eligible for a reduced ticket by presenting their proper documentation. Else, inform the users that they can issue a reduced fare only if they have their ID on them.
```
#### Report Broken ATM
```
When a user asks you about a broken ATM, get the ATM's location, and ask the user if they want to receive updates for when it will be fixed. If yes, get the user's email and tell them that they will receive updates in their email and write the ATM's location, user's email, and channel to a google sheet. Else, tell the user "Sounds good! Thanks for bringing this to my attention".
```
---
## AI Agent effectiveness
The **AI Agent effectiveness** section shows how well your AI Agent handles conversations.
## Coverage
The **Coverage** chart shows the percentage of conversations where the AI Agent did not trigger the [Unknown](../ai-agents/triggers/unknown.md) node. In this example, 83% of conversations were **covered**, meaning the Unknown node never triggered. Hover over any bar to see the percentage and absolute count.
## Containment
The **Containment** graph shows the percentage of conversations that did not require a live agent handover. Blue bars represent **contained** conversations that concluded without human intervention. Hover over any bar to see the percentage and absolute count.
---
## Customer satisfaction
The **Customer satisfaction** section tracks how happy users are with their interactions, including both AI Agent and live chat conversations.
## Rating
The **Rating by day** graph displays the average or median rating that customers give to sessions
per day.
## Rating percentage of more than three stars
The **Rating percentage of more than three stars** graph shows the percentage of sessions in which
users give a rating of more than three stars (out of a maximum of five) per day.
## Remarks from customers
The **Remarks from customers** table displays all conversations where users left ratings or feedback. Filter by rating to find unhappy users and replay their conversations. See [Logs](logs.md) for details on the replay feature.
---
## Live agent effectiveness
The **Live agent effectiveness** section shows response time statistics for your live agents. Filter by environment or individual agent.
## Live agent responsiveness
The **Live agent responsiveness** graph shows first response time and general response time. Choose between average, median, maximum, or minimum values. Compare data to the previous time period.
## First response time
The **First response time** graph provides data about the first response time to a message. The
_first response time_ is defined as the elapsed time between the user's first message and the
agent's response.
## Response time
The **Response time** graph provides data about the general response time to a message, which is the
time taken for a live agent to reply to a message, without considering if it is the first message.
:::tip
Use the **median** when extreme values are present, and the **average** otherwise.
:::
---
## Insights
## Overview
Insights automatically extract specific, structured information from your conversation history. They
grade 100% of conversations and reveal how your [**AI Agent**](../ai-agents/overview.md) performs at
scale. Instead of sampling a small set of dialogs, you gain a complete picture to track outcomes,
identify issues, and prioritize improvements.
Insights use a large language model (LLM) to interpret each dialog in context and return actionable
results. You can use these results to personalize follow-ups, enrich your CRM, and power analytics.
## Types of insights
Insights include two types: system insights and custom insights.
### System insights
System insights are predefined, high-quality metrics available out of the box. They are tuned for
different AI Agent use cases (for example, debt collection, support, upsell) and provide a reliable
foundation for performance analysis.
- **AI CSAT (customer satisfaction score)**: A score from 1 to 5 estimating user satisfaction based
on the full conversation.
- **Goal achieved**: Indicates whether the AI Agent accomplished its task. Possible values:
`SUCCESS`, `PARTIAL`, `FAIL`.
- **Sentiment**: Indicates how the user feels about the conversation. Possible values: `POSITIVE`
(😊), `NEUTRAL` (😐), `NEGATIVE` (😞).
### Custom insights
Custom insights let you define and extract business-specific data. Each custom insight includes:
- **Name**: A human-readable title (for example, "Promise to pay date").
- **Description**: Clear guidance for the LLM describing the exact information to extract (for
example, "The date the user promises to pay the outstanding balance").
- **Type**: The expected data type:
- **Boolean**: A boolean value (`true` or `false`).
- **Datetime**: A date and time value (for example, `2025-01-01 12:00:00`).
- **String**: A string value (for example, `Has two unpaid invoices`).
- **Integer**: An integer value (for example, `123`).
- **Number**: A number value (for example, `123.45`).
- **Email**: An email address (for example, `john.doe@example.com`).
- **Phone number**: A phone number (for example, `+1234567890`).
- **Categorical**: A string from a predefined list (for example, `willing`, `neutral`,
`unwilling`).
- **Categories**: Required when `type` is `categorical`; provide a list of up to 10 allowed values
(for example, `eager`, `neutral`, `reluctant`).
#### Categorical
This type is similar to `boolean` but instead of just `true` or `false`, it is more nuanced and can
be any of the categories you provide.
For example, if you want to extract the user's willingness to pay, you can set the type to
`categorical` and provide the following categories: `willing`, `neutral`, `unwilling`.
You can define up to 10 categories per categorical insight.
## Insight processing
When a conversation expires, Moveo triggers an extraction job that sends the conversation history to
the insight extractor powered by an LLM. The extractor analyzes the full context and returns values
for both system and custom insights enabled for the AI Agent.
### How to create custom insights
Custom insights are linked to a specific AI Agent. Create them in the AI Agent's settings:
1. Go to **AI Agents**.
2. Select the AI Agent.
3. Open **Review → Logs**.
4. If Insights are disabled, enable the toggle.
5. Click **Create insight**.
6. Enter a name to identify the insight in the **Logs** table.
7. Add a description that guides the LLM on what to extract.
8. Select the data `type`.
9. If the `type` is `categorical`, add the allowed categories.
10. Click **Create**.
### How to view insights
When a conversation expires and Insights are enabled, values appear as a new column in the **Logs**
table. To continue the example from the previous section, we can see how the insight value shows
differently for two different conversations. In the first conversation the user owes more than \$100,
so the insight value is `true`. In the second conversation the user owes less than \$100, so the
insight value is `false`.
:::note
Insight columns appear in the AI Agent's **Logs** table only, not in **Analytics**.
:::
## Related
- [Analytics API overview](/api/analytics/api-overview)
- [Customer satisfaction analytics](./customer-satisfaction.md)
- [Agent effectiveness analytics](./ai-agent-effectiveness.md)
---
## Logs
Logs allow you to replay conversations in the Administrator view, similar to the
[Test](../ai-agents/test.md) experience. When reviewing logs, you can see the predicted intents with
their confidence scores, the [context](../ai-agents/context.md) of the conversation
including variables and user information, and more. You can also use the
[Amend](../ai-agents/test.md#amend) functionality to improve and fine tune the AI Agent's responses.
### Analytics logs
Access conversation logs through the analytics page. This view focuses on overall conversation performance across all agents. Use it to monitor general performance trends.
### AI Agent logs
Access conversation logs through the AI Agent page. This view provides detailed information about conversations for a specific AI Agent, including context data. Use it for debugging and improving individual agent performance.
To extract structured outcomes directly in this view, enable Insights for the AI Agent. See
[Insights](./insights.md) for setup and supported data types.
### Log views comparison
## Filtering options
Filter results by:
- Channel (Web, Viber, and others)
- [Coverage](ai-agent-effectiveness.md#coverage)
- [Containment](ai-agent-effectiveness.md#containment)
- Preview sessions
- Tags
- Ratings
---
## Analytics
## Overview
Analytics help you answer questions such as:
- What was the number of conversations/users per week during the last month?
- How often do customers need to speak to a live agent?
- Which days had the largest or smallest numbers of conversations in the last month?
- What time of day do most users contact my business?
- How fast do my live agents reply to the users?
- Are the users satisfied with the AI Agent? What ratings do they leave?
- Are there questions that the assistant is not trained to answer?
The **Overview** page summarizes interactions between users and your AI Agent. View traffic for a selected time period, the percentage of meaningful conversations, and the most used environments.
Use filters to narrow by date, environment, AI Agent, or channel. Exclude test conversations or filter by minimum message count.
## Meaningful conversations
A conversation is labeled as **meaningful** if either of the following is true:
- **LLM meaningful**: The conversation has at least one covered LLM response.
- **AI Agent meaningful**: After the user's first message, an AI Agent has at least one covered and
contained response.
A session is meaningful when the AI Agent replies successfully at least once after the user's first message. A successful response does not originate from the _Unknown_ flow.
:::note
Conversations in preview environments are considered non-meaningful.
:::
Below are some examples of meaningful and non-meaningful conversations.
### Examples of non-meaningful conversations
```plaintext
--- Conversation Start ---
User: Hi
Assistant: Hi, how can I assist you?
--- Conversation End ---
```
This is classified as a **non-meaningful** conversation, since it contains just one user message.
```plaintext
--- Conversation Start ---
User: Hi
Assistant: Hi, how can I help you?
User: How do I change my credit card number?
Assistant: I'm sorry, I'm not sure how to help you change your credit card number.
User: I want to change the four last digits.
Assistant: I apologize, but I'm not sure how to help you change the four last digits of your credit card.
--- Conversation End ---
```
This is classified as a **non-meaningful** conversation, since, after the user's first message, there are no covered AI Agent responses.
```plaintext
--- Conversation Start ---
User: Hi
Assistant: Hi, how can I help you?
User: I would like to speak to an agent
Assistant: Ok, let me connect you to an agent
--- Conversation End ---
```
This is classified as a **non-meaningful** conversation, since, after the user's first message, there are no contained AI Agent responses.
---
### Examples of meaningful conversations
```plaintext
--- Conversation Start ---
User: Hi
Assistant: Hi, how can I help you?
User: What payment methods do you support?
Assistant: We support Visa, MasterCard and PayPal.
--- Conversation End ---
```
This is classified as a **meaningful** conversation, since, after the user's first message, there is a covered and contained response.
```plaintext
--- Conversation Start ---
User: What steps do I need to follow in order to reset my account?
Assistant (LLM): To reset your account, please follow the step-by-step instructions provided in our account recovery guide.
--- Conversation End ---
```
This is classified as a (LLM) **meaningful** conversation, since it contains an LLM response.
---
## Overall performance
In the **Overall performance** section, you can find useful data to compare live agents and AI
Agents.
## Number of conversations handled
This section displays the number of conversations handled by live agents and AI Agents.
## Response time
Here, you can see the response times for both live agents and AI Agents.
## Rating
This section shows the average or median ratings for live agents and AI Agents, as well as overall
ratings.
## Performance
This section provides information on the performance of live agents and AI Agents.
### Live agent performance
This subsection contains useful information about each live agent.
### AI Agent performance
The **AI Agent performance** table contains similar information to the
[live agents' one](#live-agent-performance), as well as containment and coverage percentages.
---
## Usage
The **Usage** section shows AI Agent activity for a specific time interval. Three graphs display key metrics.
## Counts
The **Counts** graph shows messages, conversations, and customers for the selected time period. Enable comparison to see the previous period as gray bars alongside current data, with percentage changes displayed.
## Messages by time of day
The **Messages by time of day** graph shows message volume during specific time intervals. Use this to identify peak hours. For example, high volume between 10 AM and 2 PM on Wednesdays suggests scheduling live chat coverage during that period. Hover over any cell to see exact counts.
## Conversations per channel
The **Conversations per channel** graph shows conversation distribution across channels. Identify which channels (Web, Facebook, Viber, etc.) users prefer for contacting your AI Agent.
---
## Guidelines and exit conditions
The Authentication Agent's behavior is steered by two free-text fields per step: the **step guideline** (general behavior) and the **failure guideline** (exit conditions). Together they're how you customize tone, script greetings, define alternative scenarios in natural language, and tell the Authentication Agent when to give up and escalate.
## Two kinds of guidelines
| Where you set it | Purpose |
| --- | --- |
| Step card → **Guidelines** link → drawer | The **step guideline** — general instructions to the Authentication Agent for this step: tone, scripted greeting, the natural-language description of any alternative scenarios enabled by your scoring, objection handling, etc. |
| **Failed identification/verification** panel → *Guideline-based* toggle | The **failure guideline** — an exit condition. Describe when the step should be considered failed. The Authentication Agent will end the step with failure if it detects the condition, regardless of how many attempts are left or how much time is on the clock. |
Both are plain prose. The Authentication Agent reads them as instructions and tries to follow them. They are not templates, regexes, or DSLs — write them the way you'd brief a new contact-center agent.
Because the Authentication Agent has [intentionally limited context](./authentication-overview.md#what-the-authentication-agent-can-see), anything you want it to *know* — your tone, the alternative-scenario phrasing, escalation rules — has to be in the guideline. Anything you want it to *not know* — the answers, the scoring config, the validation methods — is automatically out of reach.
## Scripted greeting via the step guideline
When Authentication runs at the start of the session — the usual setup, with the Authentication action sitting on the node selected under [Conversation start](../ai-agents/setup.md#conversation-start) — the Authentication Agent owns the first turn of the conversation. There is **no separate "greeting message"** — the Authentication Agent generates the first message using your step guideline. Write a greeting *into* the guideline to control it.
For example:
> *Greet the user and introduce yourself as David, the AI assistant of Moveo Financial Services.*
>
> *Politely inform the user you need to ask them some questions for authentication purposes. If the user asks questions regarding their account, let them know they need to authenticate first. Also tell them they can ask to speak to a human at any time.*
>
> *After the user gives an answer, repeat it back to them for confirmation before checking if it's valid.*
The guideline shapes:
- The persona and tone ("David, the AI assistant of …")
- Pre-flight disclaimers (the reason for the questions)
- Affordances available to the user during auth (the explicit "you can ask to speak to a human")
- The micro-UX of each question (repeat back for confirmation)
The Authentication Agent is also instructed by the platform — independently of your guideline — to never reveal expected answers, scoring details, or internal configuration. You don't need to add that to your guideline.
## Failure guideline as an exit condition
The failure guideline is the most flexible of the three failure conditions (alongside max attempts and timeout). Use it to **define when the conversation should give up and escalate**, without forcing the user to burn attempts.
Examples:
> *The user asks to speak to a human, or explicitly refuses to authenticate.*
> *The user repeatedly says they don't have the requested information and asks for an alternative the agent cannot offer.*
> *The user provides information indicating they are a third party (e.g. "I'm calling on behalf of my father") and not the account holder.*
When the agent detects the condition described in the failure guideline, it exits the step with failure and routes to the **Trigger node on failure** — typically a [handover](../ai-agents/operations/handover.md) dialog.
The failure guideline combines with **Incorrect responses** and **Authentication timeout** on the same panel. The three are independent — any of them firing ends the step with failure.
## Defining alternative scenarios
Weights and the score threshold are what make an alternative scenario *possible*; the step guideline is what makes it *real*. The agent decides which question(s) to ask based on the guideline — it has no visibility into the math.
A short example tying the two together:
**Weights and threshold:** full tax ID weighted 2 points; last 4 digits of tax ID weighted 1; date of birth weighted 1; score threshold 2.
**Step guideline:**
> *Ask the user for their full tax ID. If they don't have it on hand, accept the last 4 digits of their tax ID together with their date of birth as an alternative.*
The agent will start by asking for the full tax ID; if the user pushes back, the guideline tells it to offer the alternative pair. The scoring config ensures that whichever the user ends up giving, the math works out to ≥ 2 and the step passes.
See [Scoring → Designing alternative scenarios](./authentication-scoring.md#designing-alternative-scenarios) for two more shapes.
## Channel-aware behavior
The agent's response shape adapts to the channel:
- **Voice** — ask one question at a time, keep responses short, spell out numbers and dates.
- **Email** — bundle all questions for the current step into a single message.
- **Chat (default)** — ask one question at a time, keep responses concise.
Your guideline **composes with** these defaults — it does not replace them. If you write *"Ask all the questions at once"* in the guideline for a voice channel, the channel-level rule still applies and the agent will keep asking one at a time. Write the guideline in terms of *what to say* and *what to accept*, and let the channel-level rules handle *how to pace it*.
## Variables in guidelines
Inside a guideline, reference a context variable by wrapping its dollar-prefixed name in double curly braces: `{{$name}}`, `{{$segment}}`. At runtime, the value is substituted in before the Authentication Agent reads the guideline. This is useful for:
- **Personalized greetings** — `Greet {{$name}} by their first name only.` (once you have a `$name` populated — for outbound flows, the [campaign CSV](../campaigns/outreach.md#csv-format-reference) carries a `name` column that becomes available as `$name` in the conversation context).
- **Conditional behavior** — `If {{$segment}} is "premium", acknowledge it once at the start of the conversation.`
Variables resolved into the guideline at runtime become part of what the agent reads. They are not secrets — don't reference ground-truth variables in the guideline (the agent would then know the expected answer).
## Where to next
- [Webhooks](./authentication-webhooks.md) — pre-enter and validation webhooks that populate the context your guideline can reference.
- [Scoring](./authentication-scoring.md) — pairing guidelines with point/threshold math for alternative scenarios.
---
## Authentication overview
**Authentication** verifies the user's identity through a short, conversational question-based flow. It is a **subagent action**: you drag it from the Toolkit into a dialog node, the same way you add a text response or a webhook. When the conversation reaches that node, the auth flow takes over — and only after the user passes (or fails) does the conversation continue to your regular workflow.
Because it's an action, *you* decide where authentication happens. Place it at the start of the session (the most common setup — see [running it at session start](#running-authentication-at-the-start-of-the-session)), or deeper in a workflow so users only authenticate when they reach a sensitive operation.
Once the flow starts, the **Authentication Agent** — an LLM-powered subagent that runs inside the AI Agent's message path — handles the back-and-forth with the user, validates answers against the ground truth you control (variables, exact match, fuzzy match, or a webhook you own), and routes to a dialog node of your choice on success or on failure.
## When to use Authentication
Use Authentication when a workflow is gated on knowing *who* the user is — and getting it wrong is costly.
- **Account access** — looking up a balance, opening a ticket on the user's behalf, changing account settings.
- **Debt collection / financial services** — required identity verification before discussing amounts.
- **Healthcare / insurance** — HIPAA-style scenarios where the user must be identified before any case-specific information is shared.
- **Any flow that contains sensitive customer data** as context variables you don't want to leak to an unauthenticated user.
If you only need *light* identity context (e.g. just look up the user's name from the channel), a dialog webhook ([Dialog webhooks](../ai-agents/action-webhooks.md)) is usually simpler. Reach for Authentication when you need the AI to *converse* through the verification — handling clarifications, multiple acceptable forms of identity, failure paths to human handover, etc.
## The mental model
```mermaid
flowchart LR
A([Conversation reaches the node]) --> C[Identification step]
C -->|score ≥ threshold| D[Verification step]
C -->|fails| F([Failure node])
D -->|score ≥ threshold| S([Success node])
D -->|fails| F
C -.optional.-> D
```
A typical auth flow has two steps. The distinction is easiest to see in terms of where the conversation originates:
- **Identification** — *who do you claim to be?* Used when the conversation is **inbound** and you don't yet know who you're talking to — or whether they're a real customer at all. The user supplies an identifier (an SSN, an account number, a tax ID) that the agent can use to look the rest of them up.
- **Verification** — *prove that you are who we think you are.* Used when you already know who the user should be. Either the conversation is **outbound** (the agent proactively reached out to a known customer), or identification just resolved them against a record. The user supplies a second piece of information (date of birth, last 4 of card, an OTP) that you compare against the record on file.
Either step is optional, but at least one must be enabled. The shape of your flow follows from where the conversation comes from:
- **Inbound** (most common) — both steps. Identification first, then verification.
- **Outbound** — verification only. You already know who you called; you just need to confirm it's actually them.
Both steps pass → the conversation jumps to the **Trigger node on success** you chose.
Either step fails → the conversation jumps to the **Trigger node on failure** (typically a handover or a graceful decline).
## What you'll configure
You add Authentication from the **subagents** group of the Toolkit in the dialog builder — drag the **Authentication** action into a node. The action card renders the whole flow inline; clicking any part of it opens the matching configuration panel.
| In the builder | What it controls |
| --- | --- |
| **Where you place the action** | When the auth flow starts — it runs when the conversation reaches the node containing the action. For session-start auth, pair it with the [**Conversation start** setting](../ai-agents/setup.md#conversation-start). |
| **Identify the user** step | The first step. Asks the user to claim an identity. Optional. |
| **Verify the user** step | The second step. Confirms the identity against your records. Optional. |
| **Trigger node on success** | The dialog node the conversation jumps to once auth passes. |
| **Trigger node on failure** | The dialog node the conversation jumps to once auth fails. |
Each step has its own panels:
| In the builder | What it controls |
| --- | --- |
| Step toggle on the step card | Enables the step. |
| **Add question** / **Choose from a template** | Up to 10 questions per step. Each one has its own answer type, weight, and validation method. |
| **Successful identification/verification** panel → *Score threshold* | Total points needed for the step to pass. See [Scoring](./authentication-scoring.md). |
| **Guidelines** drawer | Free-text instructions to the agent — your tone, your scripted greeting, your offered alternatives. See [Guidelines](./authentication-guidelines.md). |
| **Failed identification/verification** panel | Three independent toggles: *Incorrect responses*, *Guideline-based*, *Authentication timeout*. |
| **Verify the user** step → *Pre-enter webhook* | Optional. Runs a webhook just before verification starts, to fetch ground truth. See [Webhooks](./authentication-webhooks.md). |
For a click-by-click setup walkthrough see [Set up Authentication](./authentication-setup.md).
## Running Authentication at the start of the session
Most authentication use cases need the flow to run **before anything else** — the user must not reach any other part of the workflow unauthenticated. Since Authentication is an action inside a node, you get this with the [**Conversation start** setting](../ai-agents/setup.md#conversation-start):
1. Create a dialog node and drop the **Authentication** action into it.
2. In the AI Agent's **Settings**, set **When a conversation starts, trigger:** to that node.
Every conversation now opens with the auth flow — the Authentication Agent generates the first message itself, shaped by your step [guideline](./authentication-guidelines.md).
## How Authentication changes the message path
While the auth flow is in progress, the Authentication Agent owns the conversation: each user message goes to it — not to intent classification — until the flow ends in success or failure. Then the conversation continues from the configured success or failure node, where the rest of your workflow takes over.
:::note One run per session
The outcome is remembered for the rest of the session. If the conversation reaches an Authentication action again after the user has already passed, the flow does not re-run — the conversation routes straight to the success node (or to the failure node, if the user had failed).
:::
See [How messages flow](../ai-agents/message-path.md) for the wider picture.
## What the Authentication Agent can see
The Authentication Agent has **limited context by design** — the central safety property of Authentication.
| Visible to the Authentication Agent | Hidden from the Authentication Agent |
| --- | --- |
| Question text | Expected answers / ground-truth values |
| Question type (date, number, etc.) | Validation method on each question (exact match, fuzzy match, webhook, …) |
| Your step guideline + failure guideline | Point values, score threshold, and number of failed attempts |
| The conversation so far | Webhook URLs, tokens, headers |
| User's display name (if available from the channel) | Other workflows / dialogs in the AI Agent |
Validation happens **server-side**. The Authentication Agent submits a candidate answer for validation and learns only whether it was accepted — never *why*, never the expected value, never how close it was. Even if the Authentication Agent is prompt-injected, it has no secrets to leak.
## Where to next
- [Set up Authentication](./authentication-setup.md) — step-by-step UI walkthrough.
- [Conversation start](../ai-agents/setup.md#conversation-start) — trigger the auth node at the start of every conversation.
- [Scoring and alternative scenarios](./authentication-scoring.md) — design "any two of three", "strong-or-two-weaker", etc.
- [Guidelines](./authentication-guidelines.md) — scripted greetings, escalation, channel awareness.
- [Webhooks](./authentication-webhooks.md) — pre-enter and per-question validation webhooks, with a worked CRM-backed two-step recipe.
---
## Scoring and alternative scenarios
Authentication uses a simple per-step scoring model: every question has a **point weight**, the step has a **score threshold**, and the step passes when the user's accumulated points meet the threshold. The clever uses come from how you combine weights, threshold, and the step's [guideline](./authentication-guidelines.md) — that combination is how you design "any two of three", "strong-or-two-weaker", or "all required" flows.
## Per-question points
Every question has a weight between **1 and 5** (default: 1). When the user gives an answer that the configured validation method accepts, the question's points are added to the step's running score. A question can be accepted at most once per step.
You set this on each question with the **Assign a weight for this question** control:
> *Set how many points this specific question contributes toward the total success score.*
## Score threshold
On each step's **Successful identification** (or **Successful verification**) panel, the **Score threshold** is the minimum total points the user needs to pass:
> *The minimum total points from correct answers needed to pass this step.*
If the threshold is higher than the sum of all weights on the step, the panel shows a warning — *"Threshold exceeds the total available points."* — meaning the step would be impossible to pass. Adjust either the weights or the threshold.
## Designing alternative scenarios
This is where scoring earns its keep.
:::tip Scoring is the gate; the guideline is how the agent offers the choice.
The auth LLM **does not see** point values or thresholds — it only sees the questions and the step guideline you wrote. To make an alternative scenario real, you have to do two things:
1. Configure points + threshold so the math allows the alternative.
2. Describe the alternative *in plain language* in the step guideline so the agent knows to offer it.
Without the guideline, the agent will just ask the questions in order and never offer the alternative. Without the math, the agent's offer would be a lie — the user would think they'd passed and the step wouldn't actually advance.
:::
Three worked examples:
### Strict identification — "all required"
| Question | Points |
| --- | --- |
| Full tax ID | 1 |
| Date of birth | 1 |
| Registered phone number | 1 |
**Threshold:** 3 (all three required).
**Step guideline:**
> *Ask the user for their full tax ID, their date of birth, and their registered phone number. All three are required.*
The agent will ask all three and only pass when all three are accepted.
### Pick any two — "user's choice"
| Question | Points |
| --- | --- |
| Full tax ID | 1 |
| Date of birth | 1 |
| Registered phone number | 1 |
**Threshold:** 2.
**Step guideline:**
> *Ask the user to confirm any two of the following: their full tax ID, their date of birth, or their registered phone number. The user can choose which two to provide.*
The agent will keep accepting answers until any two are correct. The user picks which two.
### Strong or two weaker
| Question | Points |
| --- | --- |
| Full tax ID | 2 |
| Last 4 digits of tax ID | 1 |
| Date of birth | 1 |
**Threshold:** 2.
| User provides… | Score | Passes? |
| --- | --- | --- |
| Full tax ID alone | 2 | Yes — 2 ≥ 2 |
| Last 4 + DOB | 1 + 1 = 2 | Yes — 2 ≥ 2 |
| Last 4 alone | 1 | No — 1 < 2 |
| DOB alone | 1 | No — 1 < 2 |
**Step guideline:**
> *Ask the user for their full tax ID. If they don't have it on hand, accept the last 4 digits of their tax ID together with their date of birth as an alternative.*
This is the canonical "strong primary identifier with a fallback path" shape.
:::note If the agent isn't behaving as expected
Nine times out of ten the issue is the **guideline**, not the scoring. If you set a threshold of 2 but never described the alternative in the guideline, the agent will just walk through all three questions in order. Adjust the wording in the guideline first.
:::
## How a step fails
A step has three independent terminal failure conditions. Any one of them ends the step with failure and routes the conversation to the failure node.
| Condition | Where you set it | Default when enabled |
| --- | --- | --- |
| **Max failed attempts** | Failure panel → *Incorrect responses* | 3 |
| **Step timeout** | Failure panel → *Authentication timeout* | 5 minutes |
| **Failure guideline** | Failure panel → *Guideline-based* | — (free text) |
The failure guideline is the most flexible of the three: it's a free-text description of when the step should be considered failed. The agent reads it, watches the conversation, and exits with failure when it judges the condition is met.
A common pattern is to use the failure guideline as an **escalation hook**:
> *The user asks to speak to a human, or explicitly refuses to authenticate.*
When detected, the conversation routes immediately to a handover node, instead of forcing the user to fail attempts until they hit the max-attempts limit. See [Failure guideline as an exit condition](./authentication-guidelines.md#failure-guideline-as-an-exit-condition).
## What happens after success and failure
Once a step reaches its threshold (success) or fires one of the failure conditions (failure):
- **Success on the last enabled step** → the conversation continues from the **Trigger node on success** you configured.
- **Success on identification when verification is also enabled** → the agent moves to the verification step.
- **Failure on any step** → the conversation continues from the **Trigger node on failure** you configured.
The two node selectors appear on the success and failure panels of the **last enabled step** (verification if it's on, otherwise identification).
## Where to next
- [Guidelines](./authentication-guidelines.md) — how to write the step guideline and the failure guideline.
- [Webhooks](./authentication-webhooks.md) — validation webhooks and pre-enter webhooks for fetching ground truth.
---
## Set up Authentication
This page walks through the **Authentication** action in the dialog builder, panel by panel. By the end you will have a working two-step auth flow that runs at the start of every conversation on a test AI Agent.
For a worked end-to-end example showing how scoring, guidelines, and webhooks fit together, see [the CRM-backed two-step recipe](./authentication-webhooks.md#putting-it-together-a-crm-backed-two-step-setup).
## 1. Add the Authentication action to a node
Open a dialog in your AI Agent (**Workflows** → **Dialogs**). In the **Toolkit** on the right, find the **subagents** group and drag **Authentication** into the node where you want the auth flow to run.
Where you place it is when it runs: the flow starts when the conversation reaches that node. To run it at the start of every session — the most common setup — see [step 9](#9-run-it-at-the-start-of-the-conversation).
## 2. The action card at a glance
The action card shows the whole auth flow inline: the **Identify the user** and **Verify the user** steps, each with its success and failure outcomes. Click any part of the card to open its configuration panel on the right. The rest of this walkthrough goes panel by panel.
## 3. Enable the identification step
The identification step asks the user to **claim** an identity ("what is your account number?"). It's the natural starting point for **inbound** conversations, where you don't yet know who's on the line. For outbound conversations — where the agent proactively reached out to a known customer — skip identification and use only verification (step 7). For more on the distinction see [the mental model](./authentication-overview.md#the-mental-model).
Toggle the **Identify the user** card on. Its panel opens with an empty state and two ways to add questions:
- **Choose from a template** — pre-built questions from three categories (Primary identifiers, Contact verification, Account & Transactional KBA).
- **Add first question** — start from scratch.
## 4. Configure a question
Each question expands into a form with up to seven fields. Some fields are conditional on the validation method.
| Field | Purpose |
| --- | --- |
| **Question** | The text the agent will ask the user. Required, max 256 chars. |
| **Answer type** | One of `Text`, `Date`, `Integer`, `Number`, `Phone`, `Alphanumeric`. Affects how the agent extracts the value. |
| **Save correct answer as** | The context variable to store the accepted answer in (e.g. `$ssn`). Must start with a letter or underscore. |
| **Assign a weight for this question** | 1–5 points. Defaults to 1. See [Scoring](./authentication-scoring.md). |
| **Validate answer via** | How to check the answer. Three subgroups: Operator, Guideline, Webhook. |
| **Ground truth** *(conditional)* | The variable holding the right answer (for `Exact match`, `Fuzzy match`, `Contains`, `Starts with`, `Ends with`). |
| **Fuzzy match threshold** *(conditional)* | 0–100 similarity score. Defaults to 90. |
| **Validation guideline** *(conditional)* | Free-text rule shown only when *Validate answer via* is set to **Guideline**. |
### Validation methods
- **Operator** — server-side string comparison against a context variable: `Exact match`, `Fuzzy match`, `Contains`, `Starts with`, `Ends with`.
- **Guideline** — a free-text instruction that's used to judge the answer (e.g. *"Accept if the user gives any valid US ZIP code."*).
- **Webhook** — calls a webhook of type `auth_validation` configured on this AI Agent. Only validation-typed webhooks are listed in the dropdown. See [Webhooks](./authentication-webhooks.md).
### Max ten questions per step
The **Add another question** button is disabled at ten questions per step. If you need more degrees of identification, split the work across the identification and verification steps.
## 5. Score threshold (success panel)
Click the **Successful identification** box on the action card to open the success panel.
The **Score threshold** is the minimum total points needed for the step to pass:
> *The minimum total points from correct answers needed to pass this step.*
If your questions sum to 4 points and you set the threshold to 5, you'll see a warning: *"Threshold exceeds the total available points."* — the step would never be able to pass. Adjust either the question weights or the threshold.
Threshold and weights together give you alternative-scenario design. See [Scoring](./authentication-scoring.md).
## 6. Failure conditions
Click the **Failed identification** box to open the failure panel.
Three independent failure conditions:
- **Incorrect responses** — *"End the authentication flow if the user provides the wrong information too many times."* Defaults to 3 attempts when enabled.
- **Guideline-based** — *"Describe the failure conditions"* in free text. The agent will exit the step with failure if the condition is met (e.g. *"The user asks to speak to a human."*). See [Guidelines as exit conditions](./authentication-guidelines.md#failure-guideline-as-an-exit-condition).
- **Authentication timeout** — caps the wall-clock time the user has to complete the step. Defaults to 5 minutes; options are 1, 3, 5, 10, 15, 30, or 60 minutes.
Any one of the three firing routes the conversation to the failure node.
## 7. Enable the verification step (optional)
The verification step asks the user to **prove** an identity you already think you know — either because identification just resolved them against a record, or because the conversation is outbound and you contacted a specific customer.
It has the same shape as identification, with one extra control at the top: a **Pre-enter webhook** dropdown.
The tooltip explains it:
> *Runs just before the verification step starts. Use this to fetch the ground truth data needed to validate the user's answers.*
A common pattern: identification asks for an SSN, validated via webhook against your CRM; once identification passes, the pre-enter webhook fetches the matching name and date of birth into the conversation context; verification then asks for those and validates them with **Exact match** / **Fuzzy match** against the freshly populated context variables.
The pre-enter webhook only exists on the verification step. The dropdown only lists webhooks of type `auth_pre_enter` — create one in **Workflows → Webhooks** under the *Authentication webhooks* group. See [Webhooks](./authentication-webhooks.md#pre-enter-webhook-contract).
## 8. Trigger node on success / failure
On the **last enabled step** (identification if you didn't enable verification; otherwise verification), the success and failure panels each include a node selector.
- **Trigger node on success** — *"When authentication succeeds, the conversation will continue to this node."*
- **Trigger node on failure** — *"When authentication fails, the conversation will continue to this node."*
Both fields autocomplete against the dialog nodes in your AI Agent.
Common patterns:
- Success → a dialog node that greets the now-verified user by name and proceeds with the actual task.
- Failure → a handover node that escalates to a human, or a graceful-decline dialog.
## 9. Run it at the start of the conversation
Most use cases need authentication to be the very first thing in the session. In the AI Agent's **Settings**, set [**When a conversation starts, trigger:**](../ai-agents/setup.md#conversation-start) to the node containing your Authentication action.
Every conversation now opens with the auth flow — the Authentication Agent generates the first message itself, shaped by your step guideline (step 10).
## 10. Guidelines
Below each step's question list there's a small **Guidelines** link. Click it to open the guidelines drawer.
The drawer header reads **Authentication Guidelines**, with the description:
> *Configure how the agent should handle common objections and respond during authentication.*
The editor supports:
- `/` for commands (lists, headings, etc.)
- The dollar prefix (e.g. `$user.name`) for context variables
This is where you script the greeting, define alternative scenarios in natural language, and tell the agent how to handle common objections. See [Guidelines](./authentication-guidelines.md).
## 11. Test in Try It
Open the **Try It** panel and start a conversation. While auth is running, an Authentication card appears in the panel showing the current step, status, score, attempts, and the list of variables successfully extracted.
You can deep-link from the Try It panel back to a specific question in the configuration to inspect or fix it.
---
## Authentication webhooks
Authentication uses webhooks for two distinct roles. Each role has its own dedicated webhook type — **Authentication pre-enter** and **Authentication validation** — that you pick in the wizard when creating the webhook. The Authentication setup dropdowns only list webhooks of the matching type, so you can't accidentally point a dialog-action webhook at an auth slot.
| Role | Webhook type | Where you select it in the console | When it fires | What it returns |
| --- | --- | --- | --- | --- |
| **Pre-enter webhook** | `auth_pre_enter` | On the **Verify the user** step, the *Pre-enter webhook* dropdown | Once, when entering the verification step | Context updates to use as ground truth |
| **Validation webhook** | `auth_validation` | On any question, by setting *Validate answer via* to **Webhook** | Every time the agent submits a candidate answer for that question | A boolean accept / reject |
Pre-enter and validation are independent — you can use either, both, or neither. The most common production setup uses both: a validation webhook gates identification, then a pre-enter webhook fetches CRM data so verification can validate against it.
You can create as many `auth_validation` and `auth_pre_enter` webhooks per AI Agent as you need — typically one validation webhook per question, and one pre-enter webhook for the verification step.
:::note Shared webhook plumbing
The HTTPS request shape, signature verification, custom headers, retries, and fail-on-error semantics work exactly like other Moveo webhooks. This page documents the **auth-specific** request and response bodies. For everything else, see [Build a webhook](../ai-agents/build-a-webhook.md) and [Webhooks](../ai-agents/webhooks.md).
:::
## Pre-enter webhook contract
Available **only on the verification step**. The Pre-enter webhook lets you fetch data once — typically from your CRM — so the verification questions can validate against it.
### When it fires
Once, on the first turn after the verification step is entered. It does not re-fire on subsequent turns within the same step. If the pre-enter webhook fails (timeout, non-2xx response, malformed body), the auth flow exits with a system failure and routes to the configured failure node — the verification step never starts.
### Request
`POST` with JSON body:
```json
{
"request_id": "uuid",
"session_id": "uuid",
"context": { "/* all current context vars */": "..." }
}
```
`context` is the full set of variables collected so far, including any captured during identification (e.g. `$ssn`, `$account_number`).
### Response
```json
{
"output": {
"name": "Maria Papadopoulou",
"dob": "1980-04-12"
}
}
```
Every key/value in `output` is merged into the conversation context. The returned variables become available as `$name`, `$dob`, etc. — and can be referenced as the **Ground truth** for the verification questions (e.g. *"Validate answer via Fuzzy match against `$name`"*).
### Example
A pre-enter webhook that looks up a CRM record by SSN and returns the matching `name` and `dob`. The example below uses Next.js App Router and Zod; the same pattern applies to any HTTP framework.
```ts title="app/api/fetch-crm-data/route.ts"
const bodySchema = z.object({
request_id: z.string().optional(),
session_id: z.string().optional(),
context: z.object({
ssn: z.string().min(1, 'context.ssn is required'),
}),
});
export const POST = async (req: Request): Promise => {
const body = bodySchema.parse(await req.json());
// Look up the CRM record by SSN. Replace with your own data source.
const row = await lookupCrmRow(body.context.ssn);
return NextResponse.json({ output: row });
// row shape: { name: string, dob: string } | null
};
```
```py title="fetch_crm_data.py"
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Context(BaseModel):
ssn: str
class Body(BaseModel):
request_id: str | None = None
session_id: str | None = None
context: Context
@app.post("/api/fetch-crm-data")
async def fetch_crm_data(body: Body) -> dict:
row = lookup_crm_row(body.context.ssn) # -> {"name": str, "dob": str} | None
return {"output": row}
```
If the SSN doesn't resolve to a CRM record, return `{ "output": null }` (or omit the ground-truth keys). The verification step will then fail every question that depends on them.
## Validation webhook contract
Available **per question** when you set *Validate answer via* to **Webhook**. Use it when the right-answer check can't be expressed as a string operator against a context variable.
### When it fires
Every time the agent submits a candidate answer for the question. The same webhook may be called multiple times in one step (if the user gives a wrong answer and tries again, that's a new call) and across both steps if you configure validation webhooks on both.
### Request
`POST` with JSON body:
```json
{
"request_id": "uuid",
"session_id": "uuid",
"value": "123-45-6789",
"context": { "/* all current context vars */": "..." }
}
```
- `value` is the candidate answer extracted by the agent — already normalized to the question's `type` (e.g. for a `date` question, an ISO-formatted string).
- `context` is the full set of variables collected so far. Use this if the validation depends on more than just the candidate value (e.g. validating an OTP against a previously sent one stored in `$otp_token`).
### Response
```json
{ "valid": true }
```
…or `{ "valid": false }`. There is no third state; missing or malformed `valid` is treated as a system error.
The Authentication Agent learns only the boolean. It does not learn *why* an answer was rejected. This is intentional — see [What the Authentication Agent can see](./authentication-overview.md#what-the-authentication-agent-can-see).
### Example
A validation webhook that checks whether the SSN the user provided exists in a Google Sheet.
```ts title="app/api/identify-ssn/route.ts"
const bodySchema = z.object({
value: z.string().min(1, 'value is required'),
request_id: z.string().optional(),
session_id: z.string().optional(),
context: z.record(z.string(), z.unknown()).optional(),
});
export const POST = async (req: Request): Promise => {
const { value } = bodySchema.parse(await req.json());
// Replace with your own check against your source of truth.
const valid = await ssnExists(value);
return NextResponse.json({ valid });
};
```
```py title="identify_ssn.py"
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Body(BaseModel):
value: str
request_id: str | None = None
session_id: str | None = None
context: dict | None = None
@app.post("/api/identify-ssn")
async def identify_ssn(body: Body) -> dict:
valid = ssn_exists(body.value) # -> bool
return {"valid": valid}
```
## Signature verification
Authentication webhooks use the **same HMAC-SHA256 signature scheme** as every other Moveo webhook. The signature is in the `X-Moveo-Signature` header; the secret is the verification token you configured on the webhook in the UI.
See [Build a webhook → Verify the signature](../ai-agents/build-a-webhook.md#verify-the-signature) for the full pattern with Node.js and Python examples.
:::caution The examples on this page skip signature verification
The minimal examples on this page omit signature verification for brevity. **Production webhooks must always verify the signature** to confirm the request actually came from Moveo and wasn't tampered with.
:::
## Creating an authentication webhook
Open the AI Agent → **Workflows** → **Webhooks** → **+ Create webhook**. The type selector groups webhooks into three categories — pick from the **Authentication webhooks** group:
- **Authentication validation** — validates a user's answer to an authentication question.
- **Authentication pre-enter** — runs before an authentication step to fetch ground truth values.
Then fill in the standard webhook form (name, URL, verification token, optional custom headers — see [Webhooks](../ai-agents/webhooks.md)). The wizard's Test panel shows the expected response shape for the type you picked, so you can build your endpoint against the right contract from the start.
## Selecting a webhook in the console
Once you've created the webhook, it becomes selectable on the **Authentication action** in exactly one place, determined by its type:
- **Validation webhooks** (`auth_validation`) — appear on each question, when *Validate answer via* is set to **Webhook**.
- **Pre-enter webhooks** (`auth_pre_enter`) — appear in the *Pre-enter webhook* dropdown on the **Verify the user** step.
The dropdowns are strictly filtered: only webhooks of the matching type are listed. Dialog-action webhooks and event webhooks (first/pre/post message) are never offered for auth slots.
## Deploying your webhook
Both webhooks just need a public HTTPS endpoint. The platform you deploy on is up to you — Vercel, Cloudflare Workers, AWS Lambda behind API Gateway, or your own infrastructure all work. The only constraint is that the endpoint must be reachable from Moveo's servers and respond within the webhook timeout.
A typical workflow:
1. Implement and deploy the endpoint.
2. In the webhook wizard, pick **Authentication validation** or **Authentication pre-enter** under the *Authentication webhooks* group, then fill in URL, verification token, and any custom headers — see [Webhooks](../ai-agents/webhooks.md).
3. Select it on the **Authentication action**: on a question for a validation webhook, or on the verification step's *Pre-enter webhook* dropdown for a pre-enter webhook. Each dropdown is filtered to its matching type.
4. Test end-to-end in the Try It panel.
## Type reference
Copy-paste-ready TypeScript types.
```ts title="auth-webhooks.types.ts"
// Pre-enter webhook
export type AuthPreEnterRequest = {
request_id: string;
session_id: string;
context: Record;
};
export type AuthPreEnterResponse = {
output: Record | null;
};
// Validation webhook
export type AuthValidationRequest = {
request_id: string;
session_id: string;
value: string;
context: Record;
};
export type AuthValidationResponse = {
valid: boolean;
};
```
## Putting it together: a CRM-backed two-step setup
The canonical real-world setup. Use this when your identifying credential (an SSN, a passport number) lives in a CRM and the rest of the user's record needs to come from the same source.
**On the AI Agent's Webhooks page**, configure two webhooks:
| Webhook | Type | Role | Returns |
| --- | --- | --- | --- |
| **Identify SSN** | `auth_validation` | Validation webhook for the identification question | `{ "valid": true }` or `{ "valid": false }` |
| **Fetch CRM data** | `auth_pre_enter` | Pre-enter webhook for the verification step | `{ "output": { "name": "...", "dob": "..." } }` |
**On the Authentication action** (in a dialog node — see [Setup](./authentication-setup.md)), configure both steps:
- **Identify the user** — enabled.
- One question: *"What is your Social Security number?"* (**Number**, weighted 1, saved as `ssn`).
- *Validate answer via* → **Webhook** → **Identify SSN**.
- *Score threshold* on **Successful identification**: 1.
- The **Guidelines** drawer carries the persona and compliance disclaimer the Authentication Agent will deliver on its first turn (the Authentication Agent owns the first turn — see [Guidelines → Scripted greeting](./authentication-guidelines.md#scripted-greeting-via-the-step-guideline)). The drawer also tells the user explicitly that they can ask to speak to a human at any time.
- On **Failed identification**, enable *Guideline-based* with the exit condition *"The user asks to speak to a human."* — that catches the affordance you just promised.
- Enable *Incorrect responses* (max 2) and *Authentication timeout* (5 minutes) as belt-and-braces.
- **Verify the user** — enabled.
- *Pre-enter webhook* → **Fetch CRM data**.
- Two questions:
- *"What is your full legal name?"* — **Text**, *Validate answer via* **Fuzzy match** against `$name`, threshold 95.
- *"What is your date of birth?"* — **Date**, *Validate answer via* **Exact match** against `$dob`.
- *Score threshold* on **Successful verification**: 2 (both required).
- **Trigger node on success** → a verified-customer dialog that picks up `$name` in its greeting.
- **Trigger node on failure** → a handover dialog.
**In the AI Agent's Settings**, under [Conversation start](../ai-agents/setup.md#conversation-start), set **When a conversation starts, trigger:** to the node holding the Authentication action, so the auth flow runs before anything else in the session.
### What happens at runtime
1. The conversation starts at the auth node — regardless of the user's first message. The Authentication Agent delivers the scripted greeting from the identification guideline and asks for the SSN.
2. The user answers. The agent submits the SSN to the **Identify SSN** webhook. The webhook returns `{ "valid": true }` if the SSN exists in the CRM, otherwise `{ "valid": false }`.
3. Once identification passes, the **Fetch CRM data** pre-enter webhook fires. It looks up the user record and returns `{ "output": { "name": "...", "dob": "..." } }`. Those become available as `$name` and `$dob`.
4. Verification asks for the user's full legal name and date of birth, validating each against the freshly-loaded ground truth.
5. Both accepted → the success node fires, and the next dialog can greet the user by `$name`.
6. At any point during identification, if the user says *"speak to a human"* (or similar), the failure guideline fires and the conversation routes immediately to the handover dialog — no need to burn through attempts.
Both webhooks can be backed by anything that exposes the data — a CRM API, a Google Sheet with `name`, `ssn`, `dob` columns, an internal microservice. The contract the brain cares about is just the JSON shapes documented above.
## Where to next
- [Build a webhook](../ai-agents/build-a-webhook.md) — generic signature verification, body validation, type reference.
- [Webhooks](../ai-agents/webhooks.md) — configuring URL, verification token, and custom headers on the AI Agent.
---
## Campaigns
## Overview
Campaigns reach your audience across multiple channels and route every reply to an [AI Agent](../ai-agents/overview.md). Upload a contact list, define how the agent engages each person, then track results from one place.
Moveo offers two campaign types. Both share the same foundation — an audience, an AI Agent, and multi-channel messaging — but serve different goals.
## Campaign types
### Outreach
Proactive engagement for marketing and lifecycle messaging, such as promotions, reminders, and re-engagement. An outreach campaign sends a primary message, retries with a fallback if delivery fails, and follows up when a contact stays silent.
See [Outreach campaigns](./outreach.md).
### Payment recovery
Regulated debt collection that contacts people with overdue balances and works toward a resolution, such as a promise to pay or a completed payment. Payment recovery captures debt details per contact and, with autonomous actions, runs under a compliance profile.
See [Payment recovery campaigns](./payment-recovery.md).
## How a campaign works
Every campaign shares the same building blocks, regardless of type:
- **Audience** — Upload a CSV of contacts. The platform previews each row and flags issues, such as missing contact details or duplicates.
- **AI Agent** — Choose the [AI Agent](../ai-agents/overview.md) that handles replies. The dropdown lists the latest published versions.
- **Tags** — The campaign name generates a matching tag for filtering conversations. Add more tags for reporting or routing.
- **Message journey** — Define how contacts are reached, either as a fixed sequence or with [autonomous actions](#autonomous-actions).
- **Scheduling** — Send immediately or schedule a future launch with date, time, and timezone.
- **Tracking** — Follow campaign status, subscriber activity, and message logs after launch.
## Autonomous actions
Autonomous actions let the AI Agent decide the best next action for each contact, instead of following a fixed message sequence. When enabled, the campaign becomes *agentic*: the agent chooses the channel, message, and timing per person to work toward a goal you define.
Autonomous actions is a capability you turn on during campaign setup, under the **AI capabilities** section. It applies to both campaign types.
### Standard versus autonomous
| Aspect | Standard campaign | Autonomous actions |
| ------------ | ----------------------------------- | -------------------------------- |
| Message flow | Fixed: primary, fallback, follow-up | Chosen per contact by the agent |
| Channel | Set per step | Selected by the agent |
| Timing | Fixed delays | Adapts to contact behavior |
| Goal | Not required | Required |
### Setting a goal
When autonomous actions is on, a **Goal** is required. It defines what a successful conversation achieves. How you set it depends on the campaign type:
- **Outreach** — Enter the goal as free text, such as booking a demo or confirming an appointment.
- **Payment recovery** — Select a goal from the dropdown, such as securing a promise to pay or completing a payment. A [compliance profile](#compliance-profiles) is also required.
:::note
The goal guides the agent's decisions for every contact. Keep it to a single, measurable outcome.
:::
### Availability
Autonomous actions is rolling out gradually. If you do not see the **AI capabilities** section in campaign setup, contact your account manager or [support](mailto:support@moveo.ai).
## Compliance profiles
A compliance profile is part of the autonomous agent. When you enable [autonomous actions](#autonomous-actions) on a payment recovery campaign, you select a compliance profile that applies protections respecting legal restrictions, such as quiet hours, frequency caps, and stop-contact requests. Outreach campaigns do not use compliance profiles.
See [Compliance profiles](../ai-agents/compliance-profiles.md) for the available profiles and the rules each one enforces.
## Choose a campaign type
- Reach your audience with marketing or lifecycle messaging → [Outreach campaigns](./outreach.md)
- Recover overdue payments under regulatory rules → [Payment recovery campaigns](./payment-recovery.md)
---
## Outreach campaigns
## Overview
An outreach campaign proactively reaches your audience for marketing and lifecycle messaging, such as promotions, reminders, and re-engagement. It is one of two campaign types, alongside [Payment recovery](./payment-recovery.md). For shared concepts, see the [Campaigns overview](./campaigns.md).
Upload an audience list, define the messages each person receives, and configure fallback behavior for failed deliveries or silent contacts. Every campaign tags its conversations and routes replies to your selected [AI Agent](../ai-agents/overview.md).
## Before you start
- Prepare a CSV file with at least one `phone` or `email` column. Add extra columns (such as `name`, `plan`, or `appointment_date`) to personalize messages.
- Confirm that your integrations are connected and active: [WhatsApp](../integrations/whatsapp.md), [Infobip SMS](../integrations/infobip-sms.md), [Telnyx Voice](../integrations/telnyx-voice.md), [Twilio Voice](../integrations/twilio-voice.md), or email.
- Choose which [AI Agent](../ai-agents/overview.md) handles replies. You select it during setup.
## Step 1 - Set up the campaign
1. Go to **Campaigns** and click **+ Create**.
2. Select **Outreach** as the campaign type.
3. Enter the campaign name. The system generates a matching tag from this name for filtering conversations. Add additional tags for reporting or routing as needed.
4. Pick the [AI Agent](../ai-agents/overview.md) that manages replies. The dropdown lists the latest published versions.
5. Upload your CSV or use **Quick add** to create contacts manually.
- To see the expected format, click **Download sample file** for a ready-made template.
- The table previews every row and highlights issues (missing phones, emails, or duplicates).
- Fix or remove flagged rows, then re-upload so the audience shows only valid recipients.
6. Review the audience summary panel to confirm contact count, available phones and emails, and reusable custom fields.
### Turn on autonomous actions (optional)
Under **AI capabilities**, turn on **Autonomous actions** to let the agent decide the best next action for each contact. When enabled, a **Goal** is required — for outreach, enter it as free text, such as booking a demo. The agent then composes and sequences messages toward that goal instead of following the fixed journey below. See [Autonomous actions](./campaigns.md#autonomous-actions).
### CSV format reference
Each row must follow these rules:
- Include at least one contact method (`phone` or `email`). Rows missing both are rejected.
- Provide clean, one-value-per-cell entries. Avoid merged columns or notes inside the same field.
- Keep contact identifiers unique. Remove duplicates to avoid verification errors.
- Add helper columns to personalize messages. During the build step, you can insert these fields as variables.
| email | phone | name | appointment_date |
| ----------------- | ------------- | ----------- | ---------------- |
| alex@example.com | +12025550101 | Alex Doe | 2024-09-12 |
| jamie@example.net | +442071838750 | Jamie Shaw | 2024-09-13 |
| priya@example.in | +122233344555 | Priya Singh | 2024-09-15 |
After the upload, the audience table flags rows that fail validation so you can correct them before moving on.
## Step 2 - Build the message journey
The builder walks you through three stages: the starting message, fallback options for failed deliveries, and follow-up messages for silent contacts.
:::note
This fixed journey applies to standard outreach. With [autonomous actions](./campaigns.md#autonomous-actions) enabled, the agent decides the journey per contact instead.
:::
### Primary message
1. Choose the integration for the first message.
2. Compose your message in the editor. For **WhatsApp**, use the template placeholders and variables dropdown to fill fields with CSV data. For **Infobip SMS**, type `$` to open the variable picker and insert any column.
3. Preview the result on the right to verify formatting, variables, and branding.
### Fallback when delivery fails
Toggle **Send a fallback if not delivered** to configure a backup plan:
1. Select a second integration and write the fallback message.
2. The campaign sends this fallback if the first message fails. If a contact lacks the required information (for example, no phone number for SMS), they skip that fallback and proceed to the next step.
### Follow up when there's no reply
Enable **Follow up if there is no response** to nudge silent contacts:
1. Choose how long to wait. The dropdown offers day-based delays (1–7 days) to match your follow-up cadence.
2. Select the integration and compose the follow-up content, just as you did for the primary step.
3. If the contact replies at any point, the timer stops and the follow-up does not send. If no reply arrives, the message delivers once at the scheduled time.
:::note
Email integration is in alpha and may not appear in your account.
:::
### Tips
- Switch between the primary, fallback, and follow-up sections to preview the recipient's journey.
- The default tag from the campaign name stays in place. Add more tags to trigger automations or segment reports.
- Move backward to the setup step at any time to update the audience or replace the AI Agent before launching.
## Step 3 - Review and launch
The review screen summarizes everything you configured:
- **Audience**: Total contacts, available phone numbers, available emails, and a quick look at the custom fields detected in your CSV.
- **Messaging flow**: A snapshot of the primary message, any delivery fallback, and the no-reply follow-up so you can double-check tone and sequencing.
- **Automation settings**: The [AI Agent](../ai-agents/overview.md) handling replies and the tags applied to resulting conversations.
- **Scheduling**: In the **Start** dropdown, choose **Immediately** to launch as soon as you confirm, or **Schedule for later** to set a date, time, and timezone. Scheduled campaigns stay in the queue until the start time you specify.
When everything looks right, click **Review and start**. A confirmation modal opens; click **Start campaign** to launch. You can also **Save and Exit** at any point; drafts remain in the Campaigns list until you return.
## How fallbacks behave
- **Delivery issues**: If a primary message bounces, the campaign routes that contact to the configured fallback. Each contact tries fallbacks in order. Steps that lack required data (missing contact details) are skipped.
- **No-response timers**: The platform schedules a follow-up after the primary message delivers. Replies cancel the timer. If no reply arrives before the delay ends, the follow-up sends once.
- **Campaign completion**: Each contact's progress updates in real time as they finish the journey. Once all contacts complete, the campaign status changes to "Sent".
## After launch
- Track campaign status from the Campaigns list. Click any campaign to open its progress view, subscriber activity, and message logs.
- Use filters in the list or reporting tabs to group conversations by campaign tag.
- To reuse the audience, download the CSV from the campaign or copy contacts into another workflow.
- [Payment recovery campaigns](./payment-recovery.md) also get a [Performance tab](./performance.md) with recovery and call metrics. Outreach campaigns do not.
## Troubleshooting
Check campaign logs for error codes when messages fail to deliver. For WhatsApp-specific errors, see the official [error codes page](https://developers.facebook.com/docs/whatsapp/cloud-api/support/error-codes/).
### Common issue: Error **131026 - Message Undeliverable**
Possible reasons include:
- The recipient’s number is not registered on WhatsApp.
- The recipient has not accepted the latest Terms of Service or Privacy Policy.
- The recipient is using an outdated version of WhatsApp.
- The recipient has blocked or reported your business.
- Per-user marketing message limits have been reached to maintain quality.
- The recipient has not come online within the 30-day offline message window.
- The recipient is in a
[restricted or sanctioned country](https://developers.facebook.com/docs/whatsapp/cloud-api/support/#country-restrictions).
- You are sending an
[authentication template](https://developers.facebook.com/docs/whatsapp/business-management-api/authentication-templates)
to an Indian user (+91).
## Additional resources
- [WhatsApp Cloud API Support](https://developers.facebook.com/docs/whatsapp/cloud-api/support/#message-not-delivered)
- [Related Bug Report](https://developers.facebook.com/support/bugs/994815942105900/)
---
## Payment recovery campaigns
## Overview
A payment recovery campaign contacts people with overdue balances and works toward a resolution, such as a promise to pay or a completed payment. It is one of two campaign types, alongside [Outreach](./outreach.md). For shared concepts, see the [Campaigns overview](./campaigns.md).
Payment recovery pairs an audience of debtors with an AI Agent that follows up, sends reminders, and adapts its messaging per contact. When you enable [autonomous actions](./campaigns.md#autonomous-actions), the agent decides the best next step for each person instead of following a fixed message sequence. A [compliance profile](../ai-agents/compliance-profiles.md) keeps that contact within the rules that apply to your region.
## Key concepts
- **Campaign type** — Payment recovery is a dedicated type built for regulated debt collection. It captures debt details per contact for reporting and for the AI Agent to act on.
- **AI Agent** — A [Debt Collection agent](../ai-agents/overview.md) handles replies, negotiates options, and generates payment links. Build one first with the [Build your first AI Agent](../guides/build-an-ai-agent.md) guide.
- **Autonomous actions** — An optional capability that lets the agent choose the channel, message, and timing for each contact. See [Autonomous actions](./campaigns.md#autonomous-actions).
- **Compliance profile** — A set of protections that block or delay contact when regulations require it. You select one when autonomous actions is enabled. See [Compliance profiles](../ai-agents/compliance-profiles.md).
## Before you start
- Build and publish a [Debt Collection AI Agent](../guides/build-an-ai-agent.md) to handle replies.
- Confirm that your messaging [integrations](../integrations/whatsapp.md) are connected and active.
- Prepare a CSV of debtors with the required debt fields. See [CSV format reference](#csv-format-reference).
- If you plan to use autonomous actions, decide which [compliance profile](../ai-agents/compliance-profiles.md) applies.
## Step 1 - Set up the campaign
1. Go to **Campaigns** and click **+ Create**.
2. Select **Payment recovery** as the campaign type.
3. Enter the campaign name. The system generates a matching tag from this name for filtering conversations. Add more tags for reporting or routing as needed.
4. Upload your CSV. Click **Download sample file** to get a template with the required debt columns. The audience table previews every row and flags issues, such as missing contact details or unmapped required fields.
5. Match each CSV column to a field. The platform suggests mappings automatically; adjust any that are wrong.
:::note
If a required field stays unmapped, the setup step keeps the warning active until you map it. Optional fields can be skipped.
:::
### Turn on autonomous actions
Under **AI capabilities**, turn on **Autonomous actions** to let the agent decide the best next action for each contact. When enabled:
- A **Goal** is required. Select it from the dropdown — it defines what a successful conversation achieves, such as securing a promise to pay or completing a payment.
- A **Compliance profile** is required. It applies the contact rules for your region, such as quiet hours, frequency caps, and stop-contact requests.
- The agent uses next-best-action logic to pick the channel and message per contact, rather than a fixed sequence.
For the full behavior and how it differs from a standard campaign, see [Autonomous actions](./campaigns.md#autonomous-actions).
## Step 2 - Build the message journey
The messaging step depends on whether autonomous actions is on:
- **Autonomous actions on** — Choose the channels the agent may use, then write the initial message. The **Campaign guidelines** panel lists the read-only rules that shape how the agent sequences its attempts. The agent picks the channel, message, and timing per contact, and uses only the channels that contact has.
- **Autonomous actions off** — Build a fixed journey: a primary message, a fallback for failed deliveries, and a follow-up for silent contacts, as described for [Outreach campaigns](./outreach.md#step-2---build-the-message-journey).
## Step 3 - Review and launch
The review screen summarizes the audience, messaging, and scheduling. The layout adapts to the campaign:
- **Agentic review** — Shows the goal, the AI Agent, and the compliance profile that governs contact.
- **Standard review** — Shows the primary message, delivery fallback, and no-reply follow-up.
In the **Start** dropdown, choose **Immediately** to launch as soon as you confirm, or **Schedule for later** to set a date, time, and timezone. Click **Review and start** to open the confirmation modal, then **Start campaign** to launch. Click **Save and Exit** to keep the campaign as a draft.
## CSV format reference
Each row represents one debtor. Map every required field during setup.
The required fields do more than identify each debtor. They power payment-recovery-specific analytics, such as the total amount due across your audience. When [autonomous actions](./campaigns.md#autonomous-actions) is enabled, the AI Agent also uses the amount and currency to personalize messages and decide the next best action. The optional due date and original creditor add further context to those messages when you provide them.
**Required fields**
| Field | Description |
| ------------------ | -------------------------------------------------------- |
| Consumer full name | Full name of the debtor |
| Contact | At least one of `phone` or `email` |
| Amount | Outstanding balance |
| Currency | Currency of the balance |
| Country code | Two-letter ISO country code for the debtor, such as `US` |
| Residence state | Used to apply state-level compliance rules |
**Optional fields**
| Field | Description |
| ----------------- | ------------------------------------- |
| Account ID | Unique identifier for the account |
| Due date | Date the balance became due |
| Original creditor | The creditor the debt originated with |
:::caution
Provide clean, one-value-per-cell entries and keep account identifiers unique. Rows missing both a phone and an email are rejected.
:::
## Compliance and safety
When autonomous actions is enabled, a payment recovery campaign runs under a [compliance profile](../ai-agents/compliance-profiles.md) that enforces contact rules for your region, such as quiet hours, frequency caps, and stop-contact requests. During live conversations, the AI Agent applies further guardrails, such as stopping collection when a consumer disputes the debt or reports identity theft.
:::warning
Compliance protections take precedence over custom instructions and guidelines. Compliance profiles assist with regulatory compliance but are not a substitute for legal counsel.
:::
## After launch
- Track campaign status from the Campaigns list. Open a campaign to view subscriber activity and message logs.
- Read the recovery, promise, and call metrics on the [Performance tab](./performance.md).
- Review blocked contacts and their reasons on the Performance tab, under **Barriers to progress**.
- Filter conversations by the campaign tag for reporting.
## Related pages
- [Campaign performance](./performance.md)
- [Campaigns overview](./campaigns.md)
- [Outreach campaigns](./outreach.md)
- [Autonomous actions](./campaigns.md#autonomous-actions)
- [Compliance profiles](../ai-agents/compliance-profiles.md)
- [Build your first AI Agent](../guides/build-an-ai-agent.md)
---
## Campaign performance
## Overview
The **Performance** tab reports how a [payment recovery campaign](./payment-recovery.md) is doing: how many people you reached, how many were verified as the debtor, how much they promised to pay, and what is holding the campaign back. For outbound voice campaigns it also shows how long the calls run.
Open a campaign from the **Campaigns** list, then select **Performance**. The tab sits between **Overview** and **Conversations**.
:::note Availability
Only payment recovery campaigns have a Performance tab. [Outreach campaigns](./outreach.md) do not, because the metrics below are built on debts, promises to pay, and verified-debtor checks. If a payment recovery campaign has no Performance tab, the feature is not enabled for your account yet. Contact your Moveo representative.
:::
Every number covers the whole campaign since it started. There is no date filter on the tab. The call duration chart is the one exception: it reaches back 189 days.
A metric shows `—` when it cannot be calculated, most often because its denominator is zero. That is not the same as `0`, which means the value was measured and came out at zero.
## Campaign results
Five tiles summarizing the money and the commitments.
| Tile | What it counts |
| ----------------------------- | ------------------------------------------------------------------------------------ |
| Debt amount | Total outstanding balance across every debt linked to the campaign |
| Total promised amount | Total amount promised across the campaign |
| PPA | Average promised amount, across the promises that carry an amount |
| PTP | People who committed to pay |
| Debts with a promise to pay | Debts covered by a promise |
**PTP** counts people and **Debts with a promise to pay** counts debts, so they differ whenever one person owes on more than one account.
**Total promised amount** also shows the share of the total debt that has been promised, with a progress bar underneath. The bar stops at full when a campaign promises more than the debt on file, but the percentage next to it keeps climbing past 100%.
Amounts use the campaign's own currency, taken from the audience you uploaded. When no currency can be found, the tile shows a bare number with the caption **campaign currency**.
## Outreach conversion
A four-stage funnel, with a conversion rate on each step between stages.
| Stage | What it counts |
| ----------------- | ---------------------------------------------------------------------------------- |
| Attempts | People the campaign tried to reach, counting sent, failed, and replied |
| Responded | People who replied |
| Verified debtors | People who replied and were confirmed as the debtor |
| Promised | People who committed to pay |
Each rate compares a stage with the one directly above it, not with **Attempts**:
- **Hit rate** — Responded ÷ Attempts
- **RPC rate** — Verified debtors ÷ Responded
- **Conversion** — Promised ÷ Verified debtors
Rates are rounded to a whole percentage. A stage counts a person once, however many messages or channels the campaign used to reach them, and a failed delivery still counts as an attempt.
## Promises over time
Two running totals across the life of the campaign, one in debts and one in money.
- **Cumulative PTP count** — promises to pay, adding up day by day
- **Cumulative promised amount** — the money behind those promises, in the campaign currency
Days with no activity are carried forward flat rather than dropping to zero. Hover any point for the exact value on that date; the axis labels round large numbers for readability.
The amount chart is empty more often than the count chart, because a promise can be recorded without an amount attached. When that happens the chart is replaced by the message **No promise has an amount attached yet.**
## Barriers to progress
What is stopping the campaign, split into two groups.
- **Disputes** — Disputed debts, the count of debts marked as disputed, and Dispute rate, the share of verified debtors who disputed a debt. The rate is a share of verified debtors, not of everyone contacted.
- **Campaign exclusions** — Stopped subscribers, the people the campaign no longer contacts. A contact is stopped by an opt-out, by a [compliance profile](../ai-agents/compliance-profiles.md) rule, or by reaching the end of their journey.
## Call duration
Only outbound voice campaigns fill this chart. It covers calls on the voice channels (Twilio, Telnyx, and web voice), splits them into four fixed length ranges, and shows each range as a share of all answered calls. The card is on every payment recovery campaign, so a campaign that does not place calls shows the empty state instead.
| Range | Call length |
| -------- | ---------------------- |
| `<30s` | Under 30 seconds |
| `30–60s` | 30 seconds to 1 minute |
| `1–2m` | 1 to 2 minutes |
| `≥2m` | 2 minutes and over |
All four ranges always appear, including any that hold no calls.
A range starts at its lower bound and stops just short of the next one. A call of exactly 30 seconds is in `30–60s`, and a call of 29.9 seconds is in `<30s`. The last range starts at exactly 2 minutes, so a 2-minute call sits there.
Each bar is that range's share of all answered calls, worked out on its own. The four are never adjusted to total 100. Three equal ranges come out at 33.33% each, which adds up to 99.99%. On top of that the bars round to whole numbers, so they can read 99% or 101%. A range that holds calls but less than 1% of them shows `<1%` instead of `0%`.
**Answered means the other end sent something back.** It is not a confirmed pickup from the phone carrier. A call that went to voicemail counts as answered, because the AI Agent plays its opener to the machine and the recorded greeting comes back as a message. Voicemail cannot be separated out yet.
Dials that rang out, failed, or were rejected are left out. Most dials on a voice campaign end that way and last under a second, so counting them would push almost the whole chart into the first range. The chart tells you how long your conversations run. It does not tell you how often people pick up.
Duration runs from the start of the conversation, when the campaign places the call, to the last message in it. It stops at the last message rather than when the conversation closes, because a voice conversation stays open for minutes after the call ends and counting that wait would make every call look longer. This is Moveo's own measure and will not match a carrier's billed duration exactly.
The chart reaches back 189 days, so older calls drop out. When a campaign has no answered calls yet, the chart is replaced by **No data available** and **No answered calls have been recorded for this campaign yet.**
## When numbers appear
- Recovery metrics, the funnel, and the promise charts refresh within about five minutes of the underlying activity.
- A call joins the duration chart only after its conversation closes, which is about ten minutes after the last message on it. Accounts set to hold conversations open for longer take more than that.
- Today's chart is always incomplete while a campaign is still dialing. It keeps changing for about ten minutes after each call ends, and for the same day it will not match the voice conversation counts on the Analytics pages, which do not wait for a conversation to close. The two agree once the conversations close.
If the whole tab fails to load it shows **Something went wrong** with a **Reload** button.
## Related pages
- [Payment recovery campaigns](./payment-recovery.md)
- [Campaigns overview](/docs/campaigns/)
- [Compliance profiles](../ai-agents/compliance-profiles.md)
- [Outreach campaigns](./outreach.md)
---
## Views
When handling a large volume of conversations with [human agents](overview.md), you may find it
helpful to use **views** to organize and filter your conversations. Views allow you to segment
conversations based on specific conditions and criteria.
Similar to [rule conditions](../environments/rules.md#apply-the-condition), views filter
conversations by their properties. Each view is associated with a specific
[environment](../environments/overview.md), meaning views created in one environment are not visible in
others.
## Conditions
Conditions help you filter conversations based on particular properties. Besides the standard
conditions shared with [rules](../environments/rules.md#apply-the-condition), views also offer a
unique condition:
### Conversation status
- **Open**: Conversations that have an active session which hasn't expired. These can still be
answered by a human agent.
- **Closed**: Conversations that can no longer receive messages. A conversation is closed when its
status is `resolved`, `expired`, or `closed by the user`.
- **Missed**: A conversation is marked as missed when it's closed without receiving responses from
either an [AI Agent](../ai-agents/overview.md) or a [Human Agent](human-agents.md). Typically,
these conversations expire without being addressed.
## Create a view
Follow these steps to create a view:
1. Navigate to **Live chat**.
2. Hover over the **Views** tab in the left sidebar.
3. Click on the **+** icon.
4. Provide a **name** and select an **emoji** for the view.
5. Choose if the view should be **public** or **private**.
6. Under the **Conditions** section, specify conditions to filter conversations.
7. Click on **Create** to finalize your new view.
---
## Departments
## Introduction
Departments in your environment allow for a more structured and efficient management of
conversations by categorizing teams based on their specific functions, such as Support, Sales, etc.
This feature enhances the organization and allocation of conversations to the most appropriate
agents, ensuring a smoother workflow and better customer service.
## Create a department
To utilize departments, they must be added to your environment. This allows you to segment your
teams based on their specific roles or functions. Go to your environment, then navigate to
**Departments** and click on **Create department**.
### Configuration
- Name
- [Assignment modes](#assignment-modes)
- Members
### Add agents to department
Assign agents to specific departments. This ensures that agents receive conversations that
are most relevant to their area of expertise.
1. Go to the department settings.
2. Select the department you want to manage.
3. Add agents to the department by selecting from your team list.
### Assignment modes
Departments can operate under different assignment modes to distribute conversations among agents.
These modes are designed to enhance efficiency and ensure fair distribution of workload.
1. **Manual Assignment**: Agents or supervisors manually assign conversations to specific agents
within a department.
2. **Balanced Assignment**: The system automatically assigns conversations to agents based on their
current workload, ensuring a balanced distribution.
3. **Round Robin**: Conversations are assigned to agents in a cyclical manner, ensuring each agent
receives an equal number of conversations over time.
Set a limit for how many conversations can be automatically assigned to agents by
changing the default number in the [environment settings](../environments/overview.md).
## Connect the department
To activate the newly created department, click **Connect**. This navigates you to the rules
section. Select the rule you want to modify or create a new rule, and add the option to "Assign
department".
To assign the department when the AI Agent hands over a conversation, use a rule with the **After
the AI agent replies** trigger and a **Tag** condition. See
[Route a handover to a department](../environments/rules.md#route-a-handover-to-a-department).
---
## Human agents
In Moveo, a conversation can be handled by an [AI Agent](../ai-agents/overview.md) or a human agent.
When a conversation is out of scope for the AI Agent and requires human intervention, a person can
step in and continue the conversation.
A single Moveo account can have multiple human agents. They are users who have been
[invited to the account](../platform/invitations.md) and have at least one of the following roles:
- **Chat Agent**
- **Chat Manager**
- **Admin**
- **Owner**
:::warning
Inviting team members to the account might incur **additional costs**. Please refer to
the [pricing page](https://moveo.ai/pricing) for more information.
:::
## Conversation assignment
When a conversation is assigned to a human agent, they start receiving notifications about it.
On the user's side, depending on the channel, they may see a notification indicating that a human
agent has joined the conversation.
There are several ways a conversation can be assigned to a human agent. Below is a brief description
of each method:
### 1. Sending a message
If an agent sends a message in an ongoing conversation, that conversation will be assigned to the
agent who sent the message—regardless of the agent currently assigned.
### 2. Reassigning a conversation
Agents can manually reassign a conversation to another human agent, including themselves.
### 3. Handover action
This method involves the use of [departments](./departments.md). When a
[handover action](../ai-agents/operations/handover.md) is triggered in a
[dialog](../ai-agents/dialogs.md), the AI Agent leaves the conversation, making it unassigned. After
this, two scenarios can occur:
- **No department assigned**: This is the default behavior. The conversation remains unassigned
until an agent manually picks it up.
- **Department assigned** ([Learn how to use departments](./departments.md)): If a department is
assigned, the system will automatically assign the conversation to a **connected** human agent who
belongs to **that** department. The criteria for selecting the agent depend on the
[department settings](./departments.md#assignment-modes).
Think of this process as the department assigning the conversation, while the handover
action removes the AI Agent from it.
---
## Notes
Notes let [live agents](human-agents.md) add private annotations to conversations. They are **only
visible to teammates** — end users never see them. Use notes to leave context, reminders, or
observations about a conversation for yourself or other agents.
## Add a note
To add a note to an open conversation:
1. Click on the **Note** icon (sticky note) in the chat box toolbar.
2. The chat box switches to note mode, showing a yellow header labeled **Note · only visible to
teammates**.
3. Type your note and press **Enter** or click **Add** to post it.
The note editor stays open after posting, so you can write multiple notes in a row. Press **Escape**
or click the **X** button in the header to exit note mode.
:::note
While in note mode, other toolbar actions like [quick responses](quick-responses.md), file
attachments, and emoji are disabled. Exit note mode first to use these features.
:::
## Edit a note
To edit a note you previously created:
1. Hover over the note in the conversation timeline.
2. Click the **edit** (pencil) icon that appears.
3. The note editor opens with the existing text. Make your changes and press **Enter** to save.
Edited notes display an **(edited)** label next to the timestamp. Only the original author of a
note can edit it.
## Delete a note
To delete a note you previously created:
1. Hover over the note in the conversation timeline.
2. Click the **delete** (trash) icon that appears.
3. Confirm the deletion in the popover that appears.
Once deleted, a note cannot be recovered. Only the original author of a note can delete it.
:::note
Notes support up to **2,048 characters**. Use **Shift + Enter** to add line breaks within a note.
:::
---
## Live chat overview
## Overview
Live chat in Moveo creates a seamless bridge between AI automation and human expertise. When your
[AI Agent](../ai-agents/overview.md) encounters complex inquiries or reaches its designed handover
points, human agents can step in to provide personalized customer support while maintaining full
conversation context.
This unified approach ensures customers receive the best possible experience—instant AI responses
for routine queries and expert human assistance for complex issues—all within a single, continuous
conversation.
### Key capabilities
✅ **Unified conversation management** across all
[integrated channels](../integrations/overview.md)\
✅ **Seamless AI-to-human handover** with full context preservation\
✅ **Department-based routing** for specialized support teams\
✅ **Real-time collaboration tools** and productivity features\
✅ **Queue management** with intelligent wait time estimation\
✅ **Business hours support** with automatic scheduling
---
## Getting started
### Enable live chat
Each [environment](../environments/overview.md) can have live chat enabled or disabled based on your
needs:
1. Navigate to your environment settings
2. Toggle the live chat module to **Active**
3. Configure your [human agents](human-agents.md) and [departments](departments.md)
### Essential setup steps
1. **[Add human agents](human-agents.md)** - Invite team members with appropriate roles
2. **[Create departments](departments.md)** - Organize agents by function (Support, Sales, etc.)
3. **[Configure routing](routing-and-queues.md)** - Set up automatic conversation assignment
4. **[Set business hours](../environments/business-hours.md)** - Define when each department is available
5. **[Setup handover triggers](../ai-agents/operations/handover.md)** - Configure when AI escalates
to humans
---
## How it works
Live agents can view all ongoing conversations in a single view by clicking on the live chat icon at
the top of the screen.
The live chat page is divided into distinct categories on the left side of the screen:
- **`My Inbox`**: Displays all conversations that you are handling.
- **`All`**: Displays all conversations from all live agents or AI Agents.
- **`Unassigned`**: Displays all conversations that **no** live agent has picked up. These are the
conversations in which the end user is waiting for a live agent to take over.
- **`Spam`**: Displays all conversations that have been flagged as spam.
- **`Trash`**: Displays all conversations that have been deleted.
In live chat, you can see the conversations managed by the assistant, as well as the individual
conversations handled by each agent.
Upon navigating there, you have the option to pin any agents and departments of your choice for easy
viewing in the list.
## Actions
A live agent can take the following actions:
1. Reply to a conversation after selecting it from the left side of the screen.
:::note
When you reply to a conversation, you automatically assign it to yourself. For example, if you send a
message to a conversation that an AI Agent is handling, then the AI Agent leaves the conversation
and the conversation gets assigned to you.
:::
2. Attach a file and send it in a conversation.
3. Create and edit a [quick response](quick-responses.md).
4. Add a private [note](notes.md) to a conversation, visible only to teammates.
5. Send a [template message](template-messages.md) on WhatsApp.
6. Resolve a conversation after you solve the user's request.
7. Assign the conversation to another live agent.
8. Update the user's information (name, email, address, phone number) by using the right section of
the screen.
9. Tag a conversation.
10. Flag a conversation as **spam** or delete it.
The following demonstration shows how a new conversation appears in **Unassigned** and how a live
agent can pick up the conversation and resolve it.
---
## Quick responses
'@site/src/components/Img';
Quick responses let live agents reply to users quickly without having to type messages from scratch.
They are useful when you frequently need to provide the same answer or handle common questions.
## Create a new quick response
To create a new quick response in an open conversation:
1. Click on the **Quick responses** icon in the bottom-left corner of the chat box.
2. Click on **+ Create new response**.
3. Customize your response.
4. Click **Save**.
## Use a quick response
A live agent can type / in the chat box to search for existing quick responses. To select
a quick response, navigate with the arrow keys and press **Enter**. You can also type keywords to
directly locate a particular response.
## Edit a quick response
To edit a quick response in an open conversation:
1. Click on the **Quick responses** icon in the bottom-left corner of the chat box.
2. Click **Edit** on the quick response you want to modify.
3. Make your changes, then save.
To remove a quick response, click the delete icon 🗑️ next to it.
## Troubleshooting
Below are some common questions about using quick responses:
1. **Can I use quick responses across multiple chats at the same time?**\
Yes. Quick responses are accessible in any open conversation, so they can be reused across different
chats.
2. **Is there a limit to how many quick responses I can create?**\
While there’s typically no fixed limit, creating too many can make them difficult to manage.
3. **Do all agents see my quick responses, or can I keep them private?**\
This depends on your system settings. Some setups allow personal quick responses, while others share
them organization-wide.
4. **Can I edit a quick response while chatting with a customer?**\
Absolutely. You can edit or delete a quick response anytime by clicking the Quick responses icon.
5. **Are changes to quick responses immediate for other agents?**\
If the quick response is shared, changes are available to all agents right after you save.
6. **Is there a faster way to insert a quick response than typing "/"?**\
Currently, typing "/" opens the selector. Check settings or documentation to see if your system offers
additional shortcuts.
7. **How can I organize my quick responses so they are easier to find?**\
Use clear, descriptive labels or keywords. This makes searching for them more efficient.
8. **Can I include images or emojis in a quick response?**\
Yes, you can include these elements if your chat supports them. Make sure any images are properly
hosted or referenced.
9. **Will quick responses work offline?**\
They rely on the system being online, so a stable connection is typically required for access.
10. **What if I accidentally delete a quick response?**\
Once deleted, a quick response can’t be recovered. Confirm before deleting, or maintain a backup
if needed.
---
## Conversation routing and queues
Moveo’s **AI Agent** handles most conversations from start to finish. When the AI Agent decides a
human is the best next step, the handover—and everything around it, from queueing to assignment to
wait time—is automatic and instant. Customers stay informed with clear, real-time wait time
estimates throughout.
## A simple way to think about it
Imagine a busy office lobby. A skilled receptionist (your AI Agent) greets each visitor, answers
most questions on the spot, and only calls a colleague when needed. When a human is invited, the
receptionist directs the visitor to the right department and knows in real time who is available and
who has room to help. New visitors are served fairly and quickly, while those waiting see honest
time estimates. That is how Moveo routes conversations—automatically and instantly.
## How queues keep things organized
Most conversations are resolved by the **AI Agent**. When it chooses to involve a human,
conversations don’t pile up in one place. Moveo organizes them into department queues so the right
people see the right requests.
**Departments act as separate queues.** For example, `Sales`, `Technical Support`, and `Billing`
each have their own queue, agents, and rules. See [departments](./departments.md).
Moveo assigns the right department using configurable routing rules. You define the logic once, and
conversations are directed automatically based on context or an **AI Agent** handover action. See
[rules](../environments/rules.md) and the [handover action](../ai-agents/operations/handover.md).
**Business hours are respected.** Each department can set its own schedule. Outside of those hours,
the queue pauses, customers are informed, and routing resumes automatically when the department
reopens. See [business hours](../environments/business-hours.md).
**Handovers are smooth.** When the **AI Agent** escalates via the
[handover action](../ai-agents/operations/handover.md) or an agent transfers a conversation, it
enters the correct department queue automatically.
## The smart router: how chats are assigned
When a conversation is in an active queue, Moveo immediately looks for the best agent at that
moment. It checks three things, in order:
1. **Right department match.** Only agents in the conversation’s department are considered.
2. **Real availability.** The system confirms an agent is truly ready: they are connected and
present, their status is **Available** (not **Away** or **Busy**), and they are active at their
desk. If an agent is idle for too long, Moveo can mark them **Away** to avoid routing to an empty
chair.
3. **Capacity and workload.** Each agent has a maximum number of live conversations they can handle
at once (commonly five). Moveo assigns new conversations only to agents who have room, which
prevents overload and protects quality.
### Fair and flexible assignment strategies
Different organizations prefer different ways to distribute work, and each department can choose
what fits best in **Settings → Departments**: **Manual** (assigned by a user with the **Chat
Manager** role; see [permissions](../platform/permissions.md)), **Round robin** (distributes evenly,
like dealing cards), or **Balanced** (assigns to the available agent with the lightest workload to
keep workloads even).
## What your customers see
Customers always know what is happening. As soon as someone is assigned, the chat shows the agent’s
name and profile, a “joined the conversation” note appears, and messages are clearly labeled. While
waiting, customers see clear, real-time estimates that update automatically. If an agent signs off
or becomes unavailable, the system immediately finds the next best fit or keeps the customer
informed. This experience works across all channels, though the visual presentation may differ by
channel, and in some cases there is no visual presentation at all. See the
[integrations overview](../integrations/overview.md).
:::note
This screenshot is from the Web Widget. Other channels may display differently, but routing
and wait time behavior are the same.
:::
## A typical customer journey
1. **Customer starts a conversation.** The **AI Agent** answers questions, collects details, and can
take actions. When the best next step is a human, it sends the conversation to the right
department using your routing rules and the
[handover action](../ai-agents/operations/handover.md). See [rules](../environments/rules.md).
2. **Conversation enters the queue.** The correct department queue picks it up. If the department is
closed, the customer sees a clear message and a time estimate for when the department reopens.
3. **The human agent department gets to work.** Moveo checks who is truly available and who has
capacity.
4. **Assignment happens instantly.** The best agent is assigned. The customer sees the agent’s name
and avatar; the agent sees the full history.
5. **If things change, customers stay informed.** If the assigned agent goes unavailable, Moveo
re-routes or updates the wait time.
6. **Conversation completes.** Managers can review performance in analytics, including wait times
and agent utilization.
## Key settings you can control
- **Departments and membership:** Decide who works where and which conversations reach them. See
[departments](./departments.md).
- **Business hours per department:** Set working schedules and holiday closures. See
[business hours](../environments/business-hours.md).
- **Routing strategy:** Configure in **Settings → Departments**: **Round robin**, **Balanced**, or
**Manual** (assigned by a user with the **Chat Manager** role; see
[permissions](../platform/permissions.md)).
- **Agent capacity:** Define how many simultaneous conversations each agent can handle (for example,
`5` for a standard desk, `2` for a specialized department).
- **Analytics & staffing:** Track average and peak wait times, queue length, agent utilization, and
traffic patterns to improve staffing and SLAs. See
[human agent effectiveness](../analytics/human-agent-effectiveness.md).
---
## Scheduled WhatsApp messages
Schedule an approved WhatsApp template to send at a later time, directly from a live chat
conversation. Use scheduled messages for follow-ups such as payment reminders, due-date
notices, or check-ins, without returning to the conversation to send each one by hand.
Scheduling reuses the same approved templates you send today. To learn how to create and send
templates, see [WhatsApp template message](./template-messages).
## Requirements
Scheduled messages appear in a conversation only when all of these are true:
- The scheduled messages feature is enabled for your account. Contact your Moveo representative
to enable it.
- The conversation channel is WhatsApp.
- The conversation is open (not resolved).
- An approved WhatsApp template is attached, or the conversation already has pending scheduled
messages.
## Schedule a message
1. Open the WhatsApp conversation you want to follow up on.
2. Attach an approved template. Click **Browse** in the banner, select the template, and fill in
any parameters. The template attaches to the composer as a draft chip instead of sending.
3. Click the schedule button (the calendar-clock icon) between the microphone and **Send**.
4. Choose when to send:
- **Preset** — select **In 30 minutes**, **In 1 hour**, **Tomorrow 9 AM**, or
**Next Monday 9 AM**. The message is scheduled immediately.
- **Custom** — select **Custom…**, then pick a date, time, and timezone. Click **Schedule
message** to confirm.
A confirmation appears once the message is scheduled, and the draft chip clears from the
composer.
:::note Scheduling window
You can schedule a message between 30 seconds and 14 days from now. Times outside this range
are rejected.
:::
## Timezone
The custom picker uses your local timezone by default. Change it if the customer follows a
different timezone. The system stores the exact fire time, so the message sends at the moment
you picked regardless of who views the conversation.
## View and cancel scheduled messages
A green dot on the schedule button indicates that the conversation has pending scheduled
messages. Click the button and open the scheduled messages list to review them. Each card shows
the template preview and the scheduled send time.
To cancel a pending message, click **Cancel** on its card. Cancel a message any time before it
starts sending.
:::caution Messages already sending cannot be cancelled
Once a scheduled message begins sending, it can no longer be cancelled.
:::
## Automatic cancellation
If the customer replies before a scheduled message sends, the platform automatically cancels the
pending messages for that conversation. This prevents sending a reminder to a customer who has
already responded.
## Limits
- Each conversation has a limit on the number of pending scheduled messages. When you reach it,
cancel a pending message before scheduling another.
- You cannot resolve a conversation that has pending scheduled messages. Cancel them first, or
wait until they send.
---
## WhatsApp Template Message
Send messages to users even after 24 hours have passed since their last message on
WhatsApp. First, create and approve a template in your
[WhatsApp Business](https://business.facebook.com/wa/manage/message-templates) account. Once
approved, you can use it directly in the live chat.
## Create a WhatsApp template
1. Go to your WhatsApp Business account and create a new template.
2. Submit the template for approval.
3. Once approved, the template becomes available for selection in the live chat UI.
## Send a WhatsApp template in live chat
1. Open the conversation you want to continue.
2. Click on the **Browse** button in the banner.
3. Select the approved template from the list.
4. Fill in any parameters (if applicable) and click **Send**.
---
## Business hours
Business hours allow you to set a specific time range during which your live chat agents are
available.
## Navigate to business hours
Click on the profile configuration button inside the profile's dropdown menu, choose your desired
environment from the environments menu, and click on the **Business hours** tab.
:::note
By default, the business hours are set to Weekdays 9:00 AM - 5:00 PM.
:::
## Customize your default business hours
- Navigate to the default business hours page by clicking on the button. You can change various
settings, such as the timezone, frequency (every day, weekends, weekdays, or specific day), and
start and end time. You can also add or remove business hours by clicking the respective buttons.
## Customize your holiday hours
Add holidays to your business hours. The days registered as holidays are treated
as non-business hours.
1. Click on the Holidays tab and click on the `add holidays` link.
2. Edit the name of the holiday.
3. Edit the start and end date of the holiday.
4. Add or remove holidays at will by clicking on the **+** or **-** buttons respectively.
## Add custom business hours
Add custom business hours by clicking the **+ Add business hours** button. The procedure is
the same as [the one for the default business hours](#customize-your-default-business-hours), with
the addition of an editable name.
## Use business hours in the dialog
A simple example that takes advantage of business hours is to use them in the dialog. Upon creating
a new condition, you can use the business hours variable, `$sys-business`. View a simple dialog flow
below.
## Use business hours in rules
Business hours work inside [rules](./rules.md). Create a rule and customize it
accordingly. In the following image, an example shows that if the conversation is outside
the default business hours, the conversation closes immediately.
---
## Context bundles
Context bundles automatically import [variables](../ai-agents/context.md) into the
conversation. Access the context bundles menu by selecting an environment.
## Uses of context bundles
Context bundles can be very useful in various scenarios, including but not limited to:
- Different variable values for different languages
- Webhook variables that can be edited at any time without intervening with code
- Different information within the same AI Agent, depending on the environment
## Add a context bundle
To add a context bundle, go to your environment → Context bundles → **+ Add context bundle**. Enter
a name and (optionally) a description. After you create the bundle, add all variable keys and values
and save.
## Upload a context bundle
Upload your context bundle from a JSON file. Two methods are available:
### Import a new bundle
Similar to importing an AI Agent, you can import your context bundle. Select a name, a description,
and your JSON file to import your context bundle as new.
### Merge bundle
Upload your bundle into an existing one to merge all variables. In case
of conflicts, either keep the original variable values or replace them with
the new ones.
## Use a context bundle
Once you have created a context bundle, you can use it in your Agent as context variables. To do
this, you first need to apply the context bundle to the conversation using a rule, and then you can
use the variables in a [dialog](../ai-agents/dialogs.md).
### Apply a context bundle
1. Navigate to **Deploy → Rules**.
2. Click on **+ Add rule**.
3. Select the conditions you want to apply the context bundle to.
4. In the **Then** section, select **Apply bundle**.
5. Choose the context bundle you want to apply.
6. Depending on your conditions, you may want to assign an AI Agent too.
7. Activate the rule.
8. Save changes.
### Use the variables
In a dialog, you can use the variables from the context bundle by using the
`{{$global.bundle.variable_name}}` syntax. For example, if you have a variable `name` in your
context bundle, you can use it in a dialog like `{{$global.bundle.name}}`. If you use the variable
before applying the context bundle, it will show as `%UNKNOWN` in the conversation, just like any
other variable.
Every bundle has a preset property `bundle` with its name, so you can use it in your dialog as
`{{$global.bundle.bundle}}`. This can be useful to differentiate between different bundles in the
same dialog using [conditions](../ai-agents/operations/conditions.md).
---
## Environments
A Moveo environment is like a front desk; it receives the first communication from your end user and
ensures it reaches your [AI Agents](../ai-agents/overview.md).
An environment manages the interfaces with various
[channel integrations](../integrations/overview.md) (Web, Facebook Messenger, Viber, etc.) and
connects to your AI Agents through [rules](./rules.md).
In simple use cases, only one environment is sufficient. For example, you might need one assistant
answering FAQs on your website or one assistant handling delivery rescheduling.
However, many businesses want to handle more than one use case and hence require multiple
assistants.
### Why have more than one environment?
Here are some examples:
- You can create one environment connected to your landing page to answer FAQs and generate new
leads, and another environment connected to your customer portal to support logged-in users.
- If your business operates in different markets such as the US and France, you might need to create
one environment for the US market and another for the French market.
- To handle more complex use cases, you can create a
[production and a development environment](../guides/staging-prod-environment.md) to ensure that
releases to production are well tested in the development environment first.
- If you wish to use live chat and have separate customer support teams for different use cases or
languages, you can create separate environments.
---
## Different language, different Agent
This example uses the [Web channel](../integrations/web/getting-started.md) to collect
the user's language preference and assign an [AI Agent](../ai-agents/overview.md) based on their
selection. Other integrations may retrieve the language from the user's configuration settings.
### Setting up the form
The first step is to collect the user's language preference. Set up a form
that prompts the user to choose their preferred language before starting a conversation. This
example uses two AI Agents: one for **English** and another for **Greek**.
1. Navigate to **Deploy → Integrations**.
2. Click on the **Webchat** integration.
3. Go to the **Visitor Information** section.
4. Enable **Collect data before the chat starts**.
5. Click on **+ Add Field** and select **Language** from the dropdown.
6. Add **English** and **Greek** as available language options.
7. Save your changes.
### Assigning the AI agents
[Rules](./rules.md) automate actions in conversations based on predefined conditions.
This section creates a rule to assign the correct AI Agent based on the user's selected
language.
#### Greek language rule
1. Navigate to **Deploy → Rules**.
2. Click on **+ Add Rule**.
3. Fill in the required fields and click **Create**.
4. Set the **When** condition to **A customer starts a conversation**.
5. Set the **If** condition to **Language** is **Greek**.
6. Set the **Then** condition to **Assign to Agent**, then select the **Greek** AI Agent.
7. Click **Save**.
#### English language rule
Follow the same steps as the Greek rule, but:
- Set the **If** condition to **Language** is **English**.
- Set the **Then** condition to **Assign to Agent**, then select the **English** AI Agent.
:::note
For the English rule, you can add an additional condition: if the language is not Greek.
This ensures that conversations from users with other language settings (such as Spanish on Viber)
default to the English AI Agent.
:::
---
## AI Agent routing
A very useful feature of [rules](./rules.md) is the ability to perform actions after the
conversation has started. This guide shows how to reassign the conversation to a
different [AI Agent](../ai-agents/overview.md) using rules and [tags](../ai-agents/operations/tag.md)
in a dialog.
## The plan
This example continues with the agent created in [Build an AI Agent](../guides/build-an-ai-agent.md).
In this example, a gym's **Upsell Agent** handles membership payments. But
what happens if the user wants to change their membership plan? You create a rule that
assigns the conversation to a different Agent, the **Change plan Agent**, when the user asks to
change their membership plan. This Agent is of the **Customer Support** type.
To accomplish this, create a new dialog in Agent 1 that triggers when the user asks
to change their membership plan. This dialog uses a tag that the rule evaluates. The rule then assigns the conversation to the **Change plan Agent**.
:::note
To see how to create an AI Agent from scratch, take a look at
[this guide](../guides/build-an-ai-agent.md).
:::
## Create the dialog
A [dialog](../ai-agents/dialogs.md) is a set of messages that the AI Agent sends to the user. In
this case, create a dialog in the **Upsell Agent** that triggers from an
[intent](../ai-agents/intents.md) matching when the user asks to change their membership plan.
### Intent
1. Go to **AI Agents**.
2. Click on the **Upsell Agent**.
3. Go to **Conversation > Intents**.
4. Click on **Create intent**.
5. Name the intent **Change plan**.
6. Add some examples of what the user might say when they want to change their membership plan. For
example:
- I want to change my membership plan.
- Can I change my membership plan?
- How can I change my membership plan?
7. Click on **Save**.
### Dialog
The key point of this dialog is the replay action. This action triggers a message on the
user's behalf that the rule evaluates. This message is not
visible to the user, but the rule evaluates it and shows it in the logs.
1. Go to **Conversation > Dialogs**.
2. Click on **Create dialog**.
3. Name the dialog **Change plan**.
4. Drag the **Intent** action from the right sidebar to the canvas.
5. Select the **Change plan** intent in the dropdown list.
6. Add a [text response](../ai-agents/responses/text.md) message to the dialog. For example:
- Sure! I can help you with that. Let me assign you to our **Customer Support Agent**.
7. Add a [tag](../ai-agents/operations/tag.md) to the dialog. The rule evaluates this tag. For example: `change_plan`.
8. Finally, add a replay action to the dialog.
## Create the rules
Now that the dialog is ready, you need a way to connect the Agent to the user. First, create a rule that assigns the conversation to the **Upsell Agent**. This rule triggers
when the user starts a conversation. Then, create a second rule that assigns the
conversation to the **Change plan Agent** when the tag `change_plan` is evaluated.
:::warning
This routing **cannot** be tested using the Agent
[test](../guides/build-an-ai-agent.md#testing-the-ai-agent) feature. You must test it in a real
conversation because that only works for testing the Agent functionality, not rules.
:::
### Assign to Upsell Agent
1. Go to **Deploy > Rules**.
2. Click on **+ Add rule**.
3. Fill out the form and click on **Create**.
4. Set the **When** field to **A customer starts a conversation**.
5. Set the **Then** field to **Assign to Agent** and select the **Upsell Agent**.
6. Activate the rule and click on **Save**.
### Assign to Change plan Agent
Follow the same steps as the [previous rule](#assign-to-upsell-agent), but set the **If** field to
**Tag** is **change_plan** and the **Then** field to **Assign to Agent** and select the **Change
plan Agent**.
---
## Rules
'@site/src/components/Img';
Rules let you automate actions in conversations, such as assigning the conversation to a specific AI
Agent, tagging a conversation, and much more.
Rules help you automate your workflows for optimum efficiency and ensure your customers get the best
experience possible.
An [environment](./overview.md) can have one or more rules. The following steps demonstrate rule
creation:
## Customize your rule
### Create the trigger
In the `When` field, set a trigger that determines when the rule executes. The available
triggers are:
| Trigger | When the rule runs |
| ------------------------------------ | ----------------------------------------------------------------------- |
| **A customer starts a conversation** | On the first message of a new conversation, before the AI Agent replies |
| **A customer responds to a message** | On every customer message, before the AI Agent replies |
| **After the AI agent replies** | After the AI Agent has sent its reply |
The first two triggers evaluate the rule **before** the message reaches the AI Agent, so the
conditions see the conversation as the message arrives. **After the AI agent replies** evaluates
the rule **after** the AI Agent has answered, against the conversation state the AI Agent returned
in that turn. Use this trigger when a rule needs to react to something the AI Agent did while
replying, such as adding a [tag](../ai-agents/operations/tag.md) as it
[hands over](../ai-agents/operations/handover.md) the conversation. A rule that runs before the
reply cannot see that tag, so it never matches. See
[Route a handover to a department](#route-a-handover-to-a-department) for a complete example.
#### Rules that run after the AI Agent replies
Keep the following in mind before you create a rule with the **After the AI agent replies**
trigger, or move an existing rule to it:
- **The trigger is the opt-in.** A rule runs after the reply only if it carries this trigger. An
existing rule with **A customer responds to a message** does not start running after the reply.
- **Replace the trigger instead of adding it.** A rule that has both **A customer responds to a
message** and **After the AI agent replies** is evaluated twice in every turn, once before the
reply and once after it. If the rule only routes a handover, replace its trigger. If the rule
also does other things, leave it unchanged and create a separate rule with the new trigger.
- **Conditions see the conversation after the handover.** When the AI Agent hands over, it has
already left the conversation by the time the rule runs. A condition such as **AI agent
assigned** is **known** matches before the reply but not after it. Review any **Agent assigned**
and **AI agent assigned** conditions before you move a rule to this trigger.
- **Actions apply to the next message, not to the reply just sent.** The customer already has the
reply when the rule runs. **Assign AI Agent**, **Assign knowledge base** and **Apply bundle**
change how the next customer message is handled. **Assign department** and **Close
conversation** take effect immediately.
- **The rule cannot undo a handover.** **Assign AI Agent** is ignored once the conversation has
been handed over, so a rule with this trigger cannot return a conversation to the AI Agent after
a human agent took it over.
- **It runs only after an AI Agent reply.** The trigger does not fire when an agent transfers a
conversation manually, when a handover is made through the API, for campaign messages, or in the
AI Agent test chat and simulations. It does fire when the AI Agent sends an inactivity reminder,
because the reminder is a reply. A rule that closes the conversation on this trigger also closes
it after a reminder.
### Apply the condition
A condition is optional. If no condition is set, it evaluates as true and triggers the
action. Available conditions include:
- **Availability**
- Business hours
- **User**
- Name
- Email
- Phone
- Language
- Timezone
- Country
- City
- Browser
- Platform
- **Conversation**
- Channel
- Message content
- Tags
- Customer/referral URL
- Agent assigned
- AI agent assigned
- Integration
Combine the above conditions with **and**/**or** statements.
### Then
Finally, select the **actions** to be applied if the above conditions are met, such as assigning an
AI Agent to answer the message, tagging the conversation, etc.
List of actions:
- Add [tag](../ai-agents/operations/tag.md)
- Assign [AI Agent](../ai-agents/overview.md)
- Assign [knowledge base](../knowledge-base/overview.md)
- Close conversation
- [Apply bundle](../environments/context-bundles.md)
- Assign [department](../chat/departments.md)
Don't forget to make your rule **active** so it starts working.
See [our guides](./rules-route-agent.md) for examples of assigning different AI
Agents based on [tags](./rules-route-agent.md) and
[language](./rules-language.md).
## Route a handover to a department
When the AI Agent hands over a conversation, it can add a tag that says which team should take it.
Because the AI Agent adds the tag while it replies, the rule that reads the tag must use the
**After the AI agent replies** trigger. A rule with **A customer responds to a message** runs
before the reply, does not see the tag, and leaves the conversation unassigned.
1. In the dialog that hands over the conversation, add a [tag](../ai-agents/operations/tag.md)
action next to the [handover](../ai-agents/operations/handover.md) action. For example:
`handover-sales`.
2. Navigate to **Deploy → Rules** and click **+ Add rule**.
3. Set the **When** field to **After the AI agent replies**.
4. Set the **If** field to **Tag** is **handover-sales**.
5. Set the **Then** field to **Assign department** and select the department. For example:
**Sales**.
6. Activate the rule and click **Save and close**.
The rule assigns the [department](../chat/departments.md) as soon as the AI Agent hands over, and
the department distributes the conversation to its agents according to its assignment method.
:::warning
Rules do not run in the AI Agent [test](../guides/build-an-ai-agent.md#testing-the-ai-agent) chat
or in simulations. Test this routing in a real conversation.
:::
## Reorder your rules
Reorder rules based on priority. Drag a rule from the icon on the very left of the tile
and drop it in your desired spot.
Ensure that the highest-priority rule is at the top, and the lowest priority
is at the bottom. In the following image, the **English Rule** has the highest
priority, so the assistant checks it first. Then, the **Greek Rule** is reordered to
have a higher priority than the **Spanish Rule**.
---
## Build your first AI Agent
This tutorial guides you through the process of creating, setting up, and testing a simple
[AI Agent](../ai-agents/overview.md). Each section provides clear, step-by-step instructions, making
it easy to follow. You’ll also find links to more detailed pages if you want to explore specific
topics further. Along the way, we explain not just what to do, but why, so you can gain a solid
understanding of how AI Agents work. This guide will help you build a functional AI Agent with
confidence.
## Create a new AI Agent
To begin, create a new AI Agent where you'll define the logic and overall purpose of the Agent.
1. Go to **AI Agents** in the navigation bar.
2. Click **+ Create new AI Agent**.
3. Select an agent type. (For this example, we'll use **Debt Collection**)
4. Choose a name and set the language your Agent will use.
## Configure your AI Agent
In the [Setup section](../ai-agents/setup.md), provide details about your company and its goals.
This helps the Agent understand its role and who it represents.
1. Enter your company's name.
2. In **AI Agent Goal**, describe what you want your Agent to do. For example:
`Guide the user through the process of paying a subscription.`
## Knowledge
Provide the AI Agent with knowledge in two ways:
- **[Static knowledge](../knowledge-base/overview.md)** (Knowledge bases): This is the information the AI Agent will use to answer questions.
- **[Custom guidelines](../ai-agents/knowledge.md#guidelines-prompting)**: These are the instructions the AI Agent will follow when crafting its responses.
:::tip
Think of **knowledge bases** as **what** the AI Agent should answer, and **custom guidelines** as **how** it should answer.
:::
### Preset guidelines
Each AI Agent type includes **preset guidelines** that cannot be deleted. While you can leave them
blank, filling them in improves the Agent’s performance. Since we chose the **Debt Collection**
Agent, the preset is **Handle Objections**.
1. Identify a possible user objection.
2. Provide an example response for how the Agent should handle it.
3. Click **+ Add objection**.
4. Save your changes.
#### Example
- **Objection**: `I don't like using my credit card online.`
- **Answer**:
`💳 **Your payment is secure!** We use **encrypted, PCI-compliant** processing, and your card details aren’t stored. You may also get **bank verification (OTP)** for extra security. Let me know if you need help! 😊`
### Custom guidelines
#### Payment process
A key guideline for a **Debt Collection** Agent is instructing it on how to collect payments. In
this case, the Agent must retrieve the user’s ID number in order to generate a payment link. Follow
these steps:
1. Click **+ Add guideline** in the summary card on the right.
2. Provide a relevant name and description—the Agent will consider them.
3. A new card appears below **Handling Objections**. Enter the following instructions in markdown:
```md
## What information should be collected from the user?
We must get the user's ID number to generate a payment link.
Once this information is provided, send the following link to the user:
[Payment Link](https://payment.link/)
```
:::tip\
The Agent can also pass the user's ID as a query parameter in the link.\
:::
#### Business hours
In addition to payment handling, you may want the Agent to provide your company’s schedule. Follow
the same steps as in [Payment process](#payment-process), but use the following content:
```md
## Business Hours
- **Monday – Saturday:** 7:00 AM – 8:00 PM
- **Sunday:** 7:00 AM – 12:00 PM
```
## Testing the AI Agent
Once your AI Agent is configured, you can start testing it. Testing allows you to evaluate how the
Agent responds and fine-tune its behavior.
To test the Agent:
1. Click the **Test** button in the top-right corner.
2. A popup chatbox will appear where you can interact with the Agent and review its responses.
3. In the details section, check the context variables and other runtime information.
For example, if you ask the Agent, **"What is your schedule?"**, it should respond with the business
hours you provided. However, since the goal is payment collection, you may want the Agent to more
actively guide users toward that task.
To improve this:
1. Navigate to the **Setup** section.
2. In **AI Agent Goal**, modify the description by adding:\
`"**Always** try to complete this task by prompting the user to continue or subtly encouraging them to proceed."`
3. Save changes.
4. Re-run the test.
This change helps create a more persistent Agent that nudges users toward completing a payment.
---
## Connect your agent to knowledge bases
Connect your AI Agent to knowledge bases to enable intelligent, knowledge-driven responses. This guide walks you through the connection process.
## Prerequisites
Before connecting, ensure you have:
1. An [AI Agent](../ai-agents/overview.md) created in your account
2. A [knowledge base](../knowledge-base/overview.md) with content added
## Connect a knowledge base to your agent
1. Navigate to **AI Agents**
2. Select the AI Agent you want to enhance
3. Open the **Knowledge** tab
4. In the **Knowledge base** section, click the dropdown
5. Select the knowledge base you want to connect
6. Click **Connect**
Your agent now uses the connected knowledge base to answer user questions.
## Connect multiple knowledge bases
Connect more than one knowledge base to a single agent. This is useful when:
- You have content organized by topic (e.g., Products, FAQs, Policies)
- Different teams maintain separate knowledge bases
- You want to combine internal and external content sources
To add additional knowledge bases, repeat the connection steps above. The agent searches across all connected knowledge bases when responding.
## When to use knowledge bases vs dialogs
| Use knowledge bases for | Use dialogs for |
|------------------------|-----------------|
| FAQ-style Q&A | Multi-step processes |
| Static information lookup | API integrations |
| Document-based responses | Conditional logic flows |
| Product information | Collecting user data via forms |
:::tip
Combine both approaches for the best results. Use knowledge bases for information retrieval and dialogs for structured workflows.
:::
## Troubleshooting
### Agent not using knowledge base content
- Verify the knowledge base is connected in the **Knowledge** tab
- Check that the knowledge base contains relevant content
- Ensure the knowledge base language matches user queries
### Responses are inaccurate
- Add more specific content to your knowledge base
- Review and refine your [guidelines](../ai-agents/knowledge.md#guidelines-prompting)
- Check the [Insights](../analytics/insights.md) tab for improvement suggestions
## Next steps
- [Knowledge base overview](../knowledge-base/overview.md) - Learn more about knowledge base features
- [Add FAQs](../knowledge-base/faq.md) - Create FAQ entries
- [Upload documents](../knowledge-base/documents.md) - Import existing documentation
---
## Conversations
In Moveo, conversations between users and an [AI Agent](../ai-agents/overview.md) occur within a
structure called a **session**. A session is a temporary container used to store all context needed
for an ongoing conversation, including:
- Context variables
- User information
- Metadata
Sessions enable contextual and coherent conversations by persisting data throughout the interaction.
## How sessions work
Each time a user starts a new conversation, Moveo creates a new session. This session remains active
throughout the interaction, allowing the AI Agent to maintain continuity and respond meaningfully.
The entire conversation context is preserved for the duration of the session. The session's lifetime is primarily controlled by the **session timeout**.
Sessions are automatically closed under the following conditions:
- The conversation is resolved either through a [dialog](../ai-agents/operations/resolve.md) action
or by a [human agent](../chat/human-agents.md).
- The session reaches its maximum lifetime, as defined by the [session timeout](./timeouts.md#session-timeout).
It is important to distinguish the `session_timeout` from the `inactivity_timeout` setting on an AI Agent. The `session_timeout` is the primary controller of the conversation's lifespan. The `inactivity_timeout`, while also used for analytics and routing, can in some cases shorten the session's life. For more details, see the [Timeouts](./timeouts.md) documentation.
Once closed, sessions cannot be reopened unless they are still within a defined grace period (see
[session timeout](./timeouts.md#keep-alive)).
Although sessions themselves are ephemeral, the **conversation history is preserved**. This allows
you to:
- Review and audit past conversations.
- Extract insights from analytics.
- Improve AI Agent performance over time.
## Session life cycle
The session life cycle describes how sessions are created, maintained, and ultimately closed or
expired. This process ensures a balance between maintaining continuity during a conversation and
releasing unused resources after it ends.
### 1. Creation
Sessions are created automatically when a new conversation is initiated. This typically happens:
- When a user sends the first message.
- When a `session:create` event is received from the websocket API.
- When a [broadcast](../campaigns/campaigns) message is sent to the user.
At creation, the session is initialized with context data and assigned a unique `session_id`.
### 2. Active state
While a conversation is ongoing, the session remains in an active state. During this period:
- The user can send and receive messages.
- The context can be updated dynamically.
- Dialogs and conditions have access to all session context variables.
- User metadata and preferences are preserved.
### Renewing a Session
A session's Time-To-Live (TTL) is not static; it is renewed each time the **user sends a message**. This means the session's expiration clock is reset, extending the life of the session.
However, messages sent by an **AI Agent** or a **human agent** do not renew the session TTL. The session is kept alive by the user's activity, ensuring that conversations expire only when the user has been inactive for the configured duration.
| Event | Renews Session TTL? |
| :------------------------------ | :------------------ |
| **User sends a message** | **Yes** |
| **AI Agent sends a message** | **No** |
| **Human agent sends a message** | **No** |
### 3. Closure
A session can be closed under the following conditions:
- A **resolve action** is triggered within a dialog.
- A human agent manually resolves the conversation and the user doesn't reopen it within the
[keep-alive](./timeouts.md#keep-alive) period.
- The client explicitly signals the session should be closed.
Closed sessions transition to a recoverable state for a short time.
### 4. Grace period (keep-alive)
After a session is closed, it enters a grace period defined by the
[**keep_alive**](./timeouts.md#keep-alive) setting. During this time:
- The session can be reopened if needed (only if it is not expired).
- Context and message history are retained.
This allows for short breaks in conversation without losing context.
### 5. Expiration
When the [**session_timeout**](./timeouts.md#session-timeout) is reached or the
**keep_alive** period ends, the session is permanently expired. Once expired:
- The session can no longer be accessed or resumed.
- A new session must be created for future interactions.
## Sessions and the user experience
Sessions ensure that users receive consistent responses by preserving context across messages. Each
session is uniquely identified and can include custom metadata that enriches how conversations are
handled and analyzed.
Monitor active and past sessions through the **Analytics** section of the platform. While
sessions are temporary, the information is stored for future reference and debugging purposes.
For information about how sessions behave specifically in the websocket API, including recovery
mechanisms and timeout behavior, see the [Session life cycle](/api/websocket/life-cycle)
documentation.
---
## Publishing agents to production
Deployment is a crucial step when integrating Moveo into your business. It consists of three main
components:
- Environments
- Rules
- Integrations
Each of these plays an essential role in the implementation of Moveo. Let’s explore each of them in
detail.
## Environments
Within a single Moveo account, you can create multiple environments. Each environment is an
independent instance of your Moveo setup, with its own set of rules and integrations. You can use
environments to:
- Test new setups in a sandbox environment.
- Deploy to different channels using separate environments.
- Handle different integrations of the same channel independently.
- Test different AI Agent versions.
## Rules
Rules are the logic Moveo follows to manage conversations. By defining conditions, you can perform
actions such as assigning an AI Agent, routing to a department, setting a tag, and more.
Every message in a conversation is evaluated against the same set of rules, regardless of the
channel it originates from. If you want to treat different channels in distinct ways, you'll need to
set up separate environments.
For examples on how to configure rules, refer to these guides:
- [How to route an agent using rules](../environments/rules-route-agent)
- [How to assign a different agent depending on the language](../environments/rules-language)
## Integrations
Integrations connect Moveo to your end users. These are the channels through which users interact
with your setup.
Moveo provides a web widget that can be embedded into your website. This widget is highly
customizable and built on top of an exposed [WebSocket API](/api/websocket/connection). You can
use this to build your own custom integrations as well.
Besides the web widget, Moveo supports several third-party channels:
- [Web](../integrations/web/getting-started)
- [Facebook Messenger](../integrations/facebook-messenger)
- [Instagram](../integrations/instagram-messenger)
- [WhatsApp](../integrations/whatsapp)
- [Viber](../integrations/viber)
- [Intercom](../integrations/intercom)
- [Zendesk Chat](../integrations/zendesk)
- [Sunshine Conversations](../integrations/sunco)
- [Front](../integrations/front.md)
- [Smartlead](../integrations/smartlead.md)
- [Infobip-SMS](../integrations/infobip-sms.md)
- [Infobip-RCS](../integrations/infobip-rcs.md)
- [Email](../integrations/email)
---
## Import an AI Agent
In this guide, we will show you how to import an AI Agent to your account. After importing an AI
Agent, you can test it out or make any changes you wish.
## Step 1: Login to Moveo.AI
1. Navigate to [https://console.moveo.ai](https://console.moveo.ai/).
2. Select your preferred login method. In this guide, we will continue logging in with **Google**.
3. Select your **Gmail** account and you will be directly logged in.
## Step 2: Creating and Importing an AI Agent
1. Click on **Create AI Agent**.
2. Fill out the information in the pop-up window.
3. Import your saved AI Agent (JSON file).
4. Click **Create**.
## Step 3: Navigate to the AI Agent and preview it
1. Click on the newly created AI Agent named `my_imported_brain` in this example.
2. Click on the **Test** icon in the top right of your screen and start chatting with the new AI
Agent!
---
## Guides
Follow the guides below to get familiar with Moveo.AI and learn from the examples provided.
- [View invitations](../platform/invitations.md)
- [Allow desktop notifications](../platform/desktop-notifications.md)
- [Build your first AI Agent](../ai-agents/setup.md)
- Use **rules** to assign an AI Agent
- [AI Agent routing](../ai-agents/message-path.md)
- [Assign AI Agent depending on language](../environments/rules-language.md)
- [Use staging and production environments](../environments/overview.md)
- [Knowledge base guidelines & best practices](../knowledge-base/faq.md)
- [Create a webview](../ai-agents/responses/webviews.md)
- [Create a survey](./survey)
- [Create a webhook](../ai-agents/webhooks.md)
- [Add your business hours](../environments/business-hours.md)
---
## Deploy your first AI Agent to production
## **Getting Started with Your AI Agent**
This guide walks you through the steps to get your [AI agent](../ai-agents/overview.md) up and running and interacting with your customers. The goal is to get you from zero to a fully functional agent in just a few minutes.
**A quick note for new users:** If you've just signed up, you might find that some of these steps are already done! The initial onboarding process guides you through tweaking your first agent and deploying it to a web integration. If you followed that tour, you're ahead of the game. This guide is perfect if you skipped the tour or need a refresher.
### **Step 1: Your AI Agent**
Before you can deploy your AI agent, you need to have one! We'll assume you've already created an agent. If you haven't, or if you want to build a more specialized one from scratch, you can follow this handy guide to [build your first AI Agent](../ai-agents/quickstart.md).
It's good to know that when you create a new account, a default AI agent is automatically created for you, so you can get started right away. This agent is ready to be customized and taught. You can start with this agent and mold it to fit your brand's voice and needs. A great way to do this is by adding more knowledge using [Knowledge base](../knowledge-base/overview.md). Think of Knowledge base as a library of information that your agent can use to answer questions instantly. For example, you could create a knowledge base of your most frequently asked questions (FAQs) or upload documents with product information. This gives your agent the specific knowledge it needs to be truly helpful to your customers. You can learn more about them [here](../knowledge-base/overview.md).
### **Step 2: Set up the Rules**
Next, you need to tell the system when to use your AI agent. This is done with [rules](../environments/rules.md), which are powerful automated workflows. In a new account, a fundamental rule is already set up for you and connected to the default agent, making things even easier. If you're using the default agent and haven't created a new one, you can skip this step entirely.
You'll want to set up a rule that says:
- **When:** A customer starts a conversation
- **Then:** Assign the AI agent
This simple but crucial instruction means that whenever a new conversation is started on any of your connected channels, your AI agent will be the first to respond, ensuring your customers get an immediate reply. It acts as the entry point for your automated support.
#### **Environments?**
You might see the term [Environments](../environments/overview.md) in the platform. Don't worry about this for now. An environment is like a workspace, often used to separate testing from the live, customer-facing setup. For this quick start, all you need to know is that a live environment is automatically created for you, so you don't need to configure anything here to get started.
### **Step 3: Connect to your Channels**
Now it's time to connect your agent to the channels your customers use. This is the final step to bring your agent to life and make it accessible! You can connect to one or many channels, depending on where your customers prefer to interact with you.
:::note
You might see that the web integration is already connected to the default agent. This is because the default agent is automatically created for you when you create a new account.
:::
Here are the available integrations and links to their setup guides. Choose the channel you want to start with and follow the instructions.
| Integration | Setup Page |
| ---------------------- | ----------------------------------------------------------- |
| Web | [Web Widget](../integrations/web/getting-started.md) |
| Facebook Messenger | [Facebook Messenger](../integrations/facebook-messenger.md) |
| Instagram | [Instagram](../integrations/instagram-messenger.md) |
| WhatsApp | [WhatsApp](../integrations/whatsapp.md) |
| Viber | [Viber](../integrations/viber.md) |
| Intercom | [Intercom](../integrations/intercom.md) |
| Zendesk Chat | [Zendesk Chat](../integrations/zendesk.md) |
| Sunshine Conversations | [Sunshine Conversations](../integrations/sunco.md) |
| Front | [Front](../integrations/front.md) |
| Smartlead | [Smartlead](../integrations/smartlead.md) |
| Infobip-SMS | [Infobip-SMS](../integrations/infobip-sms.md) |
| Telnyx Voice | [Telnyx Voice](../integrations/telnyx-voice.md) |
| Twilio Voice | [Twilio Voice](../integrations/twilio-voice.md) |
| Email | [Email](../integrations/email.md) |
### **And that's it!**
Once you've set up your integration, your AI agent is ready to go. Congratulations! Your agent is now live and will begin handling incoming conversations immediately, providing instant support to your customers. Your setup is now production-ready.
---
## Staging and live environments
In certain cases, you may need to use two environments for your AI Agent: a **staging**
(development) environment and a **live** (production) environment. In the staging environment, you
will be able to immediately view the changes you make to the AI Agent, whereas the production
environment should contain the assistant that your customers will converse with. Check out the
following guide, which demonstrates the full procedure of creating the staging and production
environments.
### New environment
To create the `dev` environment, follow these steps. This environment is similar to any other
environment, but we will set up a rule to route the conversation to a `draft` version of an AI
Agent.
1. Click on your avatar and go to the **Profile** section.
2. Click on the **+** button next to the **Environments** tab on the sidebar.
3. Choose a name for your new environment and decide whether you want **Human Chat** enabled or not.
### Routing rules
After creating your new environment, you need to set up a routing rule to route the conversation to
the `draft` version of the AI Agent. This version reflects the state of your Agent as you see it
when editing, without publishing a new version.
1. Go to **Deploy** → **Rules**.
2. Click on the dropdown menu in the subnavigation bar and select the environment you just created.
In our case, it would be `Development`.
3. Click on the **+ Create new rule** button.
4. Choose a name for your rule and click on **Create**.
5. Click on **Add action** and select **Assign AI Agent** from the menu.
6. In a production environment, you would select the latest version of the Agent, but in the
development environment, you should select the `draft` version.
7. Activate the rule and save changes.
---
## Survey
A survey is a set of questions that you can send to your customers to gather feedback about your
product or service. You can create a survey using the Moveo platform and send it to your customers.
See [Survey Response](../ai-agents/responses/survey.md) for more details.
## Template
If you want to jump straight into some template code, go to our
[integration-guides repository on GitHub](https://github.com/moveo-ai/integration-guides/tree/main/pages/common).
## How to create your own survey
To create your own survey, follow the steps described in the
[How to create your own webview](../ai-agents/responses/webviews.md#how-to-create-your-own-webview) guide. The main
difference with a regular webview is the data submission, which you should do by making an HTTP POST
request to: `https://channels.moveo.ai/v1/survey/${integration_id}`, using the following headers and
body:
```ts
headers: {
Authorization: `Bearer ${signature}`,
'X-Moveo-Session-Id': sessionId,
}
```
```ts
body: {
session_id: sessionId,
timestamp: Date.now(), // unix timestamp,
feedback: 'Everything was awesome',
rating: 5
}
```
---
## Timeout Mechanisms in Moveo
Moveo uses several timeout mechanisms to manage the lifecycle of conversations. These timeouts serve
different purposes and work together to ensure optimal user experience while maintaining system
efficiency. This page explains the key timeout mechanisms and how they impact conversations.
## Session timeout
The **session timeout** is the default timeout that acts as the baseline lifetime for a conversation. Its value is configured at the integration level and varies depending on the integration (e.g., WhatsApp vs. Zendesk). In the API, it is represented as **session timeout** (in seconds).
The default session timeout varies depending on the integration type. The following table shows the default session timeout for each integration type:
| Integration Type | Default Session Timeout (seconds) |
| ------------------------------------------------------------- | --------------------------------- |
| [Facebook-messenger](/docs/integrations/facebook-messenger) | 604800 (7 days) |
| [Instagram-messenger](/docs/integrations/instagram-messenger) | 604800 (7 days) |
| [Whatsapp](/docs/integrations/whatsapp) | 604800 (7 days) |
| [Viber](/docs/integrations/viber) | 604800 (7 days) |
| [Intercom](/docs/integrations/intercom) | 86400 (1 day) |
| [Zendesk](/docs/integrations/zendesk) | 86400 (1 day) |
| [Front](/docs/integrations/front) | 86400 (1 day) |
| [Web](/docs/integrations/web) | 3600 (1 hour) |
| [Sunco](/docs/integrations/sunco) | 600 (10 minutes) |
| [Smartlead](/docs/integrations/smartlead) | 1296000 (15 days) |
| [Infobip-sms](/docs/integrations/infobip-sms) | 604800 (7 days) |
| Infobip-rcs | 604800 (7 days) |
| Telnyx-voice | 300 (5 minutes) |
| Twilio-voice | 300 (5 minutes) |
| Email | 1296000 (15 days) |
This timeout is primarily used in two scenarios:
1. **Initial Conversation Timeout**: When a conversation is first created, such as through a broadcast message, it uses the **session timeout** until the user replies and an AI or human agent is assigned.
2. **Human Agent Conversations**: When a human agent is handling the conversation, the **session timeout** governs the session's maximum duration.
The session's expiration time is reset to the **session timeout** value each time the **user** sends a message during a human-handled conversation.
:::note
The **session timeout** is not configurable from the UI. It can only be set via the API by setting `config.session_timeout` propery when [creating or updating an integration](/api/rest/add-integration).
:::
---
## Inactivity timeout
The **inactivity timeout** governs the session's duration when an **AI Agent** is active, taking precedence over the default **session timeout**. When an AI Agent is assigned to a session, the **inactivity timeout** from the agent's configuration defines the session's maximum lifetime. The session will expire if the user does not send a message within this timeframe. This value is represented as **inactivity timeout seconds** in the API.
:::tip
Subscribe to [event notifications](../platform/event-notifications) to receive notification when a session expires due to inactivity.
:::
Configure this timeout in the AI Agent settings under the **Advanced** tab. The session's expiration time is reset to the **inactivity timeout** value each time the **user** sends a message during an AI-handled conversation.
### How to configure inactivity timeout
1. Navigate to your AI Agent.
2. Click on the **Advanced** tab.
3. Choose an option in the **Inactivity timeout** section.
## Dynamic timeout behavior
Moveo dynamically manages the session timeout based on the context of the conversation.
- If an **AI Agent** is assigned to the conversation, the session's lifetime is determined by the agent's **inactivity timeout**.
- If a **human agent** takes over, the timeout switches to the integration's default **session timeout**.
This ensures that the session's lifetime is adapted to the context, whether it's automated or handled by a human.
For example, if a conversation is started by a campaign, it will remain open until the initial **session timeout** expires. If the user responds and an AI Agent takes over, the session's expiration will now be dictated by the AI Agent's **inactivity timeout**. The session will expire if the user does not send another message within that new timeframe.
:::important
The session timeout—whether it is the **session timeout** or the **inactivity timeout**—is **only** reset when the **user** sends a message. Messages sent by an AI Agent or a human agent do not extend the session's life. The conversation is kept alive exclusively by the user's interactions.
:::
## Keep alive
The **keep alive** timeout specifies the number of seconds to keep a session open after it has been marked as resolved. This allows users to continue the same conversation if they have follow-up questions within a short period.
### Key features:
- **Grace Period**: Provides a buffer after a conversation is resolved.
- **Measured in Seconds**: The value is configured in seconds (e.g., 300 seconds = 5 minutes).
- **API Representation**: Represented as `keep_alive` in the API.
### Use case:
Imagine a customer support scenario where an agent has resolved a user's issue and marked the conversation as complete. With a `keep_alive` of 5 minutes:
1. The conversation remains open and accessible for 5 minutes after being resolved.
2. If the user sends another message within this window, it is appended to the same conversation.
3. If the user sends a message after the 5-minute period, a new conversation is created.
### How to configure keep alive timeout
1. Navigate to **Settings**.
2. Select the **Environment** you want to modify.
3. Click on the **Setting** tab.
4. Scroll down to the **Keep alive** section.
### Voice integrations
Keep alive does not affect call termination on voice integrations such as
[Twilio Voice](../integrations/twilio-voice.md) and
[Telnyx Voice](../integrations/telnyx-voice.md). When the AI Agent triggers
[`Resolve`](../ai-agents/operations/resolve.md), the platform hangs up the call within a couple of
seconds, whatever the keep alive value.
Choose the keep alive value for your chat channels alone. The setting applies to the whole
environment, so lowering it for a voice reason also shortens the follow-up window of every chat
integration on that environment.
To keep the caller on the line for longer before the call ends, add a
[`Pause`](../ai-agents/operations/pause.md) action before `Resolve`. A pause is the only way to
postpone the hangup.
---
## Email(Integrations)
## Overview
[Email integration](../integrations/overview.md) enables your [AI Agent](../ai-agents/overview.md) to communicate with customers through email. This channel provides a familiar and widely-used method for customer support, sales inquiries, and engagement through automated email conversations.
Moveo's email integration uses enterprise-grade email infrastructure to ensure reliable delivery, secure message handling, and professional presentation of all automated responses.
---
## Prerequisites
Before setting up the email [integration](../integrations/overview.md), ensure you have:
**Email domain requirements**
- A verified domain that you own and can configure DNS records for
- Access to your domain's DNS management (via your registrar or DNS provider)
- Ability to add DNS records (CNAME records for domain verification)
**Email service requirements**
- An email service account (Google Workspace, Microsoft 365, or custom mail server)
- Access to configure email forwarding rules in your email provider
- A dedicated email address for your [AI Agent](../ai-agents/overview.md) (e.g., `support@yourdomain.com`)
---
## How it works
The email [integration](../integrations/overview.md) requires two essential setup steps to enable both receiving and sending emails:
**Receiving emails (inbound)**:
1. **Customer sends email** to your configured email address.
2. **Email forwarding rule** forwards the message to Moveo's email processing system.
3. **[AI Agent](../ai-agents/overview.md)** receives the message content.
---
**Sending emails (outbound)**:
4. **Response is generated** based on your configured knowledge and dialogs.
5. **DNS records authorize** Moveo to send emails on behalf of your domain.
6. **Reply is sent** back to the customer from your domain.
7. **Thread management** maintains conversation context.
8. **Handover available** to human agents when needed via [Live chat](../chat/chat-overview).
All emails are processed securely and maintain proper email threading for natural conversation flow.
---
## Connect email in Moveo
### Step 1: Navigate to Connections
1. Log in to your Moveo account.
2. Navigate to **Connections** → **Emails**.
3. Select your desired environment.
4. Click **Add Email** in the top navigation bar.
### Step 2: Enter Sender information
1. In the **Sender information** form, enter the following:
- **Sender email**: The email address you want to use for your [AI Agent](../ai-agents/overview.md) (e.g., `support@yourdomain.com`).
- **Sender name**: The display name that will appear as the sender of your emails (e.g., "Support Team" or "AI Assistant").
2. Click **Verify** to proceed.
### Step 3: Complete DNS configuration
To send emails on behalf of your domain, you must complete the DNS configuration. This step is **required** for the [integration](../integrations/overview.md) to work. Follow the instructions in the [DNS configuration](#dns-configuration) section below.
### Step 4: Configure email forwarding
To receive inbound emails, you must set up email forwarding from your email service to Moveo. This step is **required** for the [integration](../integrations/overview.md) to work. Follow the instructions in the [Forward your emails to Moveo.ai](#forward-your-emails-to-moveoai) section below.
---
## DNS configuration
:::important
This DNS configuration is **required** to allow Moveo to send emails on behalf of your domain. Without these records, email replies from your [AI Agent](../ai-agents/overview.md) cannot be delivered.
:::
To enable Moveo to send emails from your domain, you need to configure DNS records that authorize and authenticate Moveo as a sender.
### Step 1: Get DNS configuration details
1. After entering your sender information and clicking **Verify**, you will see the **DNS status** section.
2. The DNS status section shows all required CNAME records with their verification status.
3. For each record, you can copy the **Host** and **Value** fields using the copy icons next to each field.
4. These values will be used to configure DNS records in your domain provider.
### Step 2: Add CNAME records
CNAME records are required for domain verification and tracking.
1. In the DNS Configuration section, you will see three CNAME records provided by Moveo.
2. For each CNAME record:
1. Log in to your domain registrar or DNS provider
2. Navigate to DNS management for your domain
3. Add a new CNAME record with the following:
**Type**: CNAME
**Name/Host**: The subdomain provided by Moveo (e.g., `em1234`, `s1._domainkey`, etc.)
**Value/Target**: The target hostname provided by Moveo
**TTL**: `3600` (or default)
3. CNAME records are required for domain verification and must be added before other records can be verified.
:::note
CNAME records point to subdomains (like `em1234.yourdomain.com`). Make sure you're adding these as subdomain records, not root domain records. Some DNS providers require you to enter just the subdomain prefix in the Name/Host field.
:::
### Step 3: Add DMARC record (Optional but recommended)
DMARC (Domain-based Message Authentication, Reporting, and Conformance) helps protect your domain from email spoofing. If you already have a DMARC entry configured you can skip this step.
1. Create a new TXT record.
2. **Name/Host**: `_dmarc`.
3. **Value**: `v=DMARC1; p=none;`.
4. **TTL**: `3600`.
### Step 4: Verify DNS configuration
1. Return to Moveo's Email integration page.
2. Click **Verify** to check the status of your DNS records.
3. Moveo will check each record and show whether each is verified or unverified:
**Verified**: DNS record is correctly configured and verified.
**Unverified**: DNS record is not found or incorrectly configured.
:::tip
DNS changes can take anywhere from a few minutes to 48 hours to propagate globally.
:::
---
## Forward your emails to Moveo.ai
:::important
Required step: Email forwarding is **required** to enable Moveo to receive inbound emails. You must configure forwarding from your email service to Moveo's email processing system.
:::
Email forwarding routes incoming emails from your configured email address to Moveo's [AI Agent](../ai-agents/overview.md) processing system. This setup works with any email service (Google Workspace, Microsoft 365, custom mail servers, etc.) and allows you to keep your existing email infrastructure while enabling [AI Agent](../ai-agents/overview.md) responses.
### Step 1: Configure forwarding in your email provider
Consult your email provider's documentation for setting up forwarding rules. The general process is:
1. Find forwarding or mail routing settings.
2. Create a rule that forwards emails to Moveo.
3. Forward to the address provided in Moveo's integration configuration.
4. If your email provider sends a verification email, this will be forwarded to Moveo and can be viewed in your [analytics logs](../analytics/logs).
### Step 2: Verify forwarding in Moveo
1. Send a test email to your configured address.
2. Verify the email appears in Moveo's analytics within a few minutes.
:::info Verification Emails
Some email providers (like Google Workspace or Microsoft 365) may send a verification email to the forwarding address when you set up email forwarding. This verification email will be forwarded to Moveo. You can view this verification email in your [analytics logs](../analytics/logs).
:::
---
## Troubleshooting
DNS records not verifying
**Symptoms**: DNS verification is unverified after configuring DNS provider
**Solutions**:
- Wait 24–48 hours for DNS propagation.
- Check for typos in record values (case-sensitive).
- Ensure you're using the exact values from Moveo (no extra spaces).
- Check if your DNS provider requires a trailing dot (.) in hostnames.
Email forwarding not working
**Symptoms**: Inbound emails not reaching Moveo, forwarding rule not triggering
**Solutions**:
- Verify forwarding rule is active and correctly configured in your email provider.
- Test forwarding by sending a test email and checking if it reaches Moveo.
- Check email provider logs for forwarding errors.
- Ensure forwarding address from Moveo is correct (no typos).
- Verify the email address matches exactly between forwarding rule and Moveo configuration.
- Review email provider's forwarding limits or restrictions.
- Check spam filters aren't blocking forwarded emails.
- If your email provider sent a verification email, check your [analytics logs](../analytics/logs) as it may have been forwarded automatically.
Emails going to spam
**Symptoms**: Customer emails or [AI Agent](../ai-agents/overview.md) replies end up in spam folders
**Solutions**:
- Verify CNAME records are properly configured (takes 24–48 hours).
- Add DMARC record for better email authentication.
- Warm up the email domain gradually if it's new.
- Avoid spam trigger words in [AI Agent](../ai-agents/overview.md) responses.
Conversation threads breaking
**Symptoms**: Each email appears as a new conversation instead of continuing existing threads
**Solutions**:
- Check if email client is preserving threading headers.
- Test with different email clients (Gmail, Outlook, etc.).
- Contact Moveo support at `support@moveo.ai` if threading issues persist.
---
## Limitations
### Email platform restrictions
- **Message size**: Standard email size limits apply (typically 30 MB including attachments).
- **File attachments**: Supported, but large attachments may affect delivery speed.
- **Email format**: Supports HTML and plain text emails.
### Integration constraints
- **One email address per integration**: Each [integration](../integrations/overview.md) handles one email address.
- **Thread management**: Requires proper email client support for threading.
- **DNS propagation**: Initial setup requires waiting for DNS propagation (up to 48 hours).
- **Domain verification**: Domain must be verified before emails can be sent.
---
## Best practices
### Email setup
- Use a dedicated email address for your [AI Agent](../ai-agents/overview.md) (e.g., `support@yourdomain.com`, `help@yourdomain.com`).
- Configure the DMARC record (optional but recommended) for best deliverability.
- Test email delivery thoroughly before going live.
- Monitor email deliverability metrics regularly.
### Compliance
- Monitor for unauthorized email sending.
- Follow email best practices and anti-spam guidelines.
- Protect your domain's sender reputation.
---
## Next steps
Once your email [integration](../integrations/overview.md) is active:
1. **Test thoroughly** by sending test emails from different addresses.
2. **Monitor initial conversations** to ensure proper threading and responses.
3. **Optimize [AI Agent](../ai-agents/overview.md) responses** for email format and clarity.
---
## Facebook Messenger
## Overview
Facebook Messenger integration allows your AI Agent to communicate with customers through your
Facebook Page. With billions of active users, Messenger provides a familiar platform where customers
already spend time, making it an ideal channel for customer service and engagement.
This integration enables:
- **Automated responses** to messages on your Facebook Page
- **24/7 availability** for customer inquiries
- **Rich messaging features** including quick replies, buttons, and carousels
- **Seamless handover** to human agents when needed
- **Integration with Facebook's ecosystem** including Instagram and WhatsApp
---
## Prerequisites
Before setting up the Facebook Messenger integration:
✅ **Facebook Page requirements**
- An active Facebook Page for your business
- [Admin access](https://www.facebook.com/help/289207354498410) to the Page
- Page must be published (not unpublished or restricted)
✅ **Moveo account setup**
- An active [AI Agent](../ai-agents/overview.md) configured
- An [environment](../environments/overview.md) selected for the integration
✅ **Technical requirements**
- Authority to grant app permissions
- Access to Page settings and messaging configuration
---
## How it works
The Facebook Messenger integration creates a direct connection between your Facebook Page and Moveo
AI Agent:
1. **Customer sends message** to your Facebook Page via Messenger
2. **Moveo receives the message** through Facebook's Graph API
3. **AI Agent processes** the message using your configured knowledge and dialogs
4. **Response is sent** back through Messenger to the customer
5. **Handover available** to human agents when needed
All conversations happen within Facebook's secure infrastructure and comply with their platform
policies.
---
## Setup guide
The setup process differs based on whether this is your first Facebook integration or you're adding
additional Pages.
### First-time connection
Follow these steps if you're connecting a Facebook Page to Moveo for the first time:
#### Step 1: Initiate connection
1. Navigate to **Integrations** in your Moveo account
2. Select your desired environment
3. Find Facebook Messenger and click **Connect**
4. You'll be redirected to the Meta Dialog Window
#### Step 2: Grant permissions
In the Meta Dialog Window:
1. **Select ONE page** you want to connect
2. **Grant ALL permissions** requested by Moveo
3. Click **Continue**
:::warning
Only select ONE page during initial setup. You can add more pages later using
the multi-page process.
:::
#### Step 3: Complete setup
1. You'll be redirected back to Moveo
2. Your Page is now connected
3. Proceed to [Configuration](#configuration-options)
---
### Adding additional Pages
If you already have Facebook Pages connected to Moveo, follow this process to add more:
#### Step 1: Preserve existing connections
1. Click **Connect** to open Meta Dialog Window
2. **Keep ALL previously connected Pages selected**
3. **Add the new Page** to your selection
4. Grant all permissions
:::caution
You MUST keep previously connected Pages selected. Deselecting them will
disconnect those Pages from Moveo.
:::
#### Step 2: Complete setup
1. Return to Moveo after authorization
2. All selected Pages are now connected
3. Configure each Page individually
---
## Configuration options
After connecting your Facebook Page, configure these settings to optimize your integration:
### Integration status
Toggle the integration to **Active** to start receiving and responding to messages.
### Welcome screen setup
Configure how new conversations begin with the welcome screen:
#### Greeting text
A brief description of your Page that appears when users first open Messenger.
#### Get Started button
The button users click to initiate conversation. Configure:
- Button text (default: "Get Started")
- Initial message sent when clicked
Example configuration:
### Persistent menu
Create an always-visible menu with quick access options:
1. **Menu items**: Add up to 3 primary menu items
2. **Actions**: Each item can:
- Send a predefined message
- Open a URL
- Trigger a specific dialog
3. **Nested menus**: Create sub-menus for better organization
Benefits:
- Quick access to common functions
- Improved user navigation
- Consistent experience across conversations
### Webview configuration
If your AI Agent uses [webview responses](../ai-agents/responses/webview.md):
#### Whitelist domains
Add trusted domains that can be opened in Messenger's in-app browser:
- Your website domain
- Payment processor domains
- Third-party service domains
Example:
```
https://example.com
https://payments.example.com
https://booking.example.com
```
### Advanced security
#### App Secret validation
Enable request signature verification for enhanced security:
1. Enable in Moveo settings
2. Add App Secret from your Facebook App
3. All webhook requests will be validated
---
## Testing your integration
### Test with your account
1. **Send a test message** to your Facebook Page
2. **Verify AI Agent responds** appropriately
3. **Test different scenarios**:
- Welcome message
- Common questions
- Handover triggers
- Error cases
### Test with different users
1. Have team members message your Page
2. Test with different user permissions
3. Verify consistent behavior
### Monitor performance
Check these metrics in Facebook Page Insights:
- Response time
- Response rate
- Customer satisfaction
- Message volume
---
## Common use cases
### Customer support
- Answer FAQs instantly
- Provide order status updates
- Handle returns and refunds
- Escalate complex issues to agents
### Lead generation
- Qualify leads automatically
- Schedule appointments
- Collect contact information
- Route to sales team
### E-commerce
- Product recommendations
- Inventory checks
- Order placement assistance
- Post-purchase support
### Marketing
- Contest and promotion management
- Event registrations
- Newsletter signups
- Product launches
---
## Best practices
### Response design
- Keep messages concise and scannable
- Use quick replies for common options
- Include buttons for clear actions
- Add images for visual appeal
### Conversation flow
- Start with a clear welcome message
- Guide users with suggested actions
- Provide escape routes (talk to human)
- End conversations gracefully
### Compliance
- Follow Facebook's Platform Policy
- Respect user privacy
- Provide opt-out options
- Handle data responsibly
### Performance optimization
- Monitor response times
- Track handover rates
- Review failed interactions
- Continuously improve responses
---
## Troubleshooting
### Connection issues
Page doesn't appear in selection
- Verify you have admin access to the Page
- Check Page is published and not restricted
- Try logging out and back into Facebook
- Clear browser cache and cookies
Permissions not granted properly
- Ensure ALL requested permissions are granted
- Check no permissions were previously revoked
- Review Facebook App settings
- Re-authorize if needed
Previously connected Pages disconnected
- When adding new Pages, keep old ones selected
- If accidentally disconnected, reconnect all Pages
- Check each Page's configuration is intact
- Contact support if data was lost
### Message delivery
AI Agent not responding
- Verify integration is set to Active
- Check AI Agent is assigned to environment
- Review Facebook Page settings
- Ensure webhook is properly configured
Responses are slow or timeout
- Check Moveo system status
- Review AI Agent complexity
- Optimize response generation
- Consider implementing typing indicators
Media not displaying correctly
- Verify image URLs are publicly accessible
- Check file size limits (25MB for images)
- Ensure HTTPS URLs are used
- Review supported formats
---
## Limitations
### Platform restrictions
- **24-hour messaging window**: Can only send promotional messages within 24 hours of user
interaction
- **Message tags**: Limited use cases for messages outside 24-hour window
- **Rate limits**: Subject to Facebook's rate limiting policies
- **Content policies**: Must comply with Facebook Community Standards
### Feature limitations
- **File attachments**: Limited file types supported
- **Message length**: Maximum 2000 characters per message
- **Quick replies**: Maximum 13 options
- **Persistent menu**: Maximum 3 top-level items
---
## Resources
### Documentation
- [Facebook Messenger Platform](https://developers.facebook.com/docs/messenger-platform)
- [Platform Policies](https://developers.facebook.com/docs/messenger-platform/policy)
- [Best Practices](https://developers.facebook.com/docs/messenger-platform/introduction/general-best-practices)
### Tools
- [Facebook Page Insights](https://www.facebook.com/help/794890670645072)
- [Meta Business Suite](https://business.facebook.com)
- [Graph API Explorer](https://developers.facebook.com/tools/explorer/)
### Support
- [Facebook Business Help](https://www.facebook.com/business/help)
- Moveo support: support@moveo.ai
---
## Next steps
Once your Messenger integration is active:
1. **Customize your welcome screen** to match your brand
2. **Configure the persistent menu** for easy navigation
3. **Test thoroughly** with different user scenarios
4. **Monitor analytics** to optimize performance
5. **Set up handover rules** for human agent escalation
---
## Front
## Overview
Front integration transforms your shared inbox into an intelligent customer communication hub. By
connecting Moveo with Front, your AI Agent works alongside your team to handle customer inquiries
across multiple channels, from email and SMS to chat and social media, all within your existing
Front workspace.
This integration enables:
- **Unified inbox management** with AI and human agents collaborating
- **Multi-channel support** across email, SMS, chat, and social platforms
- **Intelligent conversation routing** based on tags and inbox rules
- **Seamless handover** between AI and human agents
- **Complete conversation history** maintained in Front
- **Flexible deployment modes** (System or Agent mode)
---
## Prerequisites
Before setting up the Front integration, ensure you have:
✅ **Front account requirements**
- Active Front workspace
- **Company admin** role in your Front account
- Access to integration and bot settings
✅ **Channel setup**
- Configured inboxes for the channels you want to automate
- Appropriate tags for conversation routing (optional)
- Team permissions configured for handover scenarios
✅ **Moveo account setup**
- An active [AI Agent](../ai-agents/overview.md) configured
- An [environment](../environments/overview.md) selected for the integration
:::note
Company admin access is required both for initial setup and for Agent mode
operation.
:::
---
## How it works
Front integration operates through two distinct modes, each with different conversation handling
approaches:
### System Mode (Recommended)
1. **Customer message arrives** in configured Front inbox
2. **Unassigned conversations** are detected by Moveo
3. **AI Agent responds** as a separate system (no teammate seat required)
4. **Conversation remains unassigned** until human intervention needed
5. **Handover adds tag** ("Moveo Handover") for human agent pickup
### Agent Mode
1. **Customer message arrives** in configured Front inbox
2. **AI Agent acts as specified teammate** in your Front workspace
3. **Conversation is assigned** to the AI Agent teammate
4. **AI handles responses** until handover is triggered
5. **Conversation is unassigned** for human agent takeover
Both modes support tag-based filtering for precise conversation routing.
---
## Setup guide
### Step 1: Connect with Front
To connect Moveo with Front, the process is straightforward. First, create a Front integration
inside Moveo and click the **Connect** button. When you are redirected to Front, log in to your
account if you haven't already, and click **Authorize**. Lastly, configure the
[Inboxes](#inbox-configuration) in which you want Moveo to handle conversations.
---
## Configuration options
### Integration mode
Choose between two operational modes:
#### System Mode (Recommended)
- AI Agent operates as a separate system
- No teammate seat required
- Supports most Front channels (except Intercom)
- Conversations remain unassigned
- Best for high-volume automation
#### Agent Mode
- AI Agent acts as specified teammate
- Requires Company admin teammate
- Full channel support including Intercom
- Conversations are assigned/unassigned
- Best for personalized interactions
### Inbox configuration
Select which inboxes Moveo should monitor:
- Choose specific inboxes for AI Agent engagement
- AI Agent handles **unassigned conversations only**
- Configure per-inbox routing rules as needed
### Tag-based routing
Optional tag filtering for precise control:
- Specify tags for AI Agent to engage with
- Leave empty to handle all unassigned conversations
- Combine with inbox selection for advanced routing
- Use for department-specific automation
### Advanced settings
#### Response behavior by mode
**System Integration:**
- AI Agent operates as separate system
- Responses appear from "Moveo System"
- No teammate seat consumed
- Most channels supported (except Intercom)
- Conversations always remain unassigned
**Agent Integration:**
- AI Agent impersonates specified teammate
- Responses appear from chosen teammate
- Requires Company admin teammate
- All channels supported (including Intercom)
- Conversations assigned to AI Agent teammate
#### Handover behavior by mode
**System Handover:**
1. Customer requests human assistance
2. AI Agent acknowledges and responds
3. **"Moveo Handover"** tag is added
4. Conversation remains unassigned
5. Human agents can pick up tagged conversations
**Agent Handover:**
1. Customer requests human assistance
2. AI Agent acknowledges and responds
3. Conversation is **unassigned** from AI Agent
4. Human agents can take over immediately
5. Full context preserved in conversation history
---
## Testing your integration
### Initial testing
1. **Send test messages** to configured inboxes
2. **Verify AI Agent engagement** based on your settings
3. **Test both modes** if considering Agent mode
4. **Validate tag-based routing** if configured
5. **Test handover scenarios** thoroughly
### Test scenarios
✓ **Unassigned conversation handling** ✓ **Tag-based conversation filtering** ✓ **Multi-channel
message processing** ✓ **Handover tag application (System mode)** ✓ **Conversation reassignment
(Agent mode)** ✓ **Response format compatibility**
### Monitoring
- **Front inbox activity** for AI Agent responses
- **Handover success rate** and human pickup time
- **Tag application** accuracy
- **Response quality** across different channels
---
## Common use cases
### Customer support automation
- Automate first-line support across all channels
- Handle common inquiries instantly
- Escalate complex issues with context preservation
- Maintain 24/7 availability
### Multi-channel management
- Unified handling of email, SMS, chat, and social
- Consistent responses across all platforms
- Centralized conversation history
- Team-wide visibility and collaboration
### Department-specific routing
- Use tags to route conversations by department
- Specialized AI Agents for different teams
- Automated triage and categorization
- Efficient resource allocation
### High-volume inbox management
- Process large volumes of routine inquiries
- Reduce human agent workload
- Maintain response time standards
- Scale support without additional headcount
---
## Best practices
### Mode selection
- **Use System mode** for high-volume automation
- **Use Agent mode** when personalization matters
- Consider channel requirements (Intercom needs Agent mode)
- Plan for teammate seat allocation in Agent mode
### Inbox organization
- Start with specific inboxes, expand gradually
- Configure clear inbox naming conventions
- Set up proper team access permissions
- Document inbox purposes for team clarity
### Tag strategy
- Use descriptive, consistent tag naming
- Create tags for different conversation types
- Document tag usage for team alignment
- Regular tag cleanup and optimization
### Handover optimization
- Train AI Agent on clear handover triggers
- Set expectations for human response times
- Monitor handover rates and reasons
- Continuously refine handover criteria
---
## Troubleshooting
AI Agent not responding to messages
- Verify integration is Active in Moveo
- Check that conversations are unassigned in Front
- Confirm inbox is selected in integration settings
- Verify tag requirements are met (if configured)
- Check AI Agent is properly assigned to environment
Handover not working properly
**System Mode:**
- Check if "Moveo Handover" tag is being applied
- Verify human agents can see tagged conversations
- Ensure tag permissions are properly configured
**Agent Mode:**
- Confirm conversation is being unassigned
- Check teammate permissions and availability
- Verify AI Agent teammate has Company admin role
Agent mode teammate issues
- Ensure selected teammate has Company admin role
- Verify teammate is active in Front workspace
- Check that teammate isn't already handling conversations
- Confirm proper integration permissions
Channel not supported errors
- Intercom channel requires Agent mode
- Verify channel is properly connected in Front
- Check if channel supports programmatic responses
- Review Front channel configuration
Conversation not being created
Check this section: [Tags](#tags).
---
## Limitations
### Response type restrictions
- **[Carousels](../ai-agents/responses/carousel.md)**: Not supported
- **[Webviews](../ai-agents/responses/webview.md)**: Not supported
- **[Options](../ai-agents/responses/text.md#options)**: Partially supported
- Text responses and basic formatting fully supported
### Integration constraints
- **System mode**: Cannot access Intercom channel
- **Agent mode**: Requires Company admin teammate
- **Unassigned conversations only**: AI Agent won't engage with assigned conversations
- **Tag dependencies**: Tag-based routing requires proper tag management
### Platform requirements
- Company admin role required for setup and Agent mode
- Front workspace must support integrations
- Channel-specific limitations may apply
### Tags
Tags from Front are automatically forwarded to Moveo. However, Moveo supports a maximum of 25 tags per conversation.
If a Front conversation has more than 25 tags (for example, tags automatically applied by Front rules), the handoff to Moveo will fail. In this case, the Moveo conversation will never be created, and the assignment won't go through.
**How to avoid this issue:**
Make sure that Front conversations have no more than 25 tags before they are passed to Moveo. Review your Front rules to ensure they don't assign more than 25 tags at once.
---
## Resources
### Documentation
- [Front Help Center](https://help.front.com)
- [Front Integrations Guide](https://help.front.com/t/72n9vk/integrations)
- [Front API Documentation](https://dev.front.com)
### Support
- [Front Community](https://community.front.com)
- [Front Support](https://help.front.com/t/x6k9z2/contact-support)
- Moveo support: support@moveo.ai
---
## Next steps
Once your Front integration is active:
1. **Choose optimal integration mode** based on your needs
2. **Configure inbox and tag settings** for precise routing
3. **Test thoroughly** across all your channels
4. **Train your team** on handover procedures
5. **Monitor performance** and optimize AI Agent responses
---
## Infobip RCS
## Overview
Moveo supports Rich Communication Services (RCS) conversations between your AI Agent and end-users by integrating with Infobip, a global messaging platform. RCS is the next generation of SMS that offers rich media capabilities including images, videos, carousels, quick replies, and interactive buttons. This integration enables your AI Agent to deliver engaging, interactive messaging experiences that go beyond traditional text-based SMS.
Your AI Agent can send outbound RCS messages with rich content and respond to inbound RCS messages using a registered RCS sender, fully managed through your Infobip account.
:::tip Recommended reading
Review the [Infobip documentation](https://www.infobip.com/docs) to understand platform capabilities and regional requirements.
:::
## Create and Configure an Infobip Account
To use Infobip RCS with Moveo, you need an active Infobip account and a registered RCS sender. Follow these steps:
1. Go to [infobip.com](https://www.infobip.com/) and select **Start free** or **Create account**.
2. Complete the sign-up process by entering your business details and verifying your email address.
3. After logging in, [add funds](https://www.infobip.com/docs/essentials/manage-my-account/payments#add-funds) to your Infobip account to enable messaging services.
4. Request an **RCS sender**:
- Review Infobip Resources to understand senders and identifiers: [Resources](https://www.infobip.com/docs/resources).
- Submit a request via [My Requests](https://www.infobip.com/docs/myrequests/submit-myrequests). Choose the RCS channel and request a branded RCS sender.
5. Complete any required verification and launch steps coordinated by Infobip and mobile network operators (MNOs) after your sender request is submitted.
:::important
RCS is not available in all countries and requires carrier support. Contact your Infobip account manager for more information.
:::
### Understanding RCS Capabilities
RCS offers several advantages over traditional SMS:
- **Rich Media**: Send images, videos, and audio files
- **Interactive Elements**: Include quick reply buttons, suggested actions, and carousels
- **Branded Messaging**: Display your business name and logo
- **Read Receipts**: Know when messages are delivered and read
To use Moveo, your Infobip account must have an approved **RCS sender**. Traditional SMS-only numbers are not used for this integration.
---
## Connect the Infobip RCS Sender With Moveo
Once your RCS sender is available for testing or approved, connect it to Moveo by following these steps.
### Gather Required Information
You need the following details from your Infobip account:
#### 1. API key
You need to check these permissions in your API key:
- `rcs:manage`
- `subscriptions:manage`
:::tip
Use the **default API key** visible on the Infobip homepage after logging in.
:::
#### 2. Base URL
The **Base URL** of your Infobip environment (for example, `https://xyz.api.infobip.com`).
#### 3. Sender Name
The **Sender Name** of your registered RCS sender. In the Infobip web interface, navigate to **Channels and Numbers → Channels → RCS Business Messaging → Senders**. From the list of senders, find the one you want to connect with Moveo and copy the name.
### Complete the Setup in Moveo
To set up the Infobip RCS integration, go to the Moveo platform and fill the fields with the information gathered in the previous step.
1. In the Moveo platform, go to **Integrations → Infobip RCS → Connect**.
2. Enter the required fields using the details from your Infobip account.
3. Click **Save** to complete the setup.
Your AI Agent can now send and receive RCS messages using the connected RCS sender, enabling rich, interactive conversations with your users.
---
## Test and Launch Your Sender
After you complete your sender registration though Infobip and and the connection in Moveo, to go live with RCS Business Messaging follow the steps described on [Infobip](https://www.infobip.com/docs/rcs/get-started).
### Test Connection
Once the sender status is **In testing**, you can add test devices and send test messages.
1. Prepare a test device with RCS enabled (Android with Google Messages, or iPhone with iOS 18+ and RCS enabled in Settings).
2. Add safelisted test device numbers under your sender’s **Test devices** tab. Accept the invitation for testing the sender sent by Infobip.
3. Send a campaign message to the safelisted test device using [Campaigns](../campaigns/campaigns.md) and selecting the RCS sender.
### Verification and Launch
Provide brand, opt‑in, and usage details for launch approval. Mobile network operators may require additional checks. After approval, the sender is live and you can send production traffic without additional testing.
:::caution
To ensure compliance with RCS requirements, follow Infobip's official guidance. See [Compliance and guidelines](https://www.infobip.com/docs/rcs/guidelines-and-compliance). Non-compliance may result in suspension or blocking.
:::
---
## Frequently Asked Questions
**Do I need a phone number for RCS with Infobip?**
No. Infobip uses **RCS senders** (brand identities) rather than phone numbers for RCS. You need to register an RCS sender via [My Requests](https://www.infobip.com/docs/myrequests/submit-myrequests) or follow the process described [here](https://www.infobip.com/docs/rcs/get-started#registration).
**What if RCS is not available in my target country?**
RCS availability depends on carrier support. If RCS is not available, consider using [Infobip SMS](infobip-sms.md) as an alternative.
**Do I need to configure anything on Infobip to receive RCS messages?**
You just need to register and launch your RCS sender. After that, once you connect the RCS sender with Moveo, Moveo receives inbound RCS messages automatically by creating a [subscription](https://www.infobip.com/docs/cpaas-x/subscriptions-management).
**What types of rich content can I send via RCS?**
RCS supports images, videos, audio files, carousels, buttons, and more. The exact capabilities depend on the recipient's device and carrier support. You can find a list of supported features per carrier [here](https://www.infobip.com/docs/rcs/feature-parity).
---
## Limitations
### Platform constraints
- **Carrier dependency** - RCS availability depends on mobile network operator support in each country
- **Device requirements** - Recipients need RCS-enabled devices (Android with Google Messages or iPhone with iOS 18+) and a carrier that supports RCS
- **Fallback behavior** - Messages may not have SMS fallback; consider using [Infobip SMS](./infobip-sms.md) for broader reach
### Content limitations
- **File size limits** - Media files are subject to carrier-specific size restrictions
- **Feature parity** - Not all RCS features are supported by all carriers
- **Brand verification** - Sender registration and brand verification required before going live
---
## Next steps
- [Infobip SMS](./infobip-sms.md) - Set up SMS as a fallback channel
- [Campaigns](../campaigns/campaigns.md) - Send outbound RCS campaigns
- [AI Agents overview](../ai-agents/overview.md) - Configure your agent for RCS conversations
- [Analytics](../analytics/overview.md) - Monitor RCS message performance
---
## Infobip SMS
## Overview
Infobip SMS integration transforms your AI Agent into a powerful SMS communication tool, enabling
two-way conversations with customers through one of the world's leading cloud communication
platforms. Infobip connects your business to mobile carriers globally, eliminating the need for
direct telecom agreements while providing reliable, scalable SMS messaging.
This integration enables:
- **Two-way SMS conversations** with automated AI Agent responses
- **Global reach** through Infobip's carrier network coverage
- **Dedicated phone numbers** for your business messaging
- **Enterprise-grade reliability** with high delivery rates
- **Compliance support** for regional SMS regulations
- **Seamless handover** to human agents when needed
:::tip Recommended reading
Review the [Infobip documentation](https://www.infobip.com/docs) to
understand platform capabilities and regional requirements.
:::
---
## Prerequisites
Before setting up the Infobip SMS integration, ensure you have:
✅ **Business requirements**
- Active business with legitimate SMS use case
- Business registration and contact information
- Funds available for SMS messaging costs
✅ **Infobip account setup**
- Active Infobip account with verified business details
- SMS-capable phone number purchased through Infobip
- API key with required permissions
✅ **Regional compliance**
- Understanding of local SMS regulations
- Required registrations (e.g., 10DLC for US)
- Sender ID registration if applicable
✅ **Moveo account setup**
- An active [AI Agent](../ai-agents/overview.md) configured
- An [environment](../environments/overview.md) selected for the integration
:::important US Requirements For United States messaging, 10DLC registration is mandatory. See the
[10DLC registration guide](https://www.infobip.com/docs/10dlc/10dlc-registration).
:::
---
## How it works
The Infobip SMS integration creates a seamless bridge between SMS messages and your AI Agent:
1. **Customer sends SMS** to your dedicated Infobip number
2. **Infobip receives message** and forwards to Moveo via webhook
3. **AI Agent processes** the message using your configured knowledge
4. **Response is generated** based on customer inquiry
5. **SMS is sent back** through Infobip's delivery network
6. **Conversation continues** with full context maintained
7. **Handover available** to human agents when AI cannot assist
All messages are processed through Infobip's secure infrastructure with real-time delivery tracking
and comprehensive analytics.
---
## Setup guide
### Step 1: Create and configure Infobip account
To use Infobip with Moveo, you need an active Infobip account and a number that supports two-way
SMS. Follow these steps:
1. Go to [infobip.com](https://www.infobip.com/) and select **Start free** or **Create account**.
2. Complete the sign-up process by entering your business details and verifying your email address.
3. After logging in,
[add funds](https://www.infobip.com/docs/essentials/manage-my-account/payments#add-funds) to your
Infobip account to enable messaging services.
4. In the **Numbers** section,
[purchase a number](https://www.infobip.com/docs/numbers/getting-started#numbers-over-web-interface)
with **SMS capability**.
5. Select a number that supports your target region. Depending on the country, Infobip may require
additional **sender ID registration** or **number activation**.
6. Complete any required verification steps based on your region and use case.
:::important For United States 10DLC numbers, number registration is mandatory. See the
[10DLC registration guide](https://www.infobip.com/docs/10dlc/10dlc-registration) for more
information.
:::
#### Choosing the right number type
Infobip offers several types of numbers depending on your region and use case. For the United
States, see
[10DLC vs. short codes vs. toll-free numbers](https://www.infobip.com/blog/10dlc-vs-short-codes-vs-toll-free-numbers)
for a detailed comparison.
To use Moveo, your number must support **two-way SMS**. One-way messaging or voice-only numbers are
not supported.
### Step 2: Connect with Moveo
Once your number is active, connect it to Moveo by following these steps.
#### Gather required information
You need the following details from your Infobip account:
#### 1. API key
You need to check these permissions in your API key:
- `sms:manage`
- `subscriptions:manage`
- `numbers:manage`
:::tip
You can use the **default API key** visible on the Infobip homepage after logging in.
:::
#### 2. Base URL
**Base URL** of your Infobip environment (for example, `https://xyz.api.infobip.com`).
#### 3. Number ID
**Number ID** of your purchased phone number. To find this, go to the **Numbers** tab in Infobip,
click your number, and copy the **ID** field.
#### Complete Moveo setup
Now to set up our Infobip SMS integration, we need to go to the Moveo platform and fill the fields
with the information we gathered in the previous step.
1. In the Moveo platform, go to **Integrations → SMS**.
2. Click **Add Integration** and select **Infobip**.
3. Enter the required fields using the details from your Infobip account.
4. Click **Save** to complete the setup.
Your AI Agent can now send and receive SMS messages using the connected number.
---
## Configuration options
### Number management
- **Dedicated numbers**: Assign specific numbers to different AI Agents or use cases
- **Sender ID**: Configure custom sender identification where supported
- **Regional compliance**: Ensure proper registration for target markets
- **Number pooling**: Use multiple numbers for high-volume messaging
### Message settings
- **Character limits**: Configure message length and splitting behavior
- **Delivery reports**: Enable tracking for message delivery status
- **Retry logic**: Set up automatic retry for failed messages
- **Rate limiting**: Configure sending frequency per regulations
### Security and authentication
- **API key management**: Secure key storage and rotation
- **Webhook validation**: Verify incoming message authenticity
- **IP whitelisting**: Restrict API access to specific addresses
- **SSL/TLS encryption**: Ensure secure message transmission
---
## Testing your integration
### Initial testing
1. **Send test SMS** to your Infobip number from a mobile phone
2. **Verify AI Agent response** arrives correctly
3. **Test message delivery** and timing
4. **Check character encoding** for special characters and emojis
5. **Validate handover scenarios** if configured
### Test scenarios
✓ **Basic conversation flow** ✓ **Long message handling** (concatenated SMS) ✓ **Special character
support** ✓ **International number testing** ✓ **Error handling and fallbacks** ✓ **Delivery report
processing**
### Monitoring and analytics
- **Message delivery rates** through Infobip dashboard
- **Response time metrics** for AI Agent processing
- **Cost tracking** for SMS usage and optimization
- **Conversation completion rates** and user satisfaction
---
## Common use cases
### Customer support via SMS
- Handle support requests through familiar SMS interface
- Provide instant answers to common questions
- Collect customer information efficiently
- Escalate to human agents when needed
### Appointment and booking management
- Send appointment confirmations and reminders
- Handle booking modifications and cancellations
- Provide location and timing information
- Collect feedback after appointments
### Order and delivery notifications
- Send order confirmations and updates
- Provide tracking information
- Handle delivery scheduling
- Process returns and refund requests
### Marketing and engagement
- Send promotional messages (with consent)
- Conduct surveys and collect feedback
- Share product information and offers
- Build customer relationships through conversation
---
## Best practices
### Message optimization
- Keep messages concise and clear
- Use plain text for maximum compatibility
- Structure information logically
- Provide clear next steps or options
### Compliance and regulations
- Obtain proper consent for marketing messages
- Provide easy opt-out mechanisms
- Follow regional SMS regulations
- Register numbers appropriately
### User experience
- Set clear expectations about response times
- Provide help commands and instructions
- Handle errors gracefully with helpful messages
- Maintain conversation context effectively
### Cost optimization
- Monitor message length to avoid concatenation
- Use message templates for common responses
- Implement smart routing to reduce costs
- Track and analyze usage patterns
---
## Troubleshooting
Messages not being delivered
- Check Infobip account balance and funding
- Verify API key permissions and validity
- Confirm number is properly registered and active
- Review delivery reports in Infobip dashboard
- Test with different mobile carriers
AI Agent not responding
- Verify integration is Active in Moveo
- Check webhook connectivity and configuration
- Confirm AI Agent is assigned to environment
- Test with simple messages first
- Review message format and encoding
Number registration issues
- Review regional registration requirements
- For US: Complete 10DLC registration process
- Provide all required business documentation
- Allow sufficient time for approval process
- Contact Infobip support for status updates
High message costs
- Review message length and concatenation
- Optimize AI Agent responses for brevity
- Check routing and carrier selection
- Monitor usage patterns and peak times
- Consider number type optimization
Character encoding problems
- Test with different character sets
- Verify Unicode support configuration
- Check emoji and special character handling
- Review message encoding settings
- Test across different mobile devices
---
## Limitations
### Platform restrictions
- **Two-way SMS required**: Voice-only numbers not supported
- **Character limits**: SMS length restrictions apply
- **Regional availability**: Some countries have limited support
- **Carrier dependencies**: Delivery rates vary by mobile operator
### Integration constraints
- **Funding required**: Must maintain positive account balance
- **Rate limiting**: Subject to carrier and regulatory limits
- **Registration requirements**: Business verification needed for some regions
- **Number provisioning**: Availability varies by region
---
## Frequently asked questions
Can I use an existing Infobip number?
Yes, if the number supports **two-way SMS** and meets local compliance requirements.
What about US messaging requirements?
You must register your 10DLC number or use a short code or toll-free number. See the
[10DLC registration guide](https://www.infobip.com/docs/10dlc/10dlc-registration).
Can I use the service without adding credit?
No. You must add credit to your Infobip account before sending SMS messages.
Is voice capability required for the number?
No. Only **SMS capability** is required for this integration.
Do I need to configure webhooks in Infobip?
No. Once integrated, Moveo handles inbound message processing automatically.
---
## Resources
### Documentation
- [Infobip SMS API](https://www.infobip.com/docs/sms)
- [10DLC Registration Guide](https://www.infobip.com/docs/10dlc/10dlc-registration)
- [Number Types Comparison](https://www.infobip.com/blog/10dlc-vs-short-codes-vs-toll-free-numbers)
### Tools
- [Infobip Developer Portal](https://dev.infobip.com)
- [Message Testing Tools](https://www.infobip.com/docs/essentials/test-your-integration)
- [Delivery Reports Dashboard](https://www.infobip.com/docs/sms/reports)
### Support
- [Infobip Support Center](https://help.infobip.com)
- [Infobip Community](https://community.infobip.com)
- Moveo support: support@moveo.ai
---
## Next steps
Once your Infobip SMS integration is active:
1. **Complete number registration** for all target markets
2. **Optimize AI Agent responses** for SMS format constraints
3. **Set up monitoring** for delivery rates and costs
4. **Test thoroughly** across different carriers and regions
5. **Scale gradually** while monitoring performance and compliance
---
---
## Instagram
Moveo.AI provides an out-of-the-box integration with Instagram, enabling your AI Agent to handle customer conversations through Instagram Direct Messages.
## How it works
When you connect your Instagram account to Moveo:
1. Users send messages to your Instagram business profile
2. Moveo receives messages via the Meta (Facebook) API
3. Your AI Agent processes the message and generates a response
4. The response appears in the user's Instagram Direct Messages
This integration uses Meta's Messenger Platform, which is why you need a Facebook Page linked to your Instagram account.
## Connect your Page
### Before you begin
- Make sure that you have an
[Instagram **professional** account](https://www.facebook.com/help/instagram/138925576505882).
- You need to have a Facebook Page
[**linked with your Instagram account**](https://www.facebook.com/business/help/connect-instagram-to-page).
- Make sure that you have [Admin](https://www.facebook.com/help/289207354498410) access in the
Facebook Page that is connected to your Instagram account.
- Select an [environment](../environments/overview.md) in which you wish to connect your Instagram
account.
Depending on whether you have connected Facebook or Instagram to Moveo before, follow the
corresponding guides outlined below:
- [**First time** connecting an Instagram account](facebook-messenger.md#first-time-connection)
- [Connecting **more than one** Instagram accounts](facebook-messenger.md#adding-additional-pages)
## First time connecting an Instagram account
Follow the steps outlined below:
1. Click **Connect** to redirect to the _Meta Dialog Window_.
2. In the _Meta Dialog Window_, select **only one** Instagram account **and** its connected Facebook
Page and grant **all** permissions to Moveo.
3. Once you complete the process in the _Meta Dialog Window_, you will be redirected back to Moveo,
where you can [configure your integration](#configure-your-integration).
## Connecting more than one Instagram accounts
If you have already connected an Instagram account to Moveo, then you **must keep your previously
connected Instagram accounts and their linked Facebook Pages selected** in the _Meta Dialog Window_
to preserve an active connection. Follow the steps outlined below:
1. Click **Connect** to redirect to the _Meta Dialog Window_.
2. In the _Meta Dialog Window_, select **the new** Instagram account and its linked Facebook Page,
while **keeping the old one(s) selected**. Grant **all** permissions to Moveo.
3. Once you complete the process in the _Meta Dialog Window_, you will be redirected back to Moveo,
where you can [configure your integration](#configure-your-integration).
---
## Configure your integration
Now that you have successfully connected your Instagram account to Moveo, it's time to configure it
to meet your needs. Unlike Facebook Messenger, there are not many configuration options yet.
### Status
To start receiving messages, you need to make your integration `Active`.
### Advanced security settings
In some cases, the webview may need to exchange context with the AI Agent. To ensure that the data
is secure, you need to create a pair of RS256 private/public keys. Add your public key in your
integration in PEM format.
---
## Troubleshooting
Not Page Admin error
You need Admin access to the Facebook Page linked to your Instagram account:
- Check your role in Facebook Page settings
- Request Admin access from current Page admin
- Ensure Page is properly linked to Instagram account
- Verify you're using the correct Facebook account
Permission errors
All requested permissions must be granted in the Meta Dialog Window:
- Review each permission carefully
- Ensure all checkboxes are selected
- Don't skip any permission requests
- Re-authenticate if permissions were denied
Multiple account connection issues
When connecting additional accounts:
- Keep ALL previously connected accounts selected
- Add only ONE new Instagram account
- Select the corresponding Facebook Page
- Don't deselect existing connections
Messages not being received
- Verify integration is set to Active in Moveo
- Check Instagram account is properly linked to Facebook Page
- Ensure webhook permissions are granted
- Confirm AI Agent is assigned to the environment
Responses not sending
- Check Instagram account status and restrictions
- Verify Facebook Page is published and active
- Review Meta app permissions and status
- Ensure no rate limits are being hit
---
## Limitations
### Platform restrictions
- **Professional account required**: Cannot use personal Instagram accounts
- **Facebook Page dependency**: Must maintain active Facebook Page connection
- **Meta's policies**: Subject to Instagram and Facebook business policies
- **Message types**: Limited to text and basic media formats
### Integration constraints
- **One account per environment**: Each Moveo environment supports one Instagram connection
- **Admin access required**: Must maintain Admin role on connected Facebook Page
- **Page connection**: Instagram account must remain linked to Facebook Page
- **Business verification**: Some features require Meta Business verification
---
## Resources
### Documentation
- [Instagram Business Guide](https://business.instagram.com/getting-started)
- [Facebook Page Management](https://www.facebook.com/business/help/389645064451355)
- [Meta Business Platform](https://developers.facebook.com/docs/instagram-basic-display-api/)
### Tools
- [Instagram Professional Dashboard](https://www.facebook.com/business/tools/instagram-business)
- [Facebook Page Settings](https://www.facebook.com/help/289207354498410)
- [Meta Business Manager](https://business.facebook.com)
### Support
- [Instagram Business Help](https://help.instagram.com/business)
- [Meta Business Help](https://www.facebook.com/business/help)
- Moveo support: support@moveo.ai
---
## Next steps
Once your Instagram integration is active:
1. **Optimize your business profile** for customer engagement
2. **Test thoroughly** with different message types
3. **Configure handover rules** for complex inquiries
4. **Monitor Instagram insights** to track performance
5. **Train your team** on Instagram-specific workflows
---
## Intercom
## Overview
Intercom has partnered with Moveo.AI to create a powerful integration that adds an intelligent AI
Agent to your customer support team. This partnership enables seamless collaboration between AI and
human agents, providing customers with instant, accurate responses while maintaining the personal
touch of human support when needed.
This integration enables:
- **AI-powered teammate** that works alongside your human agents
- **Seamless conversation handover** between AI and human agents
- **24/7 customer support** with intelligent automation
- **Unified inbox management** with all conversations in Intercom
- **Custom workflows** for routing and escalation
---
## Prerequisites
Before setting up the Intercom integration, ensure you have:
✅ **Intercom requirements**
- Active Intercom workspace with admin access
- Ability to add new teammates to your workspace
- Access to conversation rules and workflows
✅ **Email account for AI Agent**
- Dedicated, functional email address for your AI Agent
- Access to receive and respond to invitation emails
- Unique email not used for any other Intercom teammate
✅ **Moveo account setup**
- An active [AI Agent](../ai-agents/overview.md) configured
- An [environment](../environments/overview.md) selected for the integration
---
## How it works
The Intercom integration treats your AI Agent as a teammate in your Intercom workspace:
1. **Customer sends message** through Intercom Messenger
2. **Workflow rules** assign conversation to AI Agent
3. **AI Agent processes** and responds based on your configuration
4. **Conversation continues** with AI handling routine inquiries
5. **Handover triggers** when human assistance is needed
6. **Unassigned inbox** receives escalated conversations
7. **Human agents** pick up seamlessly with full context
All interactions are initiated through and managed by Intercom, maintaining your existing workflows.
---
## Video tutorial
[](https://www.youtube.com/watch?v=JDiz4OhMO_0)
---
## Setup guide
### Part 1: Intercom configuration
1. Create a functional email account for your assistant. Each assistant must have a valid, unique
email address before it can be added to a team in Intercom.
2. From your Intercom workspace, add the assistant to your team as a new agent. Go to the teammate
settings page in your Intercom workspace, and invite the assistant as a new agent by adding the
email you created in the previous step to the invite field.
3. From the assistant email account you created earlier, find the invitation from Intercom. Click
the link in the email to join the team. Sign up using the assistant's functional email address,
and then join the team.
4. Optional: Update the profile for your assistant. You can edit the name and profile picture for
your assistant. This profile represents the assistant in private agent communications within your
workspace, and in public interactions with customers through your Intercom apps. Create a profile
that reflects your brand.
### Part 2: Moveo configuration
1. Create an [AI Agent](../ai-agents/overview.md).
2. Create an [environment](../environments/overview.md) and connect the above AI Agent to it.
3. Add an Intercom Integration by redirecting to Intercom.
:::caution
In your Intercom app, you need to log in from the account of your assistant.
:::
---
## Configuration options
### Workflow configuration
To test your integration, you need to modify your Intercom rules in order to assign the Moveo AI
Agent to the conversations you wish. The following image shows an example where logged-in users are
handled by Moveo, while logged-out users are shown the prompt to log in or sign up.
When a handover is taking place, the assistant
transfers the conversation to the `Unassigned` Inbox, in order for other live agents to take over
the conversation.
### Custom attributes
#### Automatic response tracking
Moveo offers a specialized attribute designed to notify Intercom when the assistant has responded
**more than** once. This feature can be valuable in scenarios where you intend to present a survey
or pose a question to the user. To enable and use the custom attribute, follow the instructions
below:
1. In your Intercom account, go to the **Conversation data** and select **Create a new conversation
attribute**. Set the format to **boolean** and assign the name as follows:
`Moveo AI: Replied twice`
Include a description and save the attribute.
2. Initialize the attribute. In the trigger rule, you initialize the conversation. Set the default
value of the attribute to `false`.
3. Create your feedback rule, enabling it to only trigger if the attribute is `true`.
Here are some screenshots to help you understand how to set up this custom attribute. It's designed
to trigger a survey for users who have asked at least two questions to Moveo but haven't responded
afterwards.
### Media handling
Moveo's AI Agent processes media uploads as text with URLs:
#### How media upload works
1. User or agent uploads a file in Intercom messenger
2. Moveo converts it to text containing the attachment URL
3. AI Agent processes based on configured intents and dialogs
#### Configuration for media handling
Create an [intent](../ai-agents/intents.md) with these training phrases:
`Visitor uploaded media URL: `
`Visitor uploaded media URL: https://downloads.intercomcdn.com/i/o/871967244/4b5102e0e8add69b54dbc896/example_attachment.jpg`
Then create a [dialog](../ai-agents/dialogs.md) to define how your AI Agent responds to
media uploads.
---
## Testing your integration
### Initial testing
1. **Send test message** as a customer to your Intercom messenger
2. **Verify AI Agent assignment** through your workflow rules
3. **Check response quality** and timing
4. **Test handover** by triggering escalation scenarios
### Test scenarios
✓ **Basic conversation flow** ✓ **Multiple question exchanges** ✓ **Media upload handling** ✓
**Handover to human agents** ✓ **Custom attribute triggers** ✓ **After-hours responses**
---
## Common use cases
### Customer support automation
- Answer frequently asked questions instantly
- Guide users through troubleshooting steps
- Collect information before human handover
- Provide 24/7 first-line support
### Lead qualification
- Engage website visitors immediately
- Qualify leads with targeted questions
- Route qualified leads to sales team
- Capture contact information automatically
### User onboarding
- Welcome new users with personalized messages
- Guide through initial setup steps
- Answer product questions in real-time
- Schedule demos or training sessions
### Survey and feedback collection
- Trigger surveys after AI Agent interactions
- Collect NPS scores automatically
- Gather product feedback
- Route feedback to appropriate teams
---
## Best practices
### AI Agent profile setup
- Use a clear, recognizable name for your AI Agent
- Add a professional profile picture
- Write a description that sets expectations
- Configure appropriate working hours
### Workflow optimization
- Start with simple routing rules
- Test thoroughly before complex workflows
- Use custom attributes for advanced routing
- Monitor and adjust based on performance
### Conversation management
- Set clear handover criteria
- Configure appropriate response times
- Use the Unassigned inbox for escalations
- Maintain conversation context during handovers
### Performance monitoring
- Track AI Agent response metrics
- Monitor handover rates
- Review conversation quality regularly
- Collect customer feedback on AI interactions
---
## Troubleshooting
AI Agent not receiving messages
- Verify AI Agent is logged into Intercom
- Check workflow rules are properly configured
- Ensure integration is set to Active in Moveo
- Confirm AI Agent has proper permissions
Handover not working properly
- Check that Unassigned inbox is configured
- Verify human agents are available
- Review handover triggers in dialogs
- Ensure proper workflow rules for escalation
Custom attribute not triggering
- Verify attribute name matches exactly: "Moveo AI: Replied twice"
- Check attribute is initialized to `false` in trigger rule
- Ensure feedback rule checks for `true` value
- Test with multiple message exchanges
Media uploads not processed
- Verify intent is configured with proper training phrases
- Check dialog handles media URL patterns
- Test with different file types
- Review URL format in received messages
---
## Limitations
### Platform constraints
- AI Agent requires dedicated email address
- Cannot use same email for multiple workspaces
- Limited to text-based interactions
- Media files converted to URL references
### Integration requirements
- Must maintain AI Agent as active teammate
- Workflow rules required for proper routing
- Custom attributes need exact naming
- Handover requires Unassigned inbox setup
---
## Resources
### Documentation
- [Intercom Teammates Guide](https://www.intercom.com/help/en/articles/179-add-remove-and-manage-teammates)
- [Workflow Automation](https://www.intercom.com/help/en/articles/2806696-workflows-automate-repetitive-tasks)
- [Custom Attributes](https://www.intercom.com/help/en/articles/179-create-and-manage-custom-data-attributes)
### Support
- [Intercom Help Center](https://www.intercom.com/help)
- Moveo support: support@moveo.ai
---
## Next steps
Once your Intercom integration is active:
1. **Customize AI Agent profile** to match your brand
2. **Configure workflow rules** for optimal routing
3. **Set up custom attributes** for advanced features
4. **Train your team** on AI Agent capabilities
5. **Monitor performance** and optimize responses
---
## Integrations overview
Integrations connect your AI Agent to the communication channels your customers already use. Once connected, your agent receives messages, processes them, and responds automatically—whether through web chat, messaging apps, SMS, email, or voice.
In the Moveo platform UI, integrations are also called **Connections**.
## Web chat
Embed your AI Agent directly on your website or application.
| Channel | Description |
|---------|-------------|
| [Web](./web/getting-started.md) | Customizable chat widget for websites and web applications |
## Messaging apps
Meet customers on the messaging platforms they use daily.
| Channel | Description |
|---------|-------------|
| [WhatsApp](./whatsapp) | Reach customers on the world's most popular messaging app |
| [Facebook Messenger](./facebook-messenger) | Connect through Facebook Pages |
| [Instagram](./instagram-messenger) | Handle Direct Messages from your business profile |
| [Viber](./viber) | Engage users on Viber |
## SMS & RCS
Send and receive text messages with your customers.
| Channel | Description |
|---------|-------------|
| [Infobip SMS](./infobip-sms.md) | SMS messaging via Infobip |
| [Infobip RCS](./infobip-rcs.md) | Rich messaging with images, buttons, and carousels |
| Twilio SMS | SMS messaging via Twilio *(coming soon)* |
| Telnyx SMS | SMS messaging via Telnyx *(coming soon)* |
## Email
Handle customer inquiries through email conversations.
| Channel | Description |
|---------|-------------|
| [Email](./email) | Email-based customer conversations |
## Help desk platforms
Integrate with your existing customer support tools.
| Platform | Description |
|----------|-------------|
| [Intercom](./intercom) | Customer messaging and support |
| [Zendesk Chat](./zendesk) | Zendesk live chat |
| [Sunshine Conversations](./sunco) | Zendesk omnichannel messaging |
| [Front](./front.md) | Shared inbox for teams |
## Sales & outreach
Automate customer engagement in your sales workflows.
| Platform | Description |
|----------|-------------|
| [Smartlead](./smartlead.md) | Sales automation and outreach |
## Voice
Enable phone-based interactions with your AI Agent.
| Channel | Description |
|---------|-------------|
| [Telnyx Voice](./telnyx-voice.md) | Phone call handling via Telnyx |
| [Twilio Voice](./twilio-voice.md) | Phone call handling via Twilio |
## Team collaboration
Deploy your AI Agent in internal communication tools.
| Platform | Description |
|----------|-------------|
| [Slack](./slack.md) | Slack workspace integration |
## Custom integrations
Build custom connections using the REST API.
| Channel | Description |
|---------|-------------|
| [Custom](/api/custom-integration/custom-integration-overview) | Connect any system via REST API and webhooks |
## Next steps
- [Web chat setup](./web/getting-started.md) - Get started with the most common integration
- [WhatsApp setup](./whatsapp) - Connect to WhatsApp Business
- [Environments](../environments/overview.md) - Understand how integrations work with environments
- [AI Agents](../ai-agents/overview.md) - Configure the agent that powers your integrations
---
## Slack
## Overview
Slack integration enables your AI Agent to communicate with team members and customers directly within Slack workspaces. As one of the most widely used workplace communication platforms, Slack provides a familiar environment where your AI Agent can handle inquiries, automate workflows, and provide instant support through direct messages and channel mentions.
This integration enables:
- **Direct message support** through the Messages tab in your bot's App Home
- **Channel mentions** to trigger AI Agent responses with @mentions
- **Rich message formatting** with Slack's native message capabilities
- **File sharing** for sending and receiving documents
- **Interactive components** including buttons and shortcuts
---
## Prerequisites
Before setting up the Slack integration, ensure you have:
✅ **Slack requirements**
- Slack workspace with administrative access
- Permission to install apps to your workspace
- [Slack API](https://api.slack.com/apps) account access
✅ **Moveo account setup**
- An active [AI Agent](../ai-agents/overview.md) configured
- An [environment](../environments/overview.md) selected for the integration
---
## How it works
The Slack integration operates through Slack's Events API and Bot User functionality:
1. **User messages bot** via direct message or @mention in a channel
2. **Slack sends event** to Moveo via webhook
3. **AI Agent processes** the message and generates a response
4. **Response is delivered** back through Slack's messaging API
5. **Interactive elements** can trigger additional AI Agent flows
6. **Handover possible** to human agents when needed
All messages are processed securely with Slack's signing secret verification ensuring message authenticity.
---
## Setup guide
The integration requires configuration in both the Slack API platform and Moveo.
### Step 1: Create a Slack app
1. Navigate to [api.slack.com/apps](https://api.slack.com/apps)
2. Click **Create New App**
3. Select **From scratch**
4. Enter your app name and select the workspace to develop in
5. Click **Create App**
### Step 2: Customize your app
1. In the **Basic Information** section, customize your app's display settings
2. Add an app icon and description
3. Configure the app's color scheme to match your brand
### Step 3: Configure OAuth permissions
1. Navigate to **OAuth & Permissions** in the sidebar
2. Scroll to **Scopes** section
3. Under **Bot Token Scopes**, add the following permissions:
| Permission | Description |
| ---------------------- | ----------------------------------------------- |
| `app_mentions:read` | View messages that directly mention your bot |
| `channels:history` | View messages in public channels |
| `chat:write` | Send messages as the bot |
| `chat:write.customize` | Send messages with a custom username and avatar |
| `files:read` | View files shared in channels and conversations |
| `files:write` | Upload, edit, and delete files |
| `groups:history` | View messages in private channels |
| `im:history` | View messages in direct messages |
| `im:write` | Start direct messages with users |
| `mpim:history` | View messages in group direct messages |
| `users:read` | View users in the workspace |
| `users:read.email` | View email addresses of users |
| `users:write` | Set user presence |
### Step 4: Install app to workspace
1. Scroll to the top of the **OAuth & Permissions** page
2. Click **Install to Workspace**
3. Review the permissions and click **Allow**
4. Copy the **Bot User OAuth Token** that appears after installation
### Step 5: Copy credentials
1. Navigate to **Basic Information** in the sidebar
2. Under **App Credentials**, locate the **Signing Secret**
3. Click **Show** and copy the signing secret
4. Keep both the signing secret and bot OAuth token ready for the next step
### Step 6: Configure App Home
1. Navigate to **App Home** in the sidebar
2. Enable **Always Show My Bot as Online**
3. Under **Show Tabs**, enable **Messages Tab**
4. Check **Allow users to send Slash commands and messages from the messages tab**
---
## Connect with Moveo
### Step 1: Create the integration
1. In Moveo, navigate to **Connections**
2. Locate and select **Slack**
3. Click **Connect**
### Step 2: Configure credentials
1. Paste the **Signing Secret** from your Slack app
2. Paste the **Bot User OAuth Token**
3. Configure additional settings as needed
4. Click **Save**
5. Copy the **Callback URL** provided by Moveo
### Step 3: Activate the integration
Toggle the integration status to **Active**.
---
## Enable event subscriptions
Return to your Slack app configuration to complete the webhook setup.
### Step 1: Configure Event Subscriptions
1. Navigate to **Event Subscriptions** in the sidebar
2. Toggle **Enable Events** to On
3. Paste the Moveo callback URL into the **Request URL** field
4. Wait for Slack to verify the URL (shows "Verified" checkmark)
### Step 2: Subscribe to bot events
Under **Subscribe to bot events**, add the following events:
| Event Name | Description | Required Scope |
| ------------------ | ----------------------------------------------------------------- | ------------------- |
| `app_mention` | Subscribe to only the message events that mention your app or bot | `app_mentions:read` |
| `message.channels` | A message was posted to a channel | `channels:history` |
| `message.groups` | A message was posted to a private channel | `groups:history` |
| `message.im` | A message was posted in a direct message channel | `im:history` |
| `message.mpim` | A message was posted in a multiparty direct message channel | `mpim:history` |
Click **Save Changes** after adding all events.
### Step 3: Enable Interactivity
1. Navigate to **Interactivity & Shortcuts** in the sidebar
2. Toggle **Interactivity** to On
3. Paste the same Moveo callback URL into the **Request URL** field
4. Click **Save Changes**
Your AI Agent is now ready to respond to messages in Slack.
---
## Configuration options
### Bot profile settings
- **Bot name**: Display name shown to users in Slack
- **Avatar**: Profile image for your bot
- **Status**: Always online visibility setting
### Message configuration
- **Autostart message**: Initial greeting when users open a DM
- **Response formatting**: Slack markdown and block kit support
- **File handling**: Configure file upload and sharing behavior
### Channel settings
- **Direct messages**: Enable DM conversations with users
- **Channel mentions**: Respond when @mentioned in channels
- **Private channels**: Access to private channel messages (requires invitation)
---
## Testing your integration
### Initial testing
1. **Open Slack** and navigate to your workspace
2. **Find your bot** in the Apps section
3. **Send a direct message** to test basic functionality
4. **@mention your bot** in a channel to test mentions
5. **Verify responses** are accurate and timely
### Test scenarios
- Direct message conversations
- Channel @mentions and responses
- Multi-turn conversations
- Interactive button responses
- Error handling and fallbacks
---
## Common use cases
### Internal helpdesk
- Answer employee questions about policies and procedures
- Provide instant IT support for common issues
- Guide employees through HR processes
- Automate onboarding information delivery
### Customer support in shared channels
- Engage with customers in Slack Connect channels
- Provide instant answers to product questions
- Escalate complex issues to human agents
- Maintain support presence outside business hours
### Workflow automation
- Trigger automated processes through conversation
- Collect information for form submissions
- Provide status updates on requests
- Integrate with other business systems
---
## Best practices
### Bot configuration
- Use a clear, recognizable bot name and avatar
- Set the bot to always appear online for availability
- Configure helpful initial messages
- Maintain consistent brand voice
### Message optimization
- Keep responses concise for the Slack format
- Use Slack formatting (bold, lists, code blocks) effectively
- Provide clear action buttons when appropriate
- Include helpful links and resources
### Channel management
- Add the bot to relevant channels proactively
- Set clear expectations about bot capabilities
- Provide easy access to human support
- Monitor bot performance across channels
---
## Troubleshooting
Bot not responding to messages
- Verify the signing secret and OAuth token are correct
- Check that the integration is set to Active in Moveo
- Confirm event subscriptions are enabled and verified
- Ensure the bot has been added to the channel (for channel messages)
- Check that required scopes are properly configured
URL verification failing
- Ensure you're using the exact callback URL from Moveo
- Check that the Moveo integration is saved before verification
- Verify there are no extra spaces in the URL
- Try refreshing the Slack app settings page
Bot not appearing online
- Verify "Always Show My Bot as Online" is enabled in App Home
- Check that the bot OAuth token is valid
- Reinstall the app to the workspace if needed
Missing messages from channels
- Ensure the bot has been invited to the channel
- Verify `channels:history` or `groups:history` scopes are added
- Check that `message.channels` or `message.groups` events are subscribed
- For private channels, confirm bot membership
Cannot send direct messages
- Verify `im:write` scope is configured
- Check that the Messages Tab is enabled in App Home
- Ensure "Allow users to send Slash commands and messages" is checked
---
## Limitations
### Platform constraints
- **Workspace access required** - Users must be members of the Slack workspace to interact with your bot
- **Rate limits** - Slack enforces API rate limits; high-volume deployments may require optimization
- **Message history** - Bot cannot access messages sent before it was added to a channel
- **Threading** - Responses in threads require specific handling for consistent experience
### Integration constraints
- **One workspace per integration** - Each Moveo integration connects to a single Slack workspace
- **Bot permissions** - Capabilities are limited to granted OAuth scopes
- **Private channels** - Bot must be explicitly invited to access private channels
- **Enterprise Grid** - May require additional configuration for multi-workspace deployments
---
## Resources
### Documentation
- [Slack API Documentation](https://api.slack.com/docs)
- [Bot Users Guide](https://api.slack.com/bot-users)
- [Events API Reference](https://api.slack.com/events-api)
### Support
- [Slack Help Center](https://slack.com/help)
- Moveo support: support@moveo.ai
---
## Next steps
Once your Slack integration is active:
1. **Invite the bot** to relevant channels in your workspace
2. **Test conversations** across DMs and channel mentions
3. **Configure welcome messages** for optimal first impressions
4. **Train your team** on how to interact with the AI Agent
5. **Monitor usage** and optimize responses based on feedback
---
## Smartlead
Smartlead is a supported channel in Moveo that enables you to send cold emails to your leads and
handle replies seamlessly. Moveo connects to your Smartlead account and leverages
[AI Agents](../ai-agents/overview.md) to manage incoming responses from leads.
## Getting started
Before proceeding, ensure you have a Smartlead account with a **PRO** plan. This is necessary
because it is the only plan that supports API and webhook usage.
### API key
To allow Moveo to use the Smartlead API, you must first obtain an API key.
1. Log in to your Smartlead account.
2. Go to the **Settings** page.
3. In the **Your profile** section, scroll down to the **API** settings.
4. Copy the **API key**.
### Moveo setup
Once you have the API key, set up the integration in Moveo.
1. Navigate to **Deploy** → **Integrations**.
2. Click on the **Smartlead** integration.
3. Enter the API key you copied earlier.
4. Click the **Save** button.
5. Copy the **Webhook URL**.
### Configure webhook
The final step is to configure the webhook in Smartlead. Webhooks can be set at multiple levels, and
Smartlead offers different types for each. In this example, we’ll configure it at the account level.
Regardless of the level, the event type that Moveo listens for is **Email Reply**. You can learn
more about this in the
[Smartlead documentation - Webhooks](https://helpcenter.smartlead.ai/en/articles/35-webhook-guide).
1. In your Smartlead account, go to **Settings** → **Webhooks**.
2. Click the **Add Webhook** button.
3. Enter the **Webhook URL** you copied earlier.
4. Select **Email Reply** as the event type.
5. Click the **Save** button.
## Using the integration
:::note
Sending email campaigns from Moveo is not yet supported.
:::
Campaigns must be created and sent directly from Smartlead. When a potential lead replies to an
email, the webhook is triggered and Moveo receives the reply. You can use
[rules](../environments/rules.md) to route the reply to an [AI Agent](../ai-agents/overview.md), or
assign a [department](../chat/departments.md) if you prefer a [human agent](../chat/overview.md) to
handle the response.
:::info Rule configuration
The first email sent by the campaign is included in the conversation. When creating rules for
Smartlead, use **A customer responds to a message** as the trigger in the `When` clause. Using
"A customer starts a conversation" will not match Smartlead sessions.
:::
---
## Configuration options
### Webhook configuration levels
Smartlead offers webhook configuration at multiple levels. Choose based on your organizational
needs:
- **Account level**: Apply to all campaigns across your account
- **Campaign level**: Specific to individual campaigns
- **Client level**: For agency accounts managing multiple clients
### Event type selection
For Moveo integration, always select **Email Reply** as the event type. This ensures all lead
responses are captured and processed by your AI Agent.
### Response routing
Configure how lead responses are handled:
- **[Departments](../chat/departments.md)**: Direct qualified leads to specific human teams
- **Mixed approach**: Use AI for initial qualification, humans for closing
- **[Rules](../environments/rules.md)**: Automatically route replies to appropriate AI Agents
---
## Testing your integration
### Initial testing
1. **Send test campaign** to a controlled email address
2. **Reply to the test email** with various types of responses
3. **Verify webhook delivery** in Moveo event logs
4. **Check AI Agent responses** for accuracy and context
5. **Confirm email thread continuity** in Smartlead inbox
### Test scenarios
✓ **Positive lead responses** (interested prospects) ✓ **Objection handling** (price, timing, need
concerns) ✓ **Information requests** (product details, demos) ✓ **Unsubscribe requests** (compliance
handling) ✓ **Out-of-office responses** (automated reply detection) ✓ **Handover scenarios**
(qualified lead routing)
### Monitoring
- **Webhook delivery success** in Smartlead dashboard
- **Response quality and relevance** from AI Agent
- **Lead progression tracking** through conversation stages
- **Conversion rates** from reply to qualified lead
---
## Common use cases
### Lead qualification automation
- Automatically qualify inbound responses based on criteria
- Ask qualifying questions to determine fit
- Score leads based on responses and behavior
- Route qualified leads to appropriate sales teams
### Objection handling at scale
- Address common objections automatically
- Provide relevant case studies and social proof
- Offer alternatives and compromises
- Schedule follow-ups for objection resolution
### Demo and meeting scheduling
- Respond to meeting requests instantly
- Integrate with calendar systems for availability
- Send meeting confirmations and reminders
- Handle rescheduling requests automatically
### Product information delivery
- Answer product questions with detailed information
- Share relevant case studies and testimonials
- Provide pricing information when appropriate
- Offer free trials or demos
---
## Best practices
### AI Agent training
- Train on common sales objections and responses
- Include product knowledge and competitive positioning
- Configure appropriate handover triggers
- Maintain consistent brand voice and messaging
### Campaign design
- Design campaigns that encourage responses
- Include clear value propositions
- Use compelling subject lines and CTAs
- Segment audiences for personalized approaches
### Response optimization
- Keep initial AI responses concise and valuable
- Ask one question at a time to maintain engagement
- Provide clear next steps in every interaction
- Use personalization tokens when possible
### Integration management
- Monitor webhook health and delivery rates
- Regularly review and update AI Agent responses
- Track lead progression and conversion metrics
- Maintain proper email deliverability practices
---
## Operational workflow
### Campaign execution
:::note Campaign management
Email campaigns must be created and sent directly from Smartlead. Moveo
handles only the response management.
:::
1. **Create and launch campaigns** in Smartlead
2. **Leads receive emails** from your campaigns
3. **Replies trigger webhooks** to Moveo automatically
4. **AI Agent processes** and responds appropriately
5. **Qualified leads** are routed to human agents
6. **Follow-up sequences** continue based on engagement
### Response processing
When leads reply:
1. **Webhook delivers** reply content to Moveo
2. **AI Agent analyzes** reply intent and context
3. **Response is generated** based on configured knowledge
4. **Reply is sent** back through Smartlead API
5. **Email thread** continues seamlessly
6. **Context is maintained** for subsequent interactions
---
## Troubleshooting
:::warning Delivery timing
Before troubleshooting, confirm that the reply has arrived in the
Smartlead inbox. Due to Smartlead's deliverability algorithms and email provider delays, replies
might be delayed up to 2 hours (especially with Outlook). Once the reply reaches Smartlead, the
webhook should trigger.
:::
Webhook not receiving events
- Ensure webhook URL matches exactly between Smartlead and Moveo
- Verify only one webhook is configured per level (account/campaign/client)
- Check webhook URL is accessible and returns proper response codes
- Review
[Smartlead webhooks troubleshooting](https://helpcenter.smartlead.ai/en/articles/229-webhook-not-sending-triggers)
- Test webhook manually using Smartlead's testing tools
AI Agent not responding to leads
- Verify integration is Active in Moveo
- Check AI Agent is properly assigned to environment
- Confirm rules or departments are configured correctly
- Review webhook event logs for delivery confirmation
- Test with simple email replies first
Responses not appearing in email thread
- Verify API key has proper permissions
- Check API rate limits and quotas
- Ensure email thread ID is being preserved
- Review Smartlead inbox for delivery status
- Test API connectivity manually
Poor AI response quality
- Review and improve AI Agent training data
- Configure more specific conversation rules
- Adjust response templates and knowledge base
- Monitor lead feedback and iterate
- Consider human agent handover thresholds
High volume processing issues
- Check webhook processing capacity
- Monitor API rate limits on both platforms
- Consider implementing message queuing
- Scale AI Agent processing resources
- Review and optimize response generation time
---
## Limitations
### Platform restrictions
- **PRO plan required**: API and webhook access limited to PRO plans
- **Campaign management**: Must create campaigns in Smartlead (not Moveo)
- **Email provider delays**: Response timing dependent on email infrastructure
- **Webhook limitations**: Single webhook per configuration level
### Integration constraints
- **Outbound campaigns**: Moveo cannot send initial cold emails
- **Email formatting**: Limited to text-based responses
- **Thread dependency**: Requires proper email thread maintenance
- **Deliverability**: Subject to email provider and domain reputation
---
## Resources
### Documentation
- [Smartlead API Documentation](https://smartlead.ai/api-docs)
- [Smartlead Webhook Guide](https://helpcenter.smartlead.ai/en/articles/35-webhook-guide)
- [Smartlead Help Center](https://helpcenter.smartlead.ai)
### Tools
- [Smartlead Dashboard](https://smartlead.ai/dashboard)
- [Webhook Testing Tools](https://helpcenter.smartlead.ai/en/articles/229-webhook-not-sending-triggers)
- [API Rate Limit Monitor](https://smartlead.ai/api-docs#rate-limits)
### Support
- [Smartlead Support](https://smartlead.ai/support)
- [Smartlead Community](https://community.smartlead.ai)
- Moveo support: support@moveo.ai
---
## Next steps
Once your Smartlead integration is active:
1. **Launch test campaigns** to validate response handling
2. **Train your AI Agent** on sales conversations and objections
3. **Configure qualification rules** for lead routing
4. **Monitor response quality** and iterate on AI Agent training
5. **Scale campaigns gradually** while monitoring performance and deliverability
---
## Sunshine Conversations
## Overview
Sunshine Conversations (formerly Smooch) integration brings conversational AI directly into
Zendesk's messaging platform, creating a unified customer experience across multiple messaging
channels. Through Zendesk's Bot Marketplace, your AI Agent operates as an intelligent bot that can
handle conversations while seamlessly integrating with your support team's workflow.
This integration enables:
- **Multi-channel messaging support** through Zendesk's unified platform
- **Bot Marketplace integration** with official Moveo bot
- **Seamless handover** with automatic ticket creation
- **Unified agent dashboard** for AI and human conversation management
- **Context preservation** across bot and agent interactions
- **Enterprise messaging features** including web widget and mobile SDK
---
## Prerequisites
Before setting up the Sunshine Conversations integration, ensure you have:
✅ **Zendesk requirements**
- **Zendesk Pro plan** or higher (required for Sunshine Conversations)
- Administrator access to Zendesk Admin Center
- Sunshine Conversations enabled in your account
✅ **Messaging setup**
- Zendesk messaging channels configured
- Web Widget or mobile messaging active
- Understanding of your customer communication channels
✅ **Moveo account setup**
- An active [AI Agent](../ai-agents/overview.md) configured
- An [environment](../environments/overview.md) selected for the integration
:::note Plan requirement
Sunshine Conversations requires Zendesk Pro plan or higher. Basic and Team
plans do not include messaging capabilities.
:::
---
## How it works
The Sunshine Conversations integration operates through Zendesk's Bot Marketplace with direct AI
Agent connectivity:
1. **Customer initiates conversation** through any connected messaging channel
2. **Zendesk receives message** and routes to configured channels
3. **Moveo bot engages** based on routing rules and availability
4. **AI Agent processes** message and responds through bot interface
5. **Conversation continues** with AI handling inquiries automatically
6. **Handover triggers** when human assistance is needed
7. **Ticket is created** automatically for human agent follow-up
8. **Context is preserved** throughout the conversation lifecycle
All interactions are managed within Zendesk's unified platform while leveraging Moveo's AI
capabilities.
---
## Setup guide
The integration involves configuration in both Moveo and Zendesk platforms:
### Step 1: Configure Moveo integration
1. Go to your **Integrations** and select **Configure** on Sunshine Conversations.
2. Select **Connect**.
3. Fill in your Zendesk subdomain to sign in.
4. Authorize Moveo to access your account.
5. Configure your settings, such as the name of the assistant, the autostart message, and the
avatar.
### Step 2: Set up Zendesk bot connection
1. Go to your Zendesk Admin Center.
2. Navigate to **Channels > Bots & automation > Bots**. Locate the Moveo bot under Marketplace bots
and click the **Connect** button.
3. Navigate to **Channels > Messaging & social > Messaging** and configure your customer-facing
integrations.
---
## Configuration options
### Bot settings
- **Assistant name**: Display name for your AI Agent in conversations
- **Autostart message**: Initial message sent when conversations begin
- **Avatar**: Visual representation of your AI Agent
- **Response behavior**: Configure how the bot interacts with customers
### Channel configuration
- **Web Widget**: Configure appearance and behavior in web chat
- **Mobile messaging**: Set up in-app or SDK-based messaging
- **Third-party channels**: Connect external messaging platforms
- **Routing rules**: Define when and how the bot should engage
### Handover management
- **Trigger conditions**: Configure when to escalate to human agents
- **Ticket creation**: Automatic support ticket generation
- **Agent assignment**: Route tickets to appropriate teams
- **Context transfer**: Preserve conversation history during handover
---
## Testing your integration
### Initial testing
1. **Send test messages** through your configured messaging channels
2. **Verify bot engagement** and response quality
3. **Test handover scenarios** to ensure smooth transitions
4. **Check ticket creation** in Zendesk Support
5. **Validate conversation history** preservation
### Test scenarios
✓ **Multi-channel messaging** (web, mobile, third-party) ✓ **AI Agent conversation flow** ✓
**Handover trigger activation** ✓ **Ticket creation and assignment** ✓ **Agent takeover experience**
✓ **Conversation history continuity**
### Performance monitoring
- **Bot engagement rates** across different channels
- **Handover frequency** and success rates
- **Ticket resolution times** after handover
- **Customer satisfaction** with bot interactions
---
## Common use cases
### Multi-channel customer support
- Provide consistent AI support across web, mobile, and messaging platforms
- Handle routine inquiries automatically
- Escalate complex issues with full context
- Maintain unified conversation history
### Lead qualification and routing
- Engage website visitors through messaging widget
- Qualify leads through conversational AI
- Route qualified prospects to sales teams
- Create tickets for follow-up actions
### After-hours support
- Provide 24/7 AI support when agents unavailable
- Handle urgent inquiries automatically
- Create tickets for next business day follow-up
- Maintain service level standards
### Self-service automation
- Guide customers through common processes
- Provide instant answers to FAQs
- Collect information for support requests
- Reduce agent workload through automation
---
## Best practices
### Bot configuration
- Use clear, professional bot name and avatar
- Configure engaging autostart messages
- Set appropriate response expectations
- Maintain consistent brand voice
### Handover optimization
- Define clear escalation criteria
- Configure appropriate triggers for complex issues
- Ensure smooth context transfer to agents
- Monitor handover success rates
### Channel management
- Configure channels based on customer preferences
- Maintain consistent experience across platforms
- Monitor channel-specific performance
- Optimize routing rules for efficiency
### Team coordination
- Train agents on bot capabilities and limitations
- Establish clear handover procedures
- Regular review of bot performance
- Continuous improvement of AI responses
---
## Advanced configuration
### Automatic ticket closure
Any time a conversation gets handed over by Moveo, Sunshine
Conversations automatically creates a ticket in Zendesk that your support team can handle.
Note that the control of the conversation is returned to Moveo when a ticket is **Closed**. However,
when an agent **solves** a conversation, the conversation does not close automatically. To achieve
this, you need to create a trigger in Zendesk:
1. Navigate to **Admin Center > Objects and rules > Business rules > Triggers**.
2. Add a new trigger to specify the conditions under which a conversation is considered resolved and
should be closed.
The trigger below ensures that when a ticket's status is changed to **Solved**, if the conversation
is on messaging channels (or any other channels you use in Zendesk), the status should become
**Closed**.
---
## Troubleshooting
Bot not responding in channels
- Verify Moveo bot is connected in Zendesk Bot Marketplace
- Check messaging channels are properly configured
- Confirm integration is Active in Moveo
- Review bot routing rules and conditions
- Test with different messaging channels
Handover not creating tickets
- Verify handover triggers are properly configured
- Check Zendesk Support integration is active
- Confirm agent permissions for ticket access
- Review trigger conditions and rules
- Test handover scenarios manually
Tickets not closing automatically
- Implement the ticket closure trigger as described above
- Verify trigger conditions match your workflow
- Check that agents are marking tickets as "Solved"
- Test trigger activation with sample tickets
- Review Zendesk trigger logs for errors
Conversation context lost during handover
- Check conversation history preservation settings
- Verify ticket creation includes full context
- Review agent dashboard for conversation details
- Test context transfer with sample conversations
- Ensure proper integration configuration
Authorization issues
- Verify Zendesk subdomain is correct
- Check administrator permissions in Zendesk
- Re-authorize Moveo access if needed
- Review OAuth connection status
- Test with different administrator account
---
## Limitations
### Platform requirements
- **Pro plan minimum**: Zendesk Pro plan or higher required
- **Sunshine Conversations**: Must be enabled in your Zendesk account
- **Bot marketplace**: Limited to official Moveo bot from marketplace
- **Channel dependencies**: Subject to Zendesk messaging channel availability
### Integration constraints
- **Ticket dependency**: Handover requires ticket creation
- **Agent availability**: Human handover depends on agent status
- **Channel limitations**: Some third-party channels may have restrictions
- **Context format**: Conversation history format determined by Zendesk
---
## Disconnection procedure
To safely disconnect your Sunshine Conversations integration:
### Step 1: Zendesk cleanup
1. Navigate to **Admin Center > Channels > Bots & automation > Bots**
2. Locate Moveo bot under Marketplace bots
3. Select **Uninstall** to remove bot connection
4. Confirm removal in Zendesk interface
### Step 2: Moveo cleanup
1. Go to your Moveo integration settings
2. Locate Sunshine Conversations integration
3. Select the **Delete** button (only available after Zendesk disconnection)
4. Confirm removal to complete disconnection
:::caution
Always uninstall the bot from Zendesk first, then delete the integration in
Moveo to avoid orphaned connections.
:::
---
## Resources
### Documentation
- [Sunshine Conversations Documentation](https://support.zendesk.com/hc/en-us/sections/360012725594)
- [Zendesk Messaging Guide](https://support.zendesk.com/hc/en-us/categories/360002176374)
- [Bot Marketplace](https://support.zendesk.com/hc/en-us/articles/4408886469146)
### Tools
- [Zendesk Admin Center](https://support.zendesk.com/hc/en-us/articles/4408843597850)
- [Messaging Configuration](https://support.zendesk.com/hc/en-us/categories/360002176374)
- [Trigger Management](https://support.zendesk.com/hc/en-us/articles/203662156)
### Support
- [Zendesk Support](https://support.zendesk.com)
- [Sunshine Conversations Help](https://support.zendesk.com/hc/en-us/sections/360012725594)
- Moveo support: support@moveo.ai
---
## Next steps
Once your Sunshine Conversations integration is active:
1. **Configure messaging channels** for optimal customer reach
2. **Set up ticket closure automation** for efficient workflow
3. **Train your team** on bot handover procedures
4. **Monitor performance metrics** across channels
5. **Optimize AI responses** based on conversation analytics
---
## Telnyx Voice
## Overview
The Telnyx Voice integration enables your AI Agent to handle voice conversations over phone calls. By connecting your Telnyx account to Moveo, you can provide automated voice support that combines the power of AI with natural speech interaction.
This integration supports automated phone support through your Telnyx phone numbers, outbound calling through campaigns, natural voice interactions with text-to-speech and speech-to-text capabilities, and flexible configuration to optimize voice quality and recognition accuracy.
---
## Prerequisites
Before setting up the Telnyx Voice integration, you'll need to configure both your Telnyx account and your Moveo setup.
### Telnyx account
You'll need an active Telnyx account with voice capabilities enabled and sufficient balance to cover voice call costs. All Telnyx-side values are collected from the [Mission Control Portal](https://portal.telnyx.com).
#### API key
Moveo uses a Telnyx API v2 key to place calls, control them, and provision the voice resources described in [What Moveo configures in your Telnyx account](#what-moveo-configures-in-your-telnyx-account). [Create the key](https://developers.telnyx.com/development/api-fundamentals/create-api-keys) in the Telnyx portal under **API Keys**.
:::warning
Copy the API key when it's created. Telnyx shows the value only once. The key also cannot be changed after you save the integration: to use a different key, delete the integration and create a new one.
:::
#### Public key
Telnyx [signs every webhook](https://developers.telnyx.com/development/api-fundamentals/webhooks/receiving-webhooks#webhook-signing) it sends to Moveo, and Moveo verifies that signature before acting on the call. Copy the public key from the **Public Key** page, in the same **API Keys** section of the Telnyx portal. Telnyx exposes a single public key for your organization.
:::warning
Moveo checks your API key when you enter it, but it cannot check the public key. If the public key is wrong, the integration still saves, and Moveo then rejects every webhook Telnyx sends, so calls are never answered. Copy it exactly.
:::
#### Account level
Telnyx applies limits per [account level](https://developers.telnyx.com/docs/account-setup/account-upgrade), and the lower levels are not usable for production voice. An account belongs to either the Pretrial to Verified ladder or the Level 1 and Level 2 framework, never both:
- **Pretrial** accounts have no access to Call Control Applications, which this integration requires. Upgrade before configuring the integration.
- **Trial** accounts are limited to a single outbound voice profile, restrict calls to a verified phone number, cap call duration at 10 minutes, and allow 2 concurrent outbound calls. See [trial limitations](https://developers.telnyx.com/docs/account-setup/levels-and-capabilities/trial).
- **Paid** accounts allow 5 concurrent outbound calls. Reaching 10 requires completing verification, and higher limits are available from Telnyx on request. See [concurrent call limits](https://developers.telnyx.com/docs/voice/sip-trunking/configuration/concurrent-limits).
- **Level 1** accounts cap outbound calling at 100 calls per day and 10 calls per hour, which is not enough for a campaign. See [L1 restrictions](https://developers.telnyx.com/docs/voice/programmable-voice/l1-accounts-restirctions).
:::warning Verify your Telnyx account before going live
Below the **Verified** level, Telnyx prepends an automated-call announcement to machine-generated speech, so your callers hear a Telnyx fraud notice before the AI Agent. This applies to paid accounts too, not only trials. Completing verification also lifts the concurrency and destination limits.
:::
#### Phone number
Connect a [Telnyx number, or a number you've ported to Telnyx](https://developers.telnyx.com/docs/numbers/phone-numbers/getting-started), to receive incoming calls and to place campaign calls. A Telnyx number can only be assigned to one connection at a time, so numbers already in use elsewhere in your Telnyx account cannot be selected in Moveo.
:::warning
Without a phone number the integration cannot answer incoming calls or place campaign calls. Leave **Phone** set to **None** only if you plan to add the number later.
:::
### Moveo account
The configuration steps for connecting your AI Agent to Telnyx are handled through Moveo's platform. For a complete walkthrough of the Moveo-side setup including AI Agent selection, environment configuration, and rule creation, see the [quick deployment guide](../guides/quick-start.md).
---
## How it works
The Telnyx Voice integration creates a bridge between callers and your Moveo AI Agent. When someone dials your Telnyx phone number, Telnyx notifies Moveo, Moveo answers the call, and Telnyx starts streaming the call audio. The speech-to-text engine converts spoken words into text, which your AI Agent processes to generate an appropriate response. That response is then converted back to natural voice through text-to-speech and streamed to the caller in real-time.
For outbound calls the flow is similar. A campaign asks Telnyx to dial the customer, and when the customer answers, the same speech processing and response cycle occurs. The conversation continues until the caller hangs up, or the AI Agent decides that the conversation has been resolved.
### What Moveo configures in your Telnyx account
Once you save the integration with valid credentials, Moveo creates the Telnyx resources the AI Agent needs and keeps them in sync:
- An [**outbound voice profile**](https://developers.telnyx.com/docs/voice/sip-trunking/configuration/outbound-voice-profiles) that authorizes outbound calling.
- A [**voice API application**](https://developers.telnyx.com/docs/voice/programmable-voice/voice-api-fundamentals) whose webhook points at Moveo, so Telnyx notifies Moveo about incoming calls and call events.
- The **connection resources** used for call control.
- The **phone number assignment** that binds the number you selected to that application.
Moveo re-checks these resources periodically and removes them when you delete the integration.
:::warning
Don't rename, delete, or repoint the Telnyx resources that Moveo creates. The integration stops working until the expected configuration is restored, so if one of them was changed, delete and save the integration again to have Moveo recreate it.
:::
The outbound voice profile that Moveo creates covers the common destination countries. If your campaign targets a country that isn't enabled, contact Moveo support. Telnyx also gates many destinations behind account verification, so verify your Telnyx account before dialing outside the United States and Canada.
### Reaching your AI Agent
Once the integration is configured, users can reach your AI Agent in two ways:
**Inbound calls**: Customers can call your Telnyx phone number directly to start a conversation with your AI Agent. This is particularly useful for customer support hotlines or IVR systems where users initiate contact.
**Outbound calls**: Your AI Agent can also call customers as part of a [campaign](../campaigns/campaigns.md). This enables proactive outreach for appointment reminders, notifications, surveys, or follow-ups, with the AI Agent handling the conversation when the customer answers.
---
## Call termination and handover
Apart from the caller hanging up, a call ends in one of two ways, both controlled from the AI Agent's workflow. When the AI Agent resolves the conversation, the platform hangs up the call within a couple of seconds.
- **Resolve**: the [`Resolve`](../ai-agents/operations/resolve.md) action marks the conversation as completed. The call leg closes within a couple of seconds, whatever the environment's [Keep alive](../guides/timeouts.md#keep-alive) value.
- **Handover**: the [`Handover`](../ai-agents/operations/handover.md) action transfers the active call to a phone number or SIP URI, via a **Standard transfer** (Moveo stays on the call) or **SIP REFER** (Moveo hands off to your SIP system and drops off). Optional custom SIP headers can be attached for SIP destinations. See [Voice call transfer](./voice-call-transfer.md).
To make voice calls behave predictably at the end of a conversation, apply the following checklist to every voice-enabled environment:
- Leave **Keep alive** as it is. It does not affect voice call termination. See [Keep alive for voice integrations](../guides/timeouts.md#voice-integrations).
- Add a [`Pause`](../ai-agents/operations/pause.md) action of **1–2 seconds** immediately before any `Resolve` or `Handover` action so the AI Agent's final sentence is not clipped.
---
## Setup guide
### Step 1: Prepare your Telnyx credentials
1. Log in to the [Mission Control Portal](https://portal.telnyx.com) and open [**API Keys**](https://portal.telnyx.com/#/app/api-keys).
2. On the **API Keys** page, click **Create API Key** and copy the key immediately.
3. Open **Public Key** in the same section and copy the public key.
Keep both values handy for the next step.
### Step 2: Configure the integration in Moveo
Navigate to **Connections** in your Moveo account, select your environment, find the **Telnyx Voice** integration card, and click **Configure**.
### Step 3: Enter your Telnyx account details
Enter your credentials in the **Account** section of the configuration panel:
**API Key**: the Telnyx API v2 key from the previous step. Moveo checks the key as you type and reports whether Telnyx accepts it.
**Public Key**: the public key of the same Telnyx account, used to verify webhook signatures. Moveo cannot validate this one, so copy it exactly.
Once the API key is verified, a **Phone** field appears so you can connect a number to the AI Agent. Numbers are grouped to show what you can pick:
| Group | Meaning |
|-------|---------|
| **Available** | Telnyx numbers in your account that aren't attached to another connection |
| **Verified caller ID** | Numbers you own elsewhere and have verified in Telnyx, usable for outbound calls only |
| **In use** | Already taken, so they can't be selected: a Telnyx number attached to another connection, or a verified caller ID used by another Moveo integration |
Only numbers that are **active** in Telnyx are listed, up to the first 250. Select a number to let the integration answer incoming calls to it and place campaign calls from it. A verified caller ID is the exception, since it works for outbound calls only, so read [Choose the caller ID for outbound calls](#step-4-choose-the-caller-id-for-outbound-calls) before picking one.
### Step 4: Choose the caller ID for outbound calls
Which number your customers see on outbound campaign calls depends on the kind of number you selected:
**A Telnyx number** is the recommended option, because it handles incoming and outgoing calls. For calls to the United States and Canada, Telnyx also signs numbers you own at the highest [STIR/SHAKEN attestation](https://developers.telnyx.com/docs/voice/stir-shaken/attestation-behavior) level, **A**, which lowers the chance that carriers block or label the call.
**A verified caller ID** is a number you own with another provider and have registered under [**Numbers** → **Verified numbers**](https://support.telnyx.com/en/articles/6988813-verified-numbers) in the Telnyx portal. Keep two constraints in mind:
- It works for outbound campaigns only. Incoming calls to that number keep routing through your original provider.
- Some destination carriers screen calls that present a local number arriving from another carrier's network, and in-country calls to mobile numbers are the common failure case. Telnyx also signs these calls at attestation **B** rather than **A**. Prefer a Telnyx number for the market you dial most.
**Your own SIP gateway** is an optional advanced setup. Selecting a verified caller ID reveals a **SIP gateway** field in the **Account** section: enter a host there and Moveo sends outbound calls to that gateway, so your own carrier places the call to the recipient. Enter the host without a `sip:` prefix, for example `sbc.example.com:5060`. If the gateway authenticates, enter its credentials in **SIP auth username** and **SIP auth password**.
:::note SIP gateway routing
This setup requires your own SIP infrastructure and a carrier contract that allows presenting those numbers. Contact Moveo support to plan it.
:::
### Step 5: Optimize voice settings
The integration includes default settings for **text-to-speech** (TTS) and **speech-to-text** (STT) that work well for most use cases. However, you can adjust these settings to better fit your specific needs. They sit below the **Account** section in the configuration panel; see [Voice settings](#voice-settings) for what each group controls.
### Step 6: Activate the integration
Review your configuration, turn on the toggle in the **Telnyx Voice** card at the top of the panel, and click **Save** to apply your changes. The **Account** section reports **Active** once the integration is live.
### Step 7: Route calls to an AI Agent
The integration is now connected to Telnyx, but calls still need an AI Agent to answer them. Create a rule for this integration as described in the [quick deployment guide](../guides/quick-start.md), then place a test call.
---
## Configuration options
### Voice settings
The configuration panel groups the voice behavior into three sections:
**Preferences** controls whether voice conversations are stored as call recordings on your account, and whether the AI Agent starts the conversation with the initial welcome message instead of waiting for the caller to speak first.
**Configuration** holds the language of the conversation and a preset that applies recommended settings for that language. Changing any individual setting switches the preset to **Custom**.
Click **Show advanced** to expose the pipeline itself, including **Noise Suppression**, **Speech to text** (transcription model and turn detection), and **Text to speech** (voice, model, and delivery parameters such as speed). The defaults are a good starting point, so change the advanced settings only when testing shows a reason to.
#### Noise suppression
Noise suppression reduces background noise in the caller's audio, which improves transcription accuracy at the cost of a little extra latency. It's off by default. Turn on **Enabled**, then choose where it runs:
- **Moveo.AI** applies noise suppression inside the Moveo voice pipeline, and is available on every voice integration. This is the default when you enable the feature.
- **Telnyx Noise Suppression** applies it on the Telnyx leg, before the audio reaches Moveo, and is available on Telnyx Voice only. Telnyx bills this separately, per direction of audio.
Selecting a provider also lets you pick an **Engine**. **Denoiser** suits most calls; the others target speaker isolation, WebRTC audio, far-field microphones, or speech-recognition accuracy, and each option in the list shows what it's best for. The engine names combine Telnyx's engines with their sub-models, so they don't map one to one onto the names in Telnyx's [noise suppression guide](https://developers.telnyx.com/docs/voice/programmable-voice/noise-suppression).
### Voice quality optimization
To ensure the best voice experience, structure your AI Agent's responses using clear, concise language without complex formatting. Avoid special characters and symbols that don't translate well to speech, and use natural spoken language patterns. Consider adding pauses with punctuation for better pacing.
### AI Agent guidelines for voice
Voice conversations have unique characteristics compared to text-based chat. To improve your AI Agent's performance in voice interactions, you can add specific guidelines that optimize for the auditory experience. These include using shorter, more conversational responses, avoiding lists or complex structures that are hard to follow audibly, confirming understanding of user input before proceeding, using verbal cues for transitions between topics, and providing clear call-to-action statements.
---
## Testing your integration
### Test phone calls
Dial your Telnyx phone number and wait for the AI Agent greeting. Test various conversation scenarios, verify proper call handling and termination, and check call quality and response timing.
### Test outbound calls
If you plan to run campaigns, and especially if you configured a verified caller ID, run a [campaign](../campaigns/campaigns.md) with a single contact to a phone you control. Confirm that the call connects and that the caller ID the recipient sees is the number you expect.
### Key test scenarios
Make sure to validate call initiation and greeting, clear speech recognition, natural-sounding responses, handling of unclear input or silence, proper call termination, and transcription mismatches.
---
## Troubleshooting
### Connection issues
**The integration doesn't verify**: Confirm the API key is still active in the Telnyx portal, that the public key belongs to the same account, and that the account is funded and has voice enabled. Pretrial accounts cannot create the Call Control Application the integration needs, so the integration cannot be configured on one. See [Account level](#account-level).
**You need to change the API key**: This isn't supported after the integration is saved. Delete the integration and create a new one with the new key.
**Your number isn't in the list**: The number must be in the Telnyx account that owns the API key and must be **active** in Telnyx, and only the first 250 active numbers are listed. Numbers shown under **In use** are already taken: detach a Telnyx number from its other connection in the Telnyx portal, or remove a verified caller ID from the other Moveo integration that holds it.
**The Verified caller ID group is missing**: Moveo lists Telnyx-owned numbers only when it cannot read your verified numbers from Telnyx. Confirm the numbers are verified in the Telnyx portal, then reopen the configuration panel.
### Call handling issues
**Calls aren't being answered**: Verify the integration is active, review the call in the Telnyx portal to confirm it reached Telnyx, and check that the public key in Moveo matches the one in your Telnyx account, since a mismatch makes Moveo reject every webhook. If the voice API application Moveo created was renamed or repointed, delete and save the integration again so Moveo recreates it.
**Outbound campaign calls fail to connect**: This is the common symptom of dialing in-country mobile numbers from a verified caller ID, where the destination carrier screens the call. Use a Telnyx number in that market, or route the calls through your own SIP gateway. See [Choose the caller ID for outbound calls](#step-4-choose-the-caller-id-for-outbound-calls).
**Outbound calls are rejected because of the caller ID**: The number must be in E.164 format (the international format, for example `+12025551234`), and a number you own elsewhere must be registered as a verified number in Telnyx before it can be presented.
**AI Agent not responding correctly**: Test the AI Agent in text mode first to verify logic, review voice-specific guidelines and adjust accordingly, check for speech recognition errors in logs, verify intent recognition is working properly, and consider adding confirmation steps for critical information.
### Audio quality issues
**Speech recognition is inaccurate**: Adjust STT language settings to match the caller's language, enable noise suppression for better accuracy, and review the recognition sensitivity settings.
**Voice responses sound unnatural**: Review your AI Agent's response formatting, remove special characters and formatting that don't translate to speech, adjust the TTS voice model or speaking rate, simplify complex responses for better verbal delivery, and add punctuation for natural pauses and pacing.
**Audio delays or lag**: Review [Telnyx's service status](https://status.telnyx.com) for any issues, and check whether the callers reporting the delay are in a region far from your Moveo deployment.
---
## Limitations
### Platform limitations
Call duration and concurrency limits are determined by your Telnyx account level and plan, and which destination countries you can dial depends on that level too. Audio format constraints are defined by the codecs supported by Telnyx. Accounts below the **Verified** level are capped and prepend an automated-call announcement, so they can't be used for production traffic.
### Integration constraints
Each integration configuration supports one phone number, and that number is assigned to the connection Moveo creates while the integration exists. Verified caller IDs work for outbound calls only. Voice quality depends on the caller's connection and device, STT accuracy varies with accents and background noise, and complex multi-turn conversations may require optimization.
### Best practices
Monitor call duration and implement time limits if needed for cost control. Provide clear voice prompts for better recognition. Have fallback options for unclear or failed recognition. Regularly review and optimize based on call analytics.
---
## Resources
### Telnyx documentation
- [Voice API overview](https://developers.telnyx.com/docs/voice/programmable-voice/get-started)
- [Mission Control Portal](https://portal.telnyx.com)
- [API reference](https://developers.telnyx.com/api-reference/overview)
- [Voice API pricing](https://telnyx.com/pricing/voice-api)
- [Account levels and upgrades](https://developers.telnyx.com/docs/account-setup/account-upgrade)
- [Telnyx status](https://status.telnyx.com)
### Moveo resources
- [Quick deployment guide](../guides/quick-start.md)
- [Campaigns](../campaigns/campaigns.md)
- [Voice call transfer](./voice-call-transfer.md)
- [Twilio Voice integration](./twilio-voice.md)
### Support
- [Telnyx support](https://support.telnyx.com/)
- Moveo support: support@moveo.ai
---
## Next steps
Once your Telnyx Voice integration is active, optimize your AI Agent with voice-specific guidelines, test thoroughly with various scenarios and voice configuration, monitor call analytics to identify improvement areas, adjust TTS/STT settings based on user feedback, configure fallback options for complex queries, and train your team on monitoring and handling escalations.
---
## Twilio Voice
## Overview
The Twilio Voice integration enables your AI Agent to handle voice conversations through phone calls and web-based calling. By connecting your Twilio account to Moveo, you can provide automated voice support that combines the power of AI with natural speech interaction.
This integration supports automated phone support through your Twilio phone numbers, web-based calling for browser-to-AI conversations, natural voice interactions with text-to-speech and speech-to-text capabilities, and flexible configuration to optimize voice quality and recognition accuracy.
---
## Prerequisites
Before setting up the Twilio Voice integration, you'll need to configure both your Twilio account and your Moveo setup.
### Twilio account
You'll need an active Twilio account with voice capabilities enabled and sufficient balance to cover voice call costs.
#### Subaccount (optional)
If you want to keep your Moveo voice usage separate from other Twilio services, you can create a [subaccount](https://help.twilio.com/articles/223136587-What-is-a-subaccount-). This is useful to isolate Moveo voice costs, phone numbers, and call logs from your other Twilio services.
Each subaccount gets its own Account SID and Auth Token. For instructions on creating a subaccount, see [Twilio's subaccount guide](https://help.twilio.com/articles/360011348693-View-and-Create-New-Twilio-Subaccounts).
:::tip
If you have a dedicated Twilio account with no other services using it, you can use the main account directly; a subaccount is not required.
:::
#### Account SID and Auth Token (region-specific)
Your Twilio credentials must come from the [Twilio region](https://www.twilio.com/docs/global-infrastructure/understanding-twilio-regions) that matches your Moveo deployment:
| Moveo deployment | Twilio region |
|------------------|---------------|
| Europe (EU) | Ireland (IE1) |
| United States (US) | US1 |
:::warning
Make sure you select the correct Twilio region. Using credentials from the wrong region will result in connectivity issues with Moveo.
:::
#### Trial account limitations
Twilio trial accounts are restricted to the **US1** region (see [Twilio's free trial limitations](https://help.twilio.com/articles/360036052753-Twilio-Free-Trial-Limitations)). This affects customers whose Moveo deployment is in **Europe (EU)**, which uses the Ireland (IE1) Twilio region:
- A trial account cannot connect to a Moveo deployment in the EU, because the IE1 region only becomes available after upgrading to a paid Twilio account.
- Trial accounts are also limited to a single Twilio phone number.
- The region of an existing trial account cannot be changed by re-routing or re-purchasing a number.
:::warning
If your Moveo deployment is in the EU, upgrade your Twilio account to a paid plan **before** configuring the integration. There is no workaround on a trial account.
:::
#### Phone number (optional)
You can use a Twilio-provided number or a number you've ported to Twilio. If you don't configure a phone number, the integration will be limited to web-based calls.
:::warning
A phone number is not required if you only plan to handle web calls. It becomes required when supporting incoming phone calls or when using the integration to call customers through campaigns.
:::
### Moveo account
The configuration steps for connecting your AI Agent to Twilio are handled through Moveo's platform. For a complete walkthrough of the Moveo-side setup including AI Agent selection, environment configuration, and rule creation, see the [quick deployment guide](../guides/quick-start.md).
---
## How it works
The Twilio Voice integration creates a bridge between callers and your Moveo AI Agent. When a user initiates a call through your web application, Twilio establishes the connection and begins streaming audio. The speech-to-text engine converts spoken words into text, which your AI Agent processes to generate an appropriate response. That response is then converted back to natural voice through text-to-speech and streamed to the caller in real-time.
For phone calls, the flow is similar. When someone dials your Twilio phone number, Twilio routes the call to Moveo where the same speech processing and response cycle occurs. The conversation continues until the caller hangs up, or the AI Agent decides that the conversation has been resolved.
When the AI Agent resolves the conversation, the platform hangs up the call within a couple of seconds.
### Reaching your AI Agent
Once the integration is configured, users can reach your AI Agent in two ways:
**Inbound calls**: Customers can call your Twilio phone number directly to start a conversation with your AI Agent. This is particularly useful for customer support hotlines or IVR systems where users initiate contact.
**Outbound calls**: Your AI Agent can also call customers as part of a [campaign](../campaigns/campaigns.md). This enables proactive outreach for appointment reminders, notifications, surveys, or follow-ups, with the AI Agent handling the conversation when the customer answers.
---
## Call termination and handover
A call ends in one of two ways, both controlled from the AI Agent's workflow:
- **Resolve**: the [`Resolve`](../ai-agents/operations/resolve.md) action marks the conversation as completed. The call leg closes within a couple of seconds, whatever the environment's [Keep alive](../guides/timeouts.md#keep-alive) value.
- **Handover**: the [`Handover`](../ai-agents/operations/handover.md) action transfers the active call to a phone number or SIP URI, via a **Standard transfer** (Moveo stays on the call) or **SIP REFER** (Moveo hands off to your SIP system and drops off). Optional custom SIP headers can be attached for SIP destinations. See [Voice call transfer](./voice-call-transfer.md).
To make voice calls behave predictably at the end of a conversation, apply the following checklist to every voice-enabled environment:
- Leave **Keep alive** as it is. It does not affect voice call termination. See [Keep alive for voice integrations](../guides/timeouts.md#voice-integrations).
- Add a [`Pause`](../ai-agents/operations/pause.md) action of **1–2 seconds** immediately before any `Resolve` or `Handover` action so the AI Agent's final sentence is not clipped.
- Gate the `Handover` action on call type if your AI Agent can also be reached through browser-based (Web) voice calls — handover is not supported for browser calls.
---
## Setup guide
### Step 1: Prepare your Twilio credentials
1. Log in to your [Twilio Console](https://console.twilio.com/). If you are using a subaccount, make sure you have switched to it.
2. Navigate to **Account** > **Keys & Credentials** > **API keys & tokens**.
3. From the region dropdown, select the Twilio region that matches your Moveo deployment (see the [region table above](#account-sid-and-auth-token-region-specific)).
4. Copy the **Account SID** and **Auth Token** displayed for that region.
Keep these credentials handy for the next step.
### Step 2: Configure the integration in Moveo
Navigate to **Connections** in your Moveo account, select your environment, find the **Twilio Voice** integration card, and click **Configure**.
### Step 3: Enter your Twilio account details
In the configuration panel, you'll see a **Twilio Account** section where you'll enter your credentials and optionally select a phone number:
**Account SID**: Your Twilio Account SID from the previous step (make sure these are the region-specific credentials)
**Auth Token**: Your Twilio Auth Token
**Phone Number**: Select a phone number from the dropdown to enable phone calls, or leave it set to "None" for web calls only
When no phone number is selected, the integration works exclusively for web calls. When you select a phone number, the integration handles both web calls and incoming phone calls to that number.
### Step 4: Optimize voice settings
The integration includes default settings for **text-to-speech** (TTS) and **speech-to-text** (STT) that work well for most use cases. However, you can adjust these settings to better fit your specific needs. The TTS settings let you select the voice model, speaking rate, pitch adjustments, language, and accent. The STT settings allow you to configure the recognition model, language, profanity filtering, and punctuation preferences.
These settings can be found below the Twilio Account section in the configuration panel and adjusted based on your testing results. See [Voice settings](#voice-settings) for what each group of settings controls.
### Step 5: Activate the integration
Review your configuration, turn on the toggle in the **Twilio Voice** card at the top of the panel, and click **Save** to apply your changes. The **Account** section reports **Active** once the integration is live.
---
## Configuration options
### Voice settings
The configuration panel groups the voice behavior into three sections:
**Preferences** controls whether voice conversations are stored as call recordings on your account, and whether the AI Agent starts the conversation with the initial welcome message instead of waiting for the caller to speak first.
**Configuration** holds the language of the conversation and a preset that applies recommended settings for that language. Changing any individual setting switches the preset to **Custom**.
Click **Show advanced** to expose the pipeline itself, including **Noise Suppression**, which is off by default and reduces background noise in the caller's audio to improve transcription accuracy at the cost of a little extra latency, **Speech to text** for the transcription model and turn detection, and **Text to speech** for the voice, the model, and delivery parameters such as speed. The defaults are a good starting point, so change the advanced settings only when testing shows a reason to.
### Voice quality optimization
To ensure the best voice experience, structure your AI Agent's responses using clear, concise language without complex formatting. Avoid special characters and symbols that don't translate well to speech, and use natural spoken language patterns. Consider adding pauses with punctuation for better pacing.
### AI Agent guidelines for voice
Voice conversations have unique characteristics compared to text-based chat. To improve your AI Agent's performance in voice interactions, you can add specific guidelines that optimize for the auditory experience. These include using shorter, more conversational responses, avoiding lists or complex structures that are hard to follow audibly, confirming understanding of user input before proceeding, using verbal cues for transitions between topics, and providing clear call-to-action statements.
:::tip
Check this documentation page to learn more about this: https://elevenlabs.io/docs/best-practices/prompting/normalization#putting-it-all-together
:::
---
## Testing your integration
### Test phone calls
If you configured a phone number, dial your Twilio phone number and wait for the AI Agent greeting. Test various conversation scenarios, verify proper call handling and termination, and check call quality and response timing.
### Key test scenarios
Make sure to validate call initiation and greeting, clear speech recognition, natural-sounding responses, handling of unclear input or silence, proper call termination, and transcription mismatches.
## Troubleshooting
### Connection issues
**Integration fails to connect to Twilio**: Verify your Account SID and Auth Token are correct, check that your Twilio account is active and funded, ensure you have voice capabilities enabled, and review Twilio account status for any restrictions.
**Phone number not working**: Confirm the phone number is active in your Twilio account, check that the number has voice capabilities enabled, verify the number is properly configured in Moveo, and test the number directly in Twilio Console.
**Phone number cannot be re-routed to the EU region**: If the "Re-route" button is grayed out in the Twilio console, or the integration rejects a number that otherwise looks correctly configured, your Twilio account is likely a trial account. Trial accounts are locked to the US1 region and cannot be used with an EU Moveo deployment — upgrade to a paid Twilio account and retry. See [Trial account limitations](#trial-account-limitations).
### Audio quality issues
**Speech recognition is inaccurate**: Adjust STT language settings to match the caller's language, enable noise suppression for better accuracy, check microphone quality and audio input levels, consider environment noise factors, and review recognition sensitivity settings.
**Voice responses sound unnatural**: Review your AI Agent's response formatting, remove special characters and formatting that don't translate to speech, adjust the TTS voice model or speaking rate, simplify complex responses for better verbal delivery, and add punctuation for natural pauses and pacing.
**Audio delays or lag**: Check your internet connection stability, review Twilio's service status for any issues, verify your server response times are optimal, consider geographic latency factors, and check for webhook processing delays.
### Call handling issues
**Calls not being answered**: Verify the integration is set to **Active**, check Twilio webhook configuration, review call logs in Twilio Console, confirm your environment is properly configured, and check for any error messages in Moveo logs.
**AI Agent not responding correctly**: Test the AI Agent in text mode first to verify logic, review voice-specific guidelines and adjust accordingly, check for speech recognition errors in logs, verify intent recognition is working properly, and consider adding confirmation steps for critical information.
## Phone issues
If the issue seems that the call is not connecting to Moveo at all, ensure that the phone number is set up correctly in Twilio console.
---
## Limitations
### Platform limitations
Call duration limits are based on your Twilio plan and pricing. Concurrent call limits are determined by your Twilio account tier. Voice availability varies by region due to geographic restrictions. Audio format constraints are defined by the specific codecs supported by Twilio. Trial Twilio accounts cannot be used with EU Moveo deployments; see [Trial account limitations](#trial-account-limitations).
### Integration constraints
Each integration configuration supports one phone number. Voice quality depends on the caller's connection and device. STT accuracy varies with accents and background noise. Complex multi-turn conversations may require optimization.
### Best practices
Monitor call duration and implement time limits if needed for cost control. Set up call queuing for high-volume scenarios. Provide clear voice prompts for better recognition. Have fallback options for unclear or failed recognition. Regularly review and optimize based on call analytics.
---
## Resources
### Twilio documentation
- [Twilio Voice Overview](https://www.twilio.com/docs/voice)
- [Twilio Console](https://console.twilio.com/)
- [Voice Pricing](https://www.twilio.com/voice/pricing)
- [Voice API Reference](https://www.twilio.com/docs/voice/api)
### Moveo resources
- [Quick deployment guide](../guides/quick-start.md)
- [Campaigns](../campaigns/campaigns.md)
- [Voice call transfer](./voice-call-transfer.md)
- [Telnyx Voice integration](./telnyx-voice.md)
### Support
- [Twilio Support](https://support.twilio.com/)
- Moveo support: support@moveo.ai
---
## Next steps
Once your Twilio Voice integration is active, optimize your AI Agent with voice-specific guidelines, test thoroughly with various scenarios and voice configuration, monitor call analytics to identify improvement areas, adjust TTS/STT settings based on user feedback, configure fallback options for complex queries, and train your team on monitoring and handling escalations.
---
## Viber
## Overview
Viber integration enables your AI Agent to communicate with customers through one of the world's
most popular messaging platforms. With over 1 billion users globally, Viber provides a secure,
feature-rich messaging environment where businesses can engage customers through automated
conversations, rich media, and interactive elements.
This integration enables:
- **Automated customer support** through Viber Business Messages
- **Rich messaging features** including carousels, buttons, and media
- **Global reach** with strong presence in Eastern Europe, Asia, and Middle East
- **Secure communication** with end-to-end encryption
- **Bot-managed interactions** with seamless handover capabilities
---
## Prerequisites
Before setting up the Viber integration, ensure you have:
✅ **Business requirements**
- Active business with legitimate use case for messaging
- Company registration documents
- Business website with contact information
- Valid business email address
✅ **Viber Bot Account**
- Approved Viber bot account (handled by Moveo)
- Access token provided by Moveo
- Bot name and avatar prepared
✅ **Moveo account setup**
- An active [AI Agent](../ai-agents/overview.md) configured
- An [environment](../environments/overview.md) selected for the integration
:::info
As of February 2024, Viber updated their bot creation process. Moveo handles bot
account creation on your behalf to ensure compliance with their new commercial model.
:::
---
## How it works
Viber integration operates through Viber's bot platform with Moveo managing the technical setup:
1. **Moveo creates bot** on your behalf through Viber's application process
2. **Customer starts conversation** by messaging your Viber bot
3. **AI Agent receives message** and processes using your configuration
4. **Response is sent** through Viber's messaging API
5. **Rich interactions** available through carousels, buttons, and media
6. **Handover possible** to human agents when needed
All messages are processed through Viber's secure infrastructure with full conversation history
maintained.
---
## Setup guide
Viber bot setup involves two main pathways depending on whether you have an existing bot or need a
new one.
### Bot account creation
#### Option 1: Existing Viber bot
If you already have a Viber bot account:
1. Locate your existing bot access token
2. Ensure bot is active and properly configured
3. Proceed directly to [Connect with Moveo](#step-2-connect-with-moveo)
#### Option 2: Request new Viber bot
For new bot account creation through Moveo:
1. **Contact Moveo support** at [support@moveo.ai](mailto:support@moveo.ai)
2. **Request Viber bot creation** with your business details
3. **Receive application form** from Moveo with Viber's requirements
4. **Complete form thoroughly** with:
- Company information and registration details
- Business website and contact information
- Bot purpose and expected usage
- Brand assets (logo, description)
5. **Submit to Moveo** for Viber application processing
6. **Await approval** (typically 5-10 business days)
7. **Receive access token** from Moveo once approved
:::info Bot commercial model
Viber's updated commercial model requires business verification and
approved use cases. Learn more in their
[official documentation](https://help.viber.com/hc/en-us/articles/15247629658525-Bot-commercial-model).
:::
### Step 2: Connect with Moveo
Once you have your bot access token, configure the integration:
1. **Navigate to Integrations** in your Moveo platform
2. **Select your environment** for the Viber integration
3. **Click Connect** under the Viber integration card
4. **Configure connection settings**:
- Enter your bot access token
- Set your AI Agent name (visible to users)
- Configure bot avatar/profile image
5. **Customize messaging**:
- Set autostart message (sent when users begin conversation)
- Configure welcome message and initial flow
6. **Optional configurations**:
- Set up user authentication if required
- Configure additional security settings
7. **Activate integration**:
- Set status to **ACTIVE**
- Save all configuration changes
---
## Configuration options
### Bot profile settings
- **Bot name**: Display name shown to users
- **Avatar**: Profile image representing your bot
- **Description**: Brief description of bot capabilities
- **Welcome message**: Initial message when conversation starts
### Message configuration
- **Autostart message**: Triggers AI Agent when user initiates chat
- **Response templates**: Configure standard response formats
- **Rich media settings**: Enable images, buttons, and carousels
- **Handover messages**: Configure human agent transition
### Security settings
- **User authentication**: Optional identity verification
- **Webhook security**: Token validation for message delivery
- **Rate limiting**: Configure message frequency limits
---
## Testing your integration
### Initial testing
1. **Send test message** to your Viber bot number
2. **Verify autostart message** triggers correctly
3. **Test AI Agent responses** across different scenarios
4. **Check rich media delivery** (images, buttons, carousels)
5. **Validate handover scenarios** if applicable
### Test scenarios
✓ **Welcome message flow** ✓ **FAQ responses and accuracy** ✓ **Rich media rendering** (carousels
work well on Viber) ✓ **Multi-turn conversations** ✓ **Error handling and fallbacks** ✓ **Handover
to human agents**
### Performance monitoring
- **Message delivery rates**
- **Response accuracy and relevance**
- **User engagement with rich elements**
- **Conversation completion rates**
---
## Common use cases
### Customer service automation
- Handle customer inquiries 24/7
- Provide instant answers to FAQs
- Process orders and booking requests
- Escalate complex issues to human agents
### Marketing and engagement
- Send promotional messages and offers
- Share product catalogs through carousels
- Conduct surveys and collect feedback
- Build customer relationships
### E-commerce support
- Product recommendations and information
- Order status and tracking updates
- Payment assistance and support
- Returns and refund processing
### Regional market penetration
- Target Eastern European markets effectively
- Reach users in Middle East and Asia
- Leverage Viber's strong regional presence
- Provide localized customer support
---
## Best practices
### Bot design
- Use clear, recognizable bot name and avatar
- Start conversations with engaging carousels (recommended)
- Provide clear navigation options
- Maintain consistent brand voice
### Message optimization
- Keep messages concise and scannable
- Use rich media effectively for engagement
- Implement quick reply options
- Provide clear call-to-action buttons
### User experience
- Set clear expectations about bot capabilities
- Offer easy access to human support
- Provide help commands and navigation
- Handle errors gracefully
### Compliance and etiquette
- Follow Viber's Terms of Service
- Respect user privacy and preferences
- Provide opt-out options
- Maintain professional communication
---
## Troubleshooting
Bot not responding to messages
- Verify access token is correct and active
- Check integration status is set to ACTIVE
- Ensure AI Agent is properly configured
- Confirm webhook connectivity with Viber
- Test with simple text messages first
Rich media not displaying
- Verify image URLs are publicly accessible
- Check file size limits (Viber has specific requirements)
- Ensure proper HTTPS URLs
- Test carousel configuration syntax
- Validate media format compatibility
Bot creation issues
- Ensure business information is complete and accurate
- Verify website has proper business contact information
- Check application status with Moveo support
- Provide additional documentation if requested
- Allow sufficient time for Viber approval process
Authentication problems
- Check user authentication configuration
- Verify webhook token validation
- Ensure proper SSL certificate on your domain
- Test authentication flow thoroughly
- Review security settings in integration
---
## Limitations
### Platform restrictions
- **Initial message limit**: First conversation message restricted to one
[response](../ai-agents/dialogs.md#responses)
- **Message frequency**: Rate limiting applied by Viber
- **Business verification**: Requires approved business use case
- **Geographic restrictions**: Some regions have limited support
### Integration constraints
- **Bot approval required**: All bots must be approved by Viber
- **Commercial model**: Subject to Viber's business messaging fees
- **Rich media limits**: File size and format restrictions apply
- **Authentication**: Optional but recommended for business use
:::tip
Start conversations with a carousel to maximize engagement within the single
response limitation.
:::
---
## Resources
### Documentation
- [Viber Bot Platform](https://developers.viber.com/docs/bots/)
- [Viber Business Messages](https://www.viber.com/business/)
- [Bot Commercial Model](https://help.viber.com/hc/en-us/articles/15247629658525-Bot-commercial-model)
### Tools
- [Viber Developer Portal](https://partners.viber.com/)
- [Bot Testing Tools](https://developers.viber.com/docs/tools-and-resources/)
### Support
- [Viber Support Center](https://help.viber.com)
- Moveo support: support@moveo.ai
---
## Next steps
Once your Viber integration is active:
1. **Optimize your bot profile** with engaging avatar and description
2. **Design effective carousel flows** for maximum engagement
3. **Test across different devices** and Viber versions
4. **Monitor user interactions** and optimize responses
5. **Scale gradually** as you learn user preferences
---
## Voice call transfer
When a voice AI Agent hands a call to a human agent or to your phone system, the call is
transferred with one of two **transfer methods**: a **Standard transfer** or a **SIP REFER**.
You pick the method on the [`Handover`](../ai-agents/operations/handover.md) action; this page
explains how each one works, how they differ, and when to use which.
## New to SIP?
A few terms used on this page, in plain language:
- **SIP** — the signaling protocol that sets up, changes, and ends voice calls. It carries the
call control messages; the audio itself flows separately.
- **SIP INVITE** — the message that *starts* a call to a destination.
- **SIP REFER** — a SIP message that asks the other party to *transfer* the call to a third
destination on its own, so the original party can leave.
- **SIP URI** — a SIP address, like `sip:agent@example.com` (the SIP equivalent of a phone number).
- **PBX / phone system** — the system on your side that receives the transferred call (for
example a contact center or office phone system).
- **Bridge** — keeping both call legs connected through Moveo, so Moveo stays in the call.
## Standard transfer
Moveo dials the destination and **bridges** the two calls: the caller and the destination are
connected *through Moveo*, which stays on the call for its full duration.
It works with a **phone number** (E.164) or a **SIP destination**. Because both legs stay open through Moveo, **recording continues** through the transfer and **both legs are billed** while connected.
## SIP REFER
Moveo asks the provider to **hand the call directly to your destination**, then **drops off** the
call entirely. Moveo is no longer in the path; the caller talks to your system directly.
It requires a **SIP destination** (a `sip:` URI), and the incoming call must have **arrived over SIP** — a caller who reached you over a phone line can't be transferred this way (use a Standard transfer instead). Once Moveo drops off, its **recording stops at the handoff** (recording continues on your side).
## Which one to use
| | Standard transfer | SIP REFER |
| --- | --- | --- |
| Moveo stays in the call | Yes | No (drops off) |
| Moveo-side recording after transfer | Continues | Stops at handoff |
| Destination type | Phone number or SIP | SIP only |
| Incoming call must be over SIP | No | Yes, see [Provider notes](#provider-notes) |
| If the transfer fails | Call drops | Call drops |
```mermaid
flowchart LR
subgraph standard [Standard transfer: Moveo stays in the path]
direction LR
c1[Caller] <--> m1[Moveo] <--> a1[Agent / phone system]
end
subgraph refer [SIP REFER: Moveo hands off and drops off]
direction LR
c2[Caller] <--> a2[Agent / phone system]
m2[Moveo] -. drops off .-> c2
end
```
Use **SIP REFER** when the destination is a SIP system (a PBX or contact center) reached by an
inbound SIP call and you want Moveo fully out of the path after the handoff — no second billed
leg, and no Moveo-side recording of the agent conversation. Use a **Standard transfer** for phone
destinations, or whenever the incoming call did not arrive over SIP.
## Provider notes
### Twilio
SIP REFER is only supported on SIP call legs. A call that reaches Moveo over a phone (PSTN) number
or a browser (web) call cannot be transferred with SIP REFER; use a Standard transfer for those.
See Twilio's [`` documentation](https://www.twilio.com/docs/voice/twiml/refer).
### Telnyx
SIP REFER needs a SIP destination. If the handover destination is a phone number, Moveo falls back
to a Standard transfer, so the transfer still completes.
For calls that reached Moveo over a phone (PSTN) number, whether the carrier passes the REFER on is
outside Moveo's control. Use a Standard transfer for those calls.
## See also
- [`Handover` action](../ai-agents/operations/handover.md) — configuring the transfer, including
custom SIP headers.
- [Twilio Voice integration](./twilio-voice.md).
- [Telnyx Voice integration](./telnyx-voice.md).
---
## Web channel configuration
## Configuration overview
The web channel offers extensive customization options to match your brand and user experience
requirements. You can configure these settings through the Moveo platform UI or override them
programmatically during initialization.
## Launcher appearance
Customize how the chat launcher button appears on your website.
### Launcher styles
Choose between different launcher styles:
- **Circle** (default): Circular button with icon
- **Box**: Rectangular button with text
### Teaser message
Add a teaser message next to the launcher to encourage interaction.
### Additional options
- **Focus trap**: Prevent users from browsing while conversing
- **Auto open**: Automatically open the widget when page loads
## Chat window appearance
Customize the visual design of the chat window.
### Theme customization
| Element | Default | Description |
| ------------- | ----------------- | ----------------------- |
| Primary color | `#1B66D6` | Main brand color |
| Text color | `#FFFFFF` | Text on primary color |
| Header title | Your AI Assistant | Chat window header text |
| Avatar | Default bot icon | AI Agent profile image |
## Start behavior
Configure how conversations begin when users open the chat.
### Available options
1. **User input**: User must type first message
2. **Autostart**: AI sends welcome message automatically
3. **Welcome screen**: Display options and FAQs
## Positioning
Control where and how the web channel appears on your page.
### Position options
- **Livechat** (default): Bottom-right floating widget
- **Embed**: Renders within page content
- **Pop-up**: Center of screen modal
### Widget alignment
For livechat mode, use the `widget_alignment` option to control which corner of the screen the launcher and chat window appear in.
| Value | Description |
| -------------- | ------------------------------------ |
| `bottom-right` | Bottom-right corner (default) |
| `bottom-left` | Bottom-left corner |
| `top-right` | Top-right corner, chat opens downward |
| `top-left` | Top-left corner, chat opens downward |
| `right` | Legacy alias for `bottom-right` |
| `left` | Legacy alias for `bottom-left` |
```javascript
MoveoAI.init({
integrationId: "YOUR-INTEGRATION-ID",
widget_alignment: "top-left",
});
```
### Custom positioning
For fine-grained control beyond `widget_alignment`, you can override positioning with CSS:
```css
/* Custom offset from bottom */
.web-client-container {
bottom: 100px;
}
```
:::tip
Use `widget_alignment` to position the launcher in a corner. Reserve CSS overrides for
fine-tuning offsets. When positioning the launcher on the left, consider removing the teaser message
for better visual balance.
:::
## Visitor information collection
Gather user information before or during the conversation.
### Pre-chat form fields
Enable collection of user data before chat starts:
| Field | Variable | Description |
| -------- | ---------------------------------- | -------------------- |
| Email | `user.email` | User's email address |
| Name | `user.display_name` | Display name |
| Phone | `user.phone` | Phone number |
| Address | `user.address` | Physical address |
| Language | `user.language` | Preferred language |
| Location | `user.location.latitude/longitude` | GPS coordinates |
### Additional options
- **Data policy disclaimer**: Require acceptance of terms
- **Location permission**: Request browser location access
- **Required fields**: Make specific fields mandatory
## Advanced settings
### File upload
Enable users to share files in the conversation:
- Maximum file size: 5MB
- Maximum files per message: 4
- Supported formats: Images, PDFs, documents
### Conversation history
Maintain chat history across page refreshes and navigation:
- Conversations persist for returning users
- History cleared after session timeout (1 hour default)
### Satisfaction survey
Collect feedback after conversations:
- Star ratings or thumbs up/down
- Optional comment field
- Triggered on conversation end
### Language settings
Override browser language detection:
- Set default language for all users
- Available languages include English, Spanish, French, German, and more
## Programmatic configuration
Override any setting during initialization:
```javascript
MoveoAI.init({
integrationId: "YOUR-INTEGRATION-ID",
version: "v2",
// Appearance
accent_color: "#FF5733",
background_color: "#2C3E50",
header_title: "Support Chat",
download_conversation: true,
avatar: "https://example.com/avatar.png",
bubble_image: "https://example.com/launcher.png",
font_family: "Roboto Mono",
// Behavior
auto_open: true,
focus_trap: false,
welcome_message: "How can I help?",
welcome_trigger_message: "Hello!",
virtual_agent_name: "Alex",
// Window settings
chatWindow: {
width: "400px",
height: "600px",
},
// Positioning
widget_alignment: "bottom-right", // "bottom-right" | "bottom-left" | "top-right" | "top-left"
// Launcher settings
launcher: {
size: "60px",
show: true, // Set false to hide launcher
},
show_close_icon: true, // Show/hide launcher close icon
// Language
language: "en",
// Session behavior
close_session_if_empty: false,
// Accessibility
webchat_aria_label: "Chat with support",
enableAccessibilityWidget: true,
})
.then((instance) => {
console.log("Chat configured and connected");
})
.catch((error) => console.error(error));
```
## CSS customization
Use the `setCSSVariables()` method for advanced runtime styling. This enables per-customer theming without code changes.
```javascript
instance.setCSSVariables({
"--moveo-header-text-color": "#10038C",
"--color-options-background": "#CCF3FD",
});
```
### Available CSS variables
#### General
| Variable | Description |
| -------- | ----------- |
| `--color-chat-background` | Chat container background |
#### Launcher
| Variable | Description |
| -------- | ----------- |
| `--color-launcher-background` | Launcher button background |
| `--color-launcher-foreground` | Launcher button icon color |
| `--color-opening-message-background` | Teaser message background |
| `--color-opening-message-foreground` | Teaser message text color |
#### Header
| Variable | Description |
| -------- | ----------- |
| `--moveo-header-background` | Header background color |
| `--moveo-header-text-color` | Header text and icon color |
#### Messages
| Variable | Description |
| -------- | ----------- |
| `--color-message-user-background` | User message bubble background |
| `--font-size-brain-message` | AI message text size (`small`, `medium`, or `large`) |
#### Quick replies (Options)
| Variable | Description |
| -------- | ----------- |
| `--color-options-background` | Quick reply button background |
| `--color-options-foreground` | Quick reply button text |
| `--color-options-border` | Quick reply button border |
#### System messages (Swimmlanes)
| Variable | Description |
| -------- | ----------- |
| `--color-swimmlane-background` | System message background |
| `--color-swimmlane-foreground` | System message text |
#### Carousel cards
| Variable | Description |
| -------- | ----------- |
| `--color-carousel-card-background` | Carousel card background |
| `--color-carousel-card-foreground` | Carousel card text |
| `--color-carousel-card-border` | Carousel card border |
### Example: Complete branded theme
```javascript
instance.setCSSVariables({
// Header
"--moveo-header-text-color": "#10038C",
// Quick replies
"--color-options-background": "#CCF3FD",
"--color-options-foreground": "#10038C",
"--color-options-border": "#CCF3FD",
// System messages
"--color-swimmlane-background": "#F2EBE7",
"--color-swimmlane-foreground": "#1E222D",
});
```
## Language and localization
### Default language hierarchy
Language selection follows this priority:
1. User selection in visitor form
2. Configuration default
3. Browser language
4. English fallback
### Available languages
| Code | Language |
| ------- | ---------------------- |
| `de` | 🇩🇪 German |
| `el` | 🇬🇷 Greek |
| `en` | 🇺🇸 English |
| `es` | 🇪🇸 Spanish |
| `fr` | 🇫🇷 French |
| `it` | 🇮🇹 Italian |
| `pt-br` | 🇧🇷 Portuguese (Brazil) |
| `nl` | 🇳🇱 Dutch |
| `zh` | 🇨🇳 Chinese |
| `ar` | 🇸🇦 Arabic |
| `ja` | 🇯🇵 Japanese |
| `tr` | 🇹🇷 Turkish |
### Dynamic language switching
Change language programmatically:
```javascript
instance.setLocale("es"); // Switch to Spanish
```
## Configuration best practices
1. **Brand consistency**: Match your website's colors and fonts
2. **Mobile optimization**: Test positioning on different screen sizes
3. **Performance**: Load custom assets from CDN
4. **Accessibility**: Provide ARIA labels and high contrast options
5. **User privacy**: Only collect necessary information
6. **Testing**: Preview changes before going live
## Trusted domains
Secure your integration by specifying allowed domains:
- Add all production domains
- Include staging/test environments
- Supports wildcards: `*.example.com`
- Blocks unauthorized usage
## Next steps
- [Implement methods and events](./developer-guide)
- [Troubleshoot integration issues](./troubleshooting)
---
## Web channel developer guide
## Instance methods
The web channel exposes methods to control behavior and interact with the chat programmatically.
```javascript
MoveoAI.init({
integrationId: "YOUR-INTEGRATION-ID",
version: "v2",
}).then((instance) => {
// Use instance methods here
});
```
### Window control
#### openWindow()
Opens the chat window if currently closed.
```javascript
instance.openWindow();
```
#### closeWindow()
Closes the chat window if currently open.
```javascript
instance.closeWindow();
```
### Messaging
#### sendMessage()
Programmatically send a message to the AI Agent.
```javascript
instance.sendMessage({ text: "Hello, I need help" });
// Open window after sending
instance.sendMessage({ text: "Start conversation" });
instance.openWindow();
```
**Behavior:**
- If conversation exists: sends immediately
- No conversation: overrides welcome message
- With visitor form: sends after form completion
### User context
#### updateContext()
Update user information or session data dynamically.
```javascript
instance.updateContext({
user: {
display_name: "John Doe",
email: "john@example.com",
},
customer_id: "12345",
account_type: "premium",
});
```
### Session management
#### destroy()
End the conversation and hide the web channel completely.
```javascript
// End session when user logs out
if (userLoggedOut) {
instance.destroy();
}
```
:::note
After calling `destroy()`, you can reinitialize the web channel with `MoveoAI.init()`.
:::
### Styling
#### setCSSVariables()
Dynamically customize the web channel appearance at runtime using CSS variables. This enables per-customer theming without code changes.
```javascript
instance.setCSSVariables({
"--moveo-header-text-color": "#10038C",
"--color-options-background": "#CCF3FD",
"--color-options-foreground": "#10038C",
});
```
**Available CSS variables:**
| Variable | Purpose |
|----------|---------|
| `--color-launcher-background` | Launcher button background |
| `--color-launcher-foreground` | Launcher button icon color |
| `--color-opening-message-background` | Teaser message background |
| `--color-opening-message-foreground` | Teaser message text color |
| `--color-options-background` | Quick reply button background |
| `--color-options-foreground` | Quick reply button text |
| `--color-options-border` | Quick reply button border |
| `--color-swimmlane-background` | System message background |
| `--color-swimmlane-foreground` | System message text |
| `--color-carousel-card-background` | Carousel card background |
| `--color-carousel-card-foreground` | Carousel card text |
| `--color-carousel-card-border` | Carousel card border |
| `--color-chat-background` | Chat container background |
| `--color-message-user-background` | User message bubble background |
| `--moveo-header-background` | Header background color |
| `--moveo-header-text-color` | Header text and icon color |
| `--font-size-brain-message` | AI message text size (`small`, `medium`, or `large`) |
**Example: Custom branded theme**
```javascript
instance.setCSSVariables({
"--moveo-header-text-color": "#10038C",
"--color-options-background": "#CCF3FD",
"--color-options-foreground": "#10038C",
"--color-options-border": "#CCF3FD",
"--color-swimmlane-background": "#F2EBE7",
"--color-swimmlane-foreground": "#1E222D",
});
```
**Example: Launcher customization**
```javascript
instance.setCSSVariables({
"--color-launcher-background": "#10b981",
"--color-launcher-foreground": "#ffffff",
"--color-opening-message-background": "#10b981",
"--color-opening-message-foreground": "#ffffff",
});
```
**Example: Header customization**
```javascript
instance.setCSSVariables({
"--moveo-header-background": "#11366b",
"--moveo-header-text-color": "#ffffff",
});
```
### Localization
#### setLocale()
Change the web channel language dynamically.
```javascript
instance.setLocale("es"); // Switch to Spanish
```
## Event listeners
Subscribe to web channel events to track user interactions and session changes.
### Session events
#### onSessionCreated
Fired when a new conversation starts.
```javascript
instance.onSessionCreated(() => {
console.log("New session started");
// Track in analytics
analytics.track("Chat Started");
// Set initial context
instance.updateContext({
page_url: window.location.href,
timestamp: new Date().toISOString(),
});
});
```
#### onSessionReconnected
Fired when reconnecting to existing session (with history enabled).
```javascript
instance.onSessionReconnected(() => {
console.log("Reconnected to existing session");
// Update context with new page info
instance.updateContext({
returned_user: true,
return_page: window.location.pathname,
});
});
```
#### onSessionClosed
Fired when the chat session terminates.
```javascript
instance.onSessionClosed(() => {
console.log("Session terminated");
// Clean up or redirect
if (shouldRedirect) {
window.location.href = "/thank-you";
}
});
```
### Live chat events
#### onConversationClosed
Fired when live chat conversation is resolved/closed.
```javascript
instance.onConversationClosed(() => {
console.log("Live chat ended");
// Show feedback form
showCustomFeedbackModal();
});
```
#### onMemberLeave
Fired when an agent leaves the conversation.
```javascript
instance.onMemberLeave(() => {
console.log("Agent left the conversation");
// Notify user
showNotification("Agent has disconnected");
});
```
### Window events
#### onWebchatOpened
Fired when chat window opens.
```javascript
instance.onWebchatOpened(() => {
// Pause video when chat opens
videoPlayer.pause();
// Track engagement
analytics.track("Chat Opened");
});
```
#### onWebchatClosed
Fired when chat window closes.
```javascript
instance.onWebchatClosed(() => {
// Resume video when chat closes
videoPlayer.play();
// Save draft message if any
saveDraftMessage();
});
```
### Activity tracking
#### onUserActivity
Fired on any user activity in the chat.
```javascript
let inactivityTimer;
instance.onUserActivity(() => {
// Reset inactivity timer
clearTimeout(inactivityTimer);
inactivityTimer = setTimeout(() => {
console.log("User inactive for 5 minutes");
}, 300000);
});
```
## Analytics events
Track detailed user interactions with analytics events.
### Setup
```javascript
instance.onAnalyticsEvent((eventData) => {
const { event, properties, timestamp } = eventData;
// Send to your analytics platform
analytics.track(event, {
...properties,
chat_session_id: properties.session_id,
timestamp: timestamp,
});
});
```
### Available events
#### Interaction events
- `launcher_clicked` - User clicks launcher
- `chat_expanded` - Chat window opens
- `minimize_icon_clicked` - Minimize button clicked
- `close_icon_clicked` - Close button clicked
- `message_click` - Message bubble clicked
#### Session events
- `session_start` - New session begins
- `session_end` - Session ends
- `welcome_form_submitted` - Pre-chat form completed
#### Engagement events
- `rating_clicked` - User selects rating
- `rating_submitted` - Rating confirmed
- `download_conversation_clicked` - Export chat
#### Popover events
- `popover_inactivity_end_chat_clicked` - End inactive chat
- `popover_inactivity_continue_clicked` - Continue after inactivity
- `resolved_popover_continue_clicked` - Continue resolved chat
### Event data structure
```javascript
{
"timestamp": "2025-01-20T10:30:45.123Z",
"event": "launcher_clicked",
"properties": {
"session_id": "uuid-here",
"page_url": "https://example.com/products",
"user_id": "user-123" // If authenticated
}
}
```
## Advanced integration patterns
### Custom launcher
Hide default launcher and use custom button:
```javascript
MoveoAI.init({
integrationId: "YOUR-INTEGRATION-ID",
version: "v2",
launcher: { show: false }, // Hide default launcher
}).then((instance) => {
// Custom button opens chat
document.getElementById("custom-chat-btn").addEventListener("click", () => {
instance.openWindow();
});
});
```
### Contextual messaging
Send different messages based on page:
```javascript
const pageMessages = {
"/products": "Looking for product information?",
"/pricing": "Need help choosing a plan?",
"/support": "How can we assist you today?",
};
instance.sendMessage({
text: pageMessages[window.location.pathname] || "Hello!",
});
```
### User authentication flow
```javascript
// After user logs in
async function onUserLogin(user) {
// Get fresh JWT from server
const token = await fetchUserToken(user.id);
// Destroy old session
if (window.chatInstance) {
window.chatInstance.destroy();
}
// Initialize authenticated session
window.chatInstance = await MoveoAI.init({
integrationId: "YOUR-INTEGRATION-ID",
identityToken: token,
version: "v2",
});
// Set user context
window.chatInstance.updateContext({
user: {
display_name: user.name,
email: user.email,
},
});
}
```
### Analytics integration
```javascript
// Google Analytics 4
instance.onAnalyticsEvent((eventData) => {
gtag("event", eventData.event, {
chat_session_id: eventData.properties.session_id,
engagement_time_msec: 100,
});
});
// Segment
instance.onAnalyticsEvent((eventData) => {
analytics.track(eventData.event, eventData.properties);
});
// Mixpanel
instance.onAnalyticsEvent((eventData) => {
mixpanel.track(eventData.event, eventData.properties);
});
```
### Error handling
```javascript
MoveoAI.init({
integrationId: "YOUR-INTEGRATION-ID",
version: "v2",
})
.then((instance) => {
window.chatInstance = instance;
})
.catch((error) => {
console.error("Chat initialization failed:", error);
// Show fallback contact options
document.getElementById("fallback-contact").style.display = "block";
// Report to monitoring
errorReporting.log(error);
});
```
### Multi-language support
```javascript
// Detect user language preference
const userLang =
localStorage.getItem("language") || navigator.language.substring(0, 2);
// Initialize with user's language
MoveoAI.init({
integrationId: "YOUR-INTEGRATION-ID",
language: userLang,
version: "v2",
}).then((instance) => {
// Allow language switching
document.getElementById("lang-selector").addEventListener("change", (e) => {
instance.setLocale(e.target.value);
localStorage.setItem("language", e.target.value);
});
});
```
## Testing and debugging
### Development mode
```javascript
const isDev = window.location.hostname === "localhost";
MoveoAI.init({
integrationId: isDev ? "DEV-INTEGRATION-ID" : "PROD-INTEGRATION-ID",
version: "v2",
}).then((instance) => {
if (isDev) {
// Expose instance for debugging
window.debugChat = instance;
// Log all events
instance.onAnalyticsEvent(console.log);
}
});
```
### Event monitoring
```javascript
// Monitor all chat events
const events = [
"onSessionCreated",
"onSessionReconnected",
"onSessionClosed",
"onWebchatOpened",
"onWebchatClosed",
];
events.forEach((eventName) => {
instance[eventName](() => {
console.log(`Event fired: ${eventName}`, new Date());
});
});
```
## Performance optimization
### Lazy loading
```javascript
// Load chat only when needed
function loadChat() {
const script = document.createElement("script");
script.src = "https://web.moveo.ai/web-client.min.js";
script.onload = () => {
MoveoAI.init({
integrationId: "YOUR-INTEGRATION-ID",
version: "v2",
});
};
document.body.appendChild(script);
}
// Load on user interaction
document
.getElementById("chat-trigger")
.addEventListener("click", loadChat, { once: true });
```
### Resource cleanup
```javascript
// Clean up on page unload
window.addEventListener("beforeunload", () => {
if (window.chatInstance) {
// Save conversation state if needed
localStorage.setItem(
"chatState",
JSON.stringify({
timestamp: Date.now(),
page: window.location.href,
})
);
}
});
```
## Security considerations
1. **Never expose sensitive data** in client-side code
2. **Validate tokens** server-side before passing to web channel
3. **Use HTTPS** for all communications
4. **Implement rate limiting** for API calls
5. **Sanitize user input** before passing to context
6. **Monitor for abuse** using analytics events
## Next steps
- [Platform-specific integration guides](./troubleshooting)
- [Configuration options](./configuration)
---
## Getting started with web channel
## Overview
The Moveo web channel enables you to add AI-powered conversations directly to your website. This
channel provides a customizable chat interface that can be styled to match your brand and configured
to meet your specific requirements.
:::note
By default, a conversation in the web channel stays active for one hour if the user does not
close the window. The web channel does not load if the user agent (browser) is a
**bot**.
:::
## Quick start
To add the web channel to your website:
1. Go to **Integrations** in your Moveo account
2. Select your environment
3. Click **Connect** below the **Web** integration
4. Copy the generated snippet and add it before the `
` tag:
```html
```
5. Add your domain to the trusted domains list
6. Set the web channel state to **Active**
That's it! Your web channel is now ready to receive messages.
## Installation options
### Standard installation
The standard installation loads the web channel on every page:
```html
```
### Embed mode
Render the chat within your page content instead of as a floating widget:
```html
```
### Delayed initialization
Wait for page load or user interaction before initializing:
```html
```
## User authentication
Secure your web channel and authenticate users to ensure messages come from verified customers only.
### Why authenticate?
Authentication provides:
- **Security**: Verify that messages come from your actual customers
- **Personalization**: Pass user data securely to provide tailored responses
- **Privacy**: Encrypt sensitive information end-to-end
### Basic authentication setup
1. **Generate RSA keys**:
```bash
# Private key (keep secure on your server)
openssl genrsa -out private.pem 2048
# Public key (add to Moveo)
openssl rsa -in private.pem -outform PEM -pubout -out public.pem
```
2. **Add public key to Moveo**:
- Go to **Integrations** → **Web** → **Advanced security settings**
- Enable **Activate end-to-end encryption**
- Paste your public key
3. **Generate JWT on your server**:
```js
const jwt = require('jsonwebtoken');
function generateToken(userId) {
const payload = {
sub: userId, // Required: unique user ID
iss: 'yourdomain.com', // Required: issuer
};
return jwt.sign(payload, process.env.PRIVATE_RSA_KEY, {
algorithm: 'RS256',
expiresIn: '5m', // Max 5 minutes
});
}
```
```go
"crypto/x509"
"encoding/pem"
"github.com/golang-jwt/jwt"
"time"
)
func generateToken(userId string) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
"sub": userId, // Required
"iss": "yourdomain.com", // Required
"exp": time.Now().Add(5 * time.Minute).Unix(),
})
// Sign with private key
privateKey := loadPrivateKey()
return token.SignedString(privateKey)
}
```
4. **Initialize with authentication**:
```html
```
### Passing encrypted user data
To securely pass sensitive user information (e.g., account details, VIP status):
1. **Get Moveo's public key** from your web integration settings
2. **Encrypt context with AES-256**
3. **Encrypt AES key with RSA**
4. **Include in JWT**:
:::warning Match the encryption scheme exactly
Moveo decrypts `encryption_key` and `init_vector` with **RSA-OAEP (SHA-256)**, and the
`context` with **AES-256-CBC**. Libraries that default to a different padding or hash
produce tokens Moveo cannot decrypt. In particular, `node-rsa` defaults to OAEP with
SHA-1, so always set the OAEP hash to SHA-256 (as shown below).
:::
```js
const crypto = require("crypto");
const jwt = require("jsonwebtoken");
function generateSecureToken(userId, userContext) {
// Generate AES key and IV
const aesKey = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
// Encrypt context with AES-256-CBC
const cipher = crypto.createCipheriv("aes-256-cbc", aesKey, iv);
let encrypted = cipher.update(JSON.stringify(userContext), "utf8", "base64");
encrypted += cipher.final("base64");
// Encrypt the AES key and IV with Moveo's RSA public key.
// Moveo decrypts with RSA-OAEP / SHA-256, so the padding and hash must
// match exactly or decryption fails server-side.
const oaep = {
key: process.env.MOVEO_PUBLIC_KEY,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: "sha256",
};
const encryptedKey = crypto.publicEncrypt(oaep, aesKey).toString("base64");
const encryptedIV = crypto.publicEncrypt(oaep, iv).toString("base64");
// Create JWT with encrypted data
const payload = {
sub: userId,
iss: "yourdomain.com",
context: encrypted, // AES encrypted context
encryption_key: encryptedKey, // RSA encrypted AES key
init_vector: encryptedIV, // RSA encrypted IV
};
return jwt.sign(payload, process.env.PRIVATE_RSA_KEY, {
algorithm: "RS256",
expiresIn: "5m",
});
}
// Usage
const userContext = {
user: {
email: "user@example.com",
is_vip: true,
account_tier: "premium",
},
contract_id: "12345",
credit_limit: 10000,
};
const token = generateSecureToken("user-123", userContext);
```
The encrypted context is available in your AI Agent for personalization but never sent back to the
client, ensuring sensitive data remains secure.
### Authentication flow
```mermaid
sequenceDiagram
participant S as Your Server
participant W as Web Client
participant M as Moveo.AI
S->>W: Generate JWT (signed with private key)
W->>M: Send JWT as identity token
M->>M: Verify signature with public key
M->>M: Check expiration claim
alt Token Valid
M->>W: Session created
W->>M: User sends message
M->>W: AI responds
else Token Invalid
M->>W: JWT rejected
W->>S: Request new token
S->>W: Generate fresh JWT
W->>M: Retry with new token
end
```
## Security best practices
1. **Keep private keys secure** - Never expose them in client-side code
2. **Use short expiration times** - Max 5 minutes for JWT tokens
3. **Validate on server** - Always generate tokens server-side
4. **Encrypt sensitive data** - Use AES encryption for context data
5. **Trusted domains** - Only allow your domains in settings
6. **HTTPS only** - Always use secure connections
## Mobile app integration
To use the web channel in a mobile application:
1. Host the web channel on a webpage accessible by URL
2. Embed the webpage using a WebView or iframe:
```html