# Assistants

> List the assistants available to the API key's user and use them in chat.

An assistant is a configured AI agent: a model with its own instructions, tools,
knowledge base and memory. Assistants are created and edited in the AYETO app; the API
lists them so that you can pick one and talk to it through [chat](chat.md).

## Scope

The assistant endpoints require the `ayeto.assistant` scope (shown as **AYETO
assistants** when you create a key), or a key with all scopes (`*`). See
[scopes](authentication.md#scopes).

## List assistants

| | |
|---|---|
| Endpoint | `POST /api/v3/assistant/find` |
| Scope | `ayeto.assistant` |
| Rate limit | [default](conventions.md#rate-limits) |

Returns the assistants the API key's user can use:

- assistants the user created, in personal use and in organizations;
- assistants owned by a group the user belongs to (for example the administrators of an
  organization);
- assistants shared with the user, directly by e-mail or through a group.

Organization assistants that are neither owned by nor shared with the user are not
returned, and neither are assistant templates from the gallery (a template becomes an
assistant once the user adds it in the app).

The result also contains assistants the app creates for its own studios: the assistant
behind each Booster panel and the builder assistant of each workflow. The app hides
them from its assistant lists. To leave them out, add the filters
`["booster_panel_id", "==", null]` and `["workflow_id", "==", null]` (see the
[example](#example)).

### Request

The body is a query object with the usual [filters, sorting and paging](conventions.md#filters)
fields. Send `{}` to get everything; the body itself is required.

| Field | Type | Required | Description |
|---|---|---|---|
| `filters` | array | No | Filter conditions, see [filters](conventions.md#filters) and the examples below. Several conditions are combined with AND. |
| `sort_key` | string | No | Field to sort by, for example `name`, `created.timestamp`, `updated.timestamp` or `accessed.timestamp` (last used). Default: `created.timestamp`, descending. |
| `sort_order` | integer | No | `0` ascending, `1` descending. Default `0` when `sort_key` is set. |
| `limit_from` | integer | No | Index of the first result (zero-based). Without it, all matching assistants are returned. |
| `limit_to` | integer | No | Index after the last result (exclusive), not a page size. |

Useful filters:

| Goal | Filter |
|---|---|
| Personal assistants only | `["organization_id", "==", null]` |
| Assistants of one organization | `["organization_id", "==", "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"]` |
| Without Booster panel and workflow builder assistants | `["booster_panel_id", "==", null]`, `["workflow_id", "==", null]` |
| Name contains a word (case-insensitive) | `["name", "regex", "support"]` |
| Assistants created by the user (not shared with them) | `["created.user_id", "==", "6c5b4a39-2817-4f6e-9d5c-4b3a29180f7e"]` |

### Response

`200 OK` with an array of [assistants](#assistant).

### Errors

| Status | `detail` | Cause |
|---|---|---|
| `401` | `API key is invalid` | The key lacks the `ayeto.assistant` scope (and is not an all-scopes key), or is not valid. |
| `403` | `permission denied` | The user's account is not allowed to read assistants. |
| `422` | validation error | The body is missing, or a filter or `sort_key` is invalid. |

Authentication, rate limit and server errors are described in
[conventions](conventions.md#errors).

### Example

The user's own assistants (personal, without studio assistants), most recently used
first:

```bash
curl -X POST "https://ayeto.ai/api/v3/assistant/find" \
  -H "uni-api-key: $AYETO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filters": [
      ["organization_id", "==", null],
      ["booster_panel_id", "==", null],
      ["workflow_id", "==", null]
    ],
    "sort_key": "accessed.timestamp",
    "sort_order": 1,
    "limit_from": 0,
    "limit_to": 50
  }'
```

```json
[
  {
    "id": "3f6c1a2e-8b4d-4e7a-9c1f-2d5e6a7b8c90",
    "name": "Customer support",
    "description": "Answers questions about orders, delivery and returns.",
    "avatar_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
    "organization_id": null,
    "created": {"timestamp": 1756819200000, "user_id": "6c5b4a39-2817-4f6e-9d5c-4b3a29180f7e"},
    "updated": {"timestamp": 1759222800000, "user_id": "6c5b4a39-2817-4f6e-9d5c-4b3a29180f7e"},
    "accessed": {"timestamp": 1759395606000, "user_id": "6c5b4a39-2817-4f6e-9d5c-4b3a29180f7e"}
  },
  {
    "id": "7d1e2f3a-4b5c-4d6e-8f7a-9b0c1d2e3f4a",
    "name": "Contract reviewer",
    "description": "",
    "avatar_id": null,
    "organization_id": null,
    "created": {"timestamp": 1754035200000, "user_id": "6c5b4a39-2817-4f6e-9d5c-4b3a29180f7e"},
    "updated": {"timestamp": 0, "user_id": null},
    "accessed": {"timestamp": 0, "user_id": null}
  }
]
```

## Get an assistant's avatar

| | |
|---|---|
| Endpoint | `POST /api/v3/assistant/avatar/get` |
| Scope | `ayeto.assistant` |
| Rate limit | [default](conventions.md#rate-limits) |

Returns the link to an assistant's avatar image, for example to show it next to the
assistant's answers in your application.

### Request

| Field | Type | Required | Description |
|---|---|---|---|
| `assistant_id` | UUID | yes | Id of an assistant the user owns or that is shared with them. |

### Response

`200 OK` with the full URL of the avatar image as a JSON string, or an empty string
(`""`) when the assistant has no avatar. The link works without an API key, so you can
use it directly as an image source; `avatar_id` in [List assistants](#list-assistants)
tells you in advance whether there is an avatar.

```json
"https://ayeto.ai/api/v1/public/file/read?id=9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d&secret=4f1c9e2b7a6d4c3e"
```

### Errors

| Status | `detail` | Cause |
|---|---|---|
| `401` | `API key is invalid` | The key lacks the `ayeto.assistant` scope (and is not an all-scopes key), or is not valid. |
| `403` | `permission denied` | The user's account is not allowed to read assistants. |
| `403` | `not shared with user` | The assistant is neither owned by nor shared with the user. |
| `404` | `Assistant not found` | No assistant with this id exists. |
| `422` | validation error | `assistant_id` is missing or not a UUID. |

### Example

```bash
curl -X POST "https://ayeto.ai/api/v3/assistant/avatar/get" \
  -H "uni-api-key: $AYETO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"assistant_id": "3f6c1a2e-8b4d-4e7a-9c1f-2d5e6a7b8c90"}'
```

## Assistant

The object returned by [List assistants](#list-assistants). The instructions, model,
tools and knowledge base of an assistant are not exposed by the API.

| Field | Type | Required | Description |
|---|---|---|---|
| `id` | UUID | Yes | Assistant id. Pass it as `assistant_id` to [chat](chat.md). |
| `name` | string | Yes | Display name. |
| `description` | string | Yes | Short description; may be an empty string. |
| `avatar_id` | UUID or null | No | Id of the avatar image file; `null` when the assistant has no avatar. Get its link with [Get an assistant's avatar](#get-an-assistants-avatar). |
| `organization_id` | UUID or null | No | Organization the assistant belongs to; `null` for a personal assistant. |
| `created`, `updated`, `accessed` | object | Yes | `{timestamp, user_id}` metadata, see [common fields](conventions.md#common-fields). `accessed` is when the assistant was last used in a chat; `0` if it has not been used since this was recorded. |

## Chatting with an assistant

To talk to an assistant, send its `id` as `assistant_id` to [chat](chat.md) instead of a
`model`. The assistant's own model, instructions, tools and knowledge are used, and the
new conversation is linked to it: it appears with that `assistant_id` in
[conversations](conversations.md#list-conversations).

- Sharing an assistant for reading only is enough to chat with it.
- An assistant that belongs to an organization runs in that organization (unless you
  send another `organization_id`), so the user must be a member or an administrator of
  that organization. An assistant shared with the user from an organization they do not
  belong to is listed, but chatting with it is refused with `403`.
- Chat requires the `ayeto.chat` scope on the key.
