---
title: "Data, reports and tasks"
description: "The structured data Raíz agents capture as definitions and facts, the reports built on it, the change history, and the tasks that run in the background."
---

> 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.

# Data, reports and tasks

Besides talking, your agents capture data, such as why a patient called or which site they prefer. You decide what to capture with definitions, and each value captured for a contact or a conversation is a fact that records who wrote it and where it came from. Reports turn conversations and facts into numbers, the change history records who changed what, and tasks are the long jobs that run in the background.

## Definitions

A definition is one thing to capture:

| Field | What it is |
| --- | --- |
| `kind` | `attribute` (a property), `category` (a classification), `metric` (a measured number, with a UCUM `unit`) or `assessment` (a judgement about a conversation; yes/no assessments feed the assessment report). |
| `subject` | What its facts describe: a `contact` or a `conversation`. |
| `valueType` | `text`, `number`, `boolean`, `date` (`YYYY-MM-DD`) or `option`, with up to 100 `options`, each with a `key` and a `label`. |
| `key` | A stable machine name: lowercase letters, digits and `_`, starting with a letter. A CSV column with this header [imports](/en/developers/raiz/contacts/#import-from-a-csv) into it. |
| `name`, `instructions` | Its name for people, and how the AI decides the value. |
| `agentIds` | The agents that use it. Empty: every agent. |
| `status` | `draft` while you prepare it, `active` when agents use it and it accepts facts, or `retired`. |

[`raiz.definitions.create`](/api/raiz/definitions/create/) adds one; a key that a draft or active definition already uses answers `409 KEY_IN_USE`. [`raiz.definitions.update`](/api/raiz/definitions/update/) changes one, with `expectedVersion`. Its `options` and `agentIds` are complete sets, and an option you leave out is retired, never deleted, because facts use it. The value type and subject can't change once the definition has facts (`409 DEFINITION_TYPE_LOCKED`), and a retired definition can't change at all. [`raiz.definitions.list`](/api/raiz/definitions/list/) lists draft and active definitions by default, by `kind`, `subject` and `status`.

## Facts

A fact is the value of a definition for one contact or one conversation. Contacts and conversations come with their current facts, in `facts`: for each definition, the newest assertion that wasn't rejected, while older ones stay as history. Each fact says who wrote it (`author`: `person`, `ai`, `system`, `import` or `provider`), how sure the AI was (`confidence`, from 0 to 1), when it was observed, and its `reviewStatus`.

[`raiz.facts.create`](/api/raiz/facts/create/) records a value under an active definition. The value follows the definition's type: a string, a number, a boolean, a `YYYY-MM-DD` date or an option key. Give `contactId` or `conversationId`, whichever the definition's subject is. Say where the value came from with `reason` and, as evidence, a closed `sourceConversationId` and its `sourceMessageId`. In this example, the definition is a contact's preferred site, of type `option`, and `north` is one of its option keys:

```bash
curl https://api.getarbol.com/v1/raiz/facts \
  --request POST \
  --header "Authorization: Bearer $ARBOL_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "definitionId": "def_01jd8xfm2n3p4q5r6s7t8v9w0x",
    "contactId": "cnt_01jd8x7c4d5e6f7g8h9j0k1m2n",
    "value": "north",
    "reason": "The patient said they prefer the North site.",
    "sourceConversationId": "cnv_01jd8x8d5e6f7g8h9j0k1m2n3p"
  }'
```

`"valueStatus": "unknown"` or `"not_applicable"`, without a `value`, records that there is none. [`raiz.facts.update`](/api/raiz/facts/update/) reviews a fact: `confirmed` vouches for it, and `rejected` withdraws it, so the previous assertion becomes current again.

## Reports

[`raiz.reports.get`](/api/raiz/reports/get/) answers the numbers behind a question, and `name` picks the report:

| `name` | Rows | Filters |
| --- | --- | --- |
| `conversations_daily` | Conversations the AI took part in, per day, agent, channel type and direction, with successes, failures, escalations and negative sentiment. | `agentId`, `channelType` |
| `booking_outcomes` | Bookings from verified booking receipts, per completion day, agent and integration: new appointments, reschedules, cancellations, and failed, pending, unverified and duplicate receipts. | `agentId` |
| `tool_calls_daily` | Tool calls per day, agent and tool, with failures and durations. | `agentId` |
| `tool_calls` | Each tool call, newest first, without its inputs or outputs. | `agentId` |
| `assessment_results_daily` | Assessment results per day and definition: yes, no and unknown. | `definitionId` |
| `pqrsf_daily` | PQRSF classification, confirmed resolutions and referrals, from the `pqrsf_*` facts. | `agentId`, `channelType` |
| `campaign_progress` | Each campaign's recipients by status. | `campaignId` |

Daily reports count days in the organization's time zone, from `from` to `to` (`YYYY-MM-DD`, both included; the last 30 days by default). A report has at most 1,000 rows, and `hasMore` means narrow the range or the filters. A filter the report doesn't take answers `400 REPORT_FILTER_UNSUPPORTED`. In `booking_outcomes`, `createdCount` counts new appointments the AI created, not confirmations of existing ones, and `confirmedCount` is another name for it, so never add the two. Its rows are historical receipts, not an appointment's current status.

## Change history

[`raiz.changes.list`](/api/raiz/changes/list/) is the audit log: who created, updated or deleted what, when and why, newest first. Each change has the `resourceType` and `resourceId`, the `action`, the `author` and `authorId` (the person or client; none for the AI and Raíz itself), the `reason` when the writer gave one, such as `merge`, `contact_import` or `conversation_analysis`, and, for an update, each changed field with its value `from` and `to`. Filter by `resourceId`, `resourceType`, `contactId` (with the duplicates it absorbed), `authorId`, `createdAfter` and `createdBefore`. Values can include contacts' personal data; reading the history takes `raiz:changes:read`.

## Tasks

Long jobs run in the background as tasks: contact imports (`contact_import`), conversation re-analyses (`analysis_run`) and website crawls (`knowledge_crawl`). [`raiz.tasks.get`](/api/raiz/tasks/get/) reads one; after an action returns a task, check it again every few seconds. [`raiz.tasks.list`](/api/raiz/tasks/list/) lists them, newest first, by `kind` and `status`:

| `status` | Meaning |
| --- | --- |
| `queued`, `running` | Waiting, or working. `progress` counts the steps of a task split into parts. |
| `completed` | Done. `result` holds what it produced, such as an import's counts. |
| `failed` | `errorCode` says why, and `retryable` whether it can run again. |
| `cancelled` | Stopped on request. What it already did stays done. |

[`raiz.tasks.cancel`](/api/raiz/tasks/cancel/) cancels a queued task at once, and asks a running one to stop at its next checkpoint (`cancelRequestedAt`); asking again changes nothing. [`raiz.tasks.retry`](/api/raiz/tasks/retry/) queues a failed task again, from where it stopped. A task whose kind never retries, or that used every attempt, answers `409 TASK_NOT_RETRYABLE`.

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