---
title: "Agents"
description: "What a Raíz agent is made of, when it is ready to talk to patients, its settings, and how to change it safely."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.getarbol.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Agents

An agent is the AI that talks to your patients for you. You tell it in plain words what its job is and what it must never do, give it documents to consult and tools to look things up in your systems, and put it on a phone number, a WhatsApp number or your website's chat. It answers there, and a voice agent can also call people for a [campaign](/en/developers/raiz/campaigns/). In the Raíz Dashboard, agents are called Workers.

To create one step by step, follow [Create an agent](/en/developers/guides/create-an-agent/). This page explains the parts.

## Voice or text

Every agent has one `modality`, chosen when it's created:

| `modality` | Talks on | How it opens |
| --- | --- | --- |
| `voice` | Phone calls, inbound and outbound. | `firstMessage`: what it says when a call connects. |
| `text` | WhatsApp and web chat. | On WhatsApp, `settings.greeting` decides how it answers a contact who opens a conversation. A conversation your organization starts on WhatsApp opens with an approved [template](/en/developers/raiz/campaigns/#whatsapp-templates). |

The modality must fit the channel: voice agents serve phone numbers, text agents serve WhatsApp numbers and web chat. It can change only while the agent has no channels and no published voice line; otherwise the update answers `409 AGENT_MODALITY_LOCKED`.

## What an agent is made of

| Field | What it is |
| --- | --- |
| `name` | Up to 120 characters. Required, with `modality`. |
| `instructions` | Its job in plain words: its role, what it may and may not do, the facts it relies on. Up to 100,000 characters. |
| `firstMessage` | Voice agents: what it says first when a call connects, inbound or outbound. |
| `language`, `timeZone` | A BCP 47 language tag such as `es-CO`, and an IANA time zone such as `America/Bogota`. |
| `status` | `active` or `paused`. A paused agent answers nothing and places no calls. |
| `settings` | How it behaves. See [Settings](#settings). |
| `knowledgeDocumentIds` | Up to 100 [Knowledge](/en/developers/raiz/knowledge/) documents it consults. |
| `integrationTools` | Up to 200 tools of your [integrations](/en/developers/integrations/) it may call. See [Tools and skills](#tools-and-skills). |
| `integrationSkills` | Text agents: up to 32 skills that your connections publish. |
| `skills` | Text agents: up to 32 procedures of your own, 256 KiB in total. |
| `description` | Free text, up to 2,000 characters. |

An agent also reports its `channels` (up to 50, each with its type and status), `channelCount`, `toolCount` and `version`.

## Ready and synced

Two fields say whether an agent can work:

- **`ready`** is `true` when it can hold conversations: it is `active`, it has instructions and, for a voice agent, it is published for calls.
- **`synced`** says whether calls already use its current version. A voice agent is published to its phone lines in the background after each change; until `synced` is `true`, calls use the older version, and `syncErrorCode` gives the error of the last attempt. Fixing the cause, such as an invalid `voiceId` or missing instructions, publishes it again. Text agents are always `synced`.

```bash
curl -s "https://api.getarbol.com/v1/raiz/agents/agt_01jd8x5k2m7q9r3t6v8w0y4z1b" \
  --header "Authorization: Bearer $ARBOL_API_KEY" \
  | jq '.data | {status, ready, synced, syncErrorCode, version}'
```

## Settings

`settings` holds how the agent behaves. Text settings apply only to text agents and voice settings only to voice agents; a setting that doesn't fit the modality, or that contradicts another, answers `422 AGENT_SETTINGS_INVALID`. In an update, `settings` is the complete new value: keys you leave out return to their default. Some of them:

| Setting | Agents | What it does |
| --- | --- | --- |
| `model` | Text | The tier that writes replies: `arbolito/agile` (the default; quickest and least expensive), `arbolito/balanced`, `arbolito/advanced` or `arbolito/top` (the most capable). |
| `reasoningEffort` | Text | How much `arbolito/advanced` and `arbolito/top` deliberate, from `none` to `xhigh`. A tier that doesn't reason refuses it. |
| `greeting` | Text, WhatsApp | How it answers a contact who opens a conversation nobody has answered yet. Its `type` is `message` (a fixed text), `businessApp` (the greeting the WhatsApp Business app sends) or `instructions` (extra instructions for its first reply). |
| `followUpAfterMinutes`, `followUpMessage` | Text | When it spoke last and asked something, write once more after this many minutes of silence (WhatsApp only, within its 24-hour window). |
| `sessionCloseAfterMinutes` | Text | Close a conversation after this many minutes without messages. Default: 1,440 on WhatsApp, 30 on web chat. |
| `humanEscalation.instructions` | Both | When to ask your team to step in. An explicit request for a person is always respected. |
| `handoffMessage` | Text, WhatsApp | The notice added after a handoff to your team. An empty string turns the notice off; the handoff still happens. |
| `automaticKnowledge` | Text | Look up relevant Knowledge before answering a substantive message, not only when the agent searches. |
| `monthlyTokenBudget` | Text | A monthly token limit. On WhatsApp, once it's spent, the contact reads `budgetExhaustedMessage` and the conversation goes to your team. |
| `evalGate` | Text, WhatsApp | Require a passing [evaluation run](/en/developers/raiz/evaluations/#require-a-passing-run) before a change to what the model reads goes live. |
| `voice.voiceId` | Voice | A voice from [`raiz.voices.list`](/api/raiz/voices/list/), which filters voices by `language` and links samples to listen to. |
| `voice.llm` | Voice | The tier it thinks with on calls, from the same four. |
| `voice.recordCalls` | Voice | Keep each call's recording. |
| `voice.redactKeypadInput` | Voice | Replace numbers typed on the phone keypad with `<REDACTED>` in stored transcripts and analysis, for future calls. The agent still receives the digits. Off by default. |
| `voice.maxDurationSeconds` | Voice | The longest a call may last. Default: 600 seconds. |

The [reference](/api/raiz/agents/update/) lists every setting, such as `humanReplyTimeoutMinutes`: when automatic replies resume after a person takes over a WhatsApp chat.

## Tools and skills

- **Integration tools.** Each entry pairs a `connectionId` with a `tool` that connection offers, as [`account.connections.list`](/api/account/connections/list/) lists them. Raíz saves each tool with its definition at that moment, its `digest`, and its `effect`: `read` only looks, `write` may change data. If the connection's tool changes later, the agent keeps the saved definition until you save the agent again. A tool that isn't on the connection, or that Raíz can't run, answers `422 INTEGRATION_TOOL_UNAVAILABLE`.
- **Integration skills** are skills a connection publishes, saved with their text at that moment. Their names must differ from the agent's own skills.
- **Skills** are your own procedures, each with a `name`, a one-line `description`, its `instructions` and up to 16 reference `resources`. The agent loads one when it needs it. Skills never give an agent more tools and never run scripts.

For something temporary, such as a day without appointments, post a [bulletin](/en/developers/raiz/campaigns/#bulletins) instead of changing the instructions.

## Versions and safe updates

Every agent carries a `version`. Send the one you read as `expectedVersion` to [`raiz.agents.update`](/api/raiz/agents/update/): the change applies only if nobody changed the agent since, and otherwise answers `409 VERSION_CONFLICT`, so read it again and reapply your change. Fields you leave out stay as they are; `settings`, `integrationTools`, `integrationSkills`, `skills` and `knowledgeDocumentIds` replace the whole value.

With `settings.evalGate` on, an update that changes what the model reads (instructions, skills, integration skills, `model` or `reasoningEffort`) must also send `evalRunId`: a completed [evaluation run](/en/developers/raiz/evaluations/) of exactly that content in which every case passed. Otherwise it answers `409 EVAL_GATE_UNMET`.

## Operations

| Operation | What it does |
| --- | --- |
| [`raiz.agents.create`](/api/raiz/agents/create/) | Create an agent. Not idempotent: after an unknown outcome, list agents before trying again. |
| [`raiz.agents.get`](/api/raiz/agents/get/) | Read an agent's complete setup by `agentId`. |
| [`raiz.agents.list`](/api/raiz/agents/list/) | Find agents by `status`, `modality` or `q` (the name), newest first. |
| [`raiz.agents.update`](/api/raiz/agents/update/) | Change an agent. `"status": "paused"` stops it from answering and calling. |
| [`raiz.voices.list`](/api/raiz/voices/list/) | Find a voice for a voice agent. |
| [`raiz.channels.update`](/api/raiz/channels/update/) | Put the agent on a channel. See [Channels](/en/developers/raiz/channels/#assign-an-agent-and-switch-traffic). |

All of them are in the [Agents reference](/api/raiz/tags/agents/), and the [Create an agent](/en/developers/guides/create-an-agent/) guide shows each request and its errors.

Source: https://docs.getarbol.com/en/developers/raiz/agents/index.mdx
