# Assistants

> Lister les assistants disponibles pour l'utilisateur de la clé API et les utiliser dans le chat.

Un assistant est un agent d'IA configuré : un modèle avec ses propres instructions, outils,
base de connaissances et mémoire. Les assistants se créent et se modifient dans l'application AYETO ; l'API
les liste pour que vous puissiez en choisir un et lui parler via le [chat](chat.md).

## Portée

Les endpoints des assistants nécessitent la portée `ayeto.assistant` (affichée comme **Assistants
AYETO** lorsque vous créez une clé), ou une clé avec toutes les portées (`*`). Voir
[portées](authentication.md#portees).

## Lister les assistants

| | |
|---|---|
| Endpoint | `POST /api/v3/assistant/find` |
| Portée | `ayeto.assistant` |
| Limite de débit | [par défaut](conventions.md#limites-de-debit) |

Renvoie les assistants que l'utilisateur de la clé API peut utiliser :

- les assistants créés par l'utilisateur, à titre personnel et dans les organisations ;
- les assistants appartenant à un groupe dont l'utilisateur fait partie (par exemple les administrateurs d'une
  organisation) ;
- les assistants partagés avec l'utilisateur, directement par e-mail ou via un groupe.

Les assistants d'organisation qui n'appartiennent pas à l'utilisateur et ne sont pas partagés avec lui ne sont pas
renvoyés, pas plus que les modèles d'assistants de la galerie (un modèle devient un
assistant une fois que l'utilisateur l'ajoute dans l'application).

Le résultat contient aussi les assistants que l'application crée pour ses propres studios : l'assistant
derrière chaque panneau Booster et l'assistant builder de chaque workflow. L'application les masque
dans ses listes d'assistants. Pour les exclure, ajoutez les filtres
`["booster_panel_id", "==", null]` et `["workflow_id", "==", null]` (voir
l'[exemple](#exemple)).

### Requête

Le corps est un objet de requête avec les champs habituels de [filtres, tri et pagination](conventions.md#filtres).
Envoyez `{}` pour tout obtenir ; le corps lui-même est obligatoire.

| Champ | Type | Obligatoire | Description |
|---|---|---|---|
| `filters` | tableau | Non | Conditions de filtre, voir [filtres](conventions.md#filtres) et les exemples ci-dessous. Plusieurs conditions sont combinées par AND. |
| `sort_key` | chaîne | Non | Champ de tri, par exemple `name`, `created.timestamp`, `updated.timestamp` ou `accessed.timestamp` (dernière utilisation). Par défaut : `created.timestamp`, décroissant. |
| `sort_order` | entier | Non | `0` croissant, `1` décroissant. Par défaut `0` lorsque `sort_key` est défini. |
| `limit_from` | entier | Non | Index du premier résultat (à partir de zéro). Sans lui, tous les assistants correspondants sont renvoyés. |
| `limit_to` | entier | Non | Index suivant le dernier résultat (exclusif), et non une taille de page. |

Filtres utiles :

| Objectif | Filtre |
|---|---|
| Assistants personnels uniquement | `["organization_id", "==", null]` |
| Assistants d'une organisation | `["organization_id", "==", "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"]` |
| Sans les assistants des panneaux Booster ni les assistants builder des workflows | `["booster_panel_id", "==", null]`, `["workflow_id", "==", null]` |
| Le nom contient un mot (insensible à la casse) | `["name", "regex", "support"]` |
| Assistants créés par l'utilisateur (et non partagés avec lui) | `["created.user_id", "==", "6c5b4a39-2817-4f6e-9d5c-4b3a29180f7e"]` |

### Réponse

`200 OK` avec un tableau d'[assistants](#assistant).

### Erreurs

| Statut | `detail` | Cause |
|---|---|---|
| `401` | `API key is invalid` | La clé n'a pas la portée `ayeto.assistant` (et n'est pas une clé « toutes les portées »), ou n'est pas valide. |
| `403` | `permission denied` | Le compte de l'utilisateur n'est pas autorisé à lire les assistants. |
| `422` | erreur de validation | Le corps est absent, ou un filtre ou `sort_key` n'est pas valide. |

Les erreurs d'authentification, de limite de débit et du serveur sont décrites dans les
[conventions](conventions.md#erreurs).

### Exemple

Les assistants de l'utilisateur (personnels, sans les assistants des studios), les plus récemment utilisés
en premier :

```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}
  }
]
```

## Obtenir l'avatar d'un assistant

| | |
|---|---|
| Endpoint | `POST /api/v3/assistant/avatar/get` |
| Portée | `ayeto.assistant` |
| Limite de débit | [par défaut](conventions.md#limites-de-debit) |

Renvoie le lien vers l'image d'avatar d'un assistant, par exemple pour l'afficher à côté des
réponses de l'assistant dans votre application.

### Requête

| Champ | Type | Obligatoire | Description |
|---|---|---|---|
| `assistant_id` | UUID | oui | Identifiant d'un assistant dont l'utilisateur est propriétaire ou qui est partagé avec lui. |

### Réponse

`200 OK` avec l'URL complète de l'image d'avatar sous forme de chaîne JSON, ou une chaîne vide
(`""`) lorsque l'assistant n'a pas d'avatar. Le lien fonctionne sans clé API, vous pouvez donc
l'utiliser directement comme source d'image ; `avatar_id` dans [Lister les assistants](#lister-les-assistants)
vous indique à l'avance s'il existe un avatar.

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

### Erreurs

| Statut | `detail` | Cause |
|---|---|---|
| `401` | `API key is invalid` | La clé n'a pas la portée `ayeto.assistant` (et n'est pas une clé « toutes les portées »), ou n'est pas valide. |
| `403` | `permission denied` | Le compte de l'utilisateur n'est pas autorisé à lire les assistants. |
| `403` | `not shared with user` | L'assistant n'appartient pas à l'utilisateur et n'est pas partagé avec lui. |
| `404` | `Assistant not found` | Aucun assistant avec cet identifiant n'existe. |
| `422` | erreur de validation | `assistant_id` est absent ou n'est pas un UUID. |

### Exemple

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

L'objet renvoyé par [Lister les assistants](#lister-les-assistants). Les instructions, le modèle,
les outils et la base de connaissances d'un assistant ne sont pas exposés par l'API.

| Champ | Type | Obligatoire | Description |
|---|---|---|---|
| `id` | UUID | Oui | Identifiant de l'assistant. Passez-le comme `assistant_id` au [chat](chat.md). |
| `name` | chaîne | Oui | Nom affiché. |
| `description` | chaîne | Oui | Description courte ; peut être une chaîne vide. |
| `avatar_id` | UUID ou null | Non | Identifiant du fichier de l'image d'avatar ; `null` lorsque l'assistant n'a pas d'avatar. Obtenez son lien avec [Obtenir l'avatar d'un assistant](#obtenir-lavatar-dun-assistant). |
| `organization_id` | UUID ou null | Non | Organisation à laquelle appartient l'assistant ; `null` pour un assistant personnel. |
| `created`, `updated`, `accessed` | objet | Oui | Métadonnées `{timestamp, user_id}`, voir [champs communs](conventions.md#champs-communs). `accessed` indique la dernière utilisation de l'assistant dans un chat ; `0` s'il n'a pas été utilisé depuis que cette information est enregistrée. |

## Discuter avec un assistant

Pour parler à un assistant, envoyez son `id` comme `assistant_id` au [chat](chat.md) à la place d'un
`model`. Le modèle, les instructions, les outils et les connaissances propres à l'assistant sont utilisés, et la
nouvelle conversation lui est liée : elle apparaît avec cet `assistant_id` dans les
[conversations](conversations.md#lister-les-conversations).

- Un partage de l'assistant en lecture seule suffit pour discuter avec lui.
- Un assistant qui appartient à une organisation s'exécute dans cette organisation (sauf si vous
  envoyez un autre `organization_id`) ; l'utilisateur doit donc être membre ou administrateur de
  cette organisation. Un assistant partagé avec l'utilisateur depuis une organisation dont il ne fait pas
  partie est listé, mais la discussion avec lui est refusée avec `403`.
- Le chat nécessite la portée `ayeto.chat` sur la clé.
