> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# Procédures structurées

## Vue d’ensemble

Une procédure structurée est une [procédure](/docs/fr/eleven-agents/customization/procedures) qui exécute une séquence fixe d’étapes. Une [procédure libre](/docs/fr/eleven-agents/customization/procedures/free-form-procedures) fournit des indications en langage naturel que l’agent interprète et adapte à la situation. Une procédure structurée est une liste ordonnée d’étapes typées que l’agent exécute dans l’ordre chaque fois que la procédure s’applique.

Utilisez une procédure structurée lorsque des étapes précises doivent se dérouler de la même façon à chaque appel : vérifier l’identité d’un appelant, faire remonter un ticket ou accepter un paiement. Rédigez-la sous la forme d’une courte liste d’étapes en langage clair.

Comme toute procédure, une procédure structurée possède un déclencheur qui décrit quand elle s’applique. Lorsqu’une conversation correspond au déclencheur, l’agent exécute les étapes de la procédure dans l’ordre, puis revient au reste de la conversation.

![Éditeur de procédures structurées](/docs/_fern-img/bc996f67b2afad8f1de5abe8febcf8af3766b4f098627b0ae60e0456b3c2703b.webp)

## Quand utiliser une procédure structurée

Utilisez une procédure structurée lorsque des étapes précises doivent s’exécuter de la même manière à chaque fois, tout en vous permettant de rédiger rapidement des étapes simples. Les procédures structurées sont plus faciles à écrire qu’un workflow, mais moins expressives. Pour découvrir comment elles se comparent aux procédures libres, aux workflows et au prompt système, consultez [Quand utiliser les procédures](/docs/fr/eleven-agents/customization/procedures#when-to-use-procedures).

## Anatomie d’une procédure structurée

Une procédure structurée comporte trois éléments : un nom, un déclencheur et une liste ordonnée d’étapes.

### Nom

Un libellé court qui identifie la procédure dans le Dashboard. Le nom n’est jamais envoyé au LLM, il n’affecte donc pas le comportement de l’agent.

### Déclencheur

Une description en langage clair du moment où l’agent doit exécuter cette procédure, par exemple *Lorsque l’utilisateur demande le remboursement d’une commande*. L’agent compare l’intention de l’utilisateur au déclencheur de chaque procédure et exécute celle qui correspond. Les déclencheurs doivent donc être précis et distincts. L’agent ne voit que le texte du déclencheur, jamais le nom ni l’ID de la procédure. Un déclencheur fonctionne comme pour toute procédure. Consultez [Rédiger des déclencheurs](/docs/fr/eleven-agents/customization/procedures/free-form-procedures#writing-triggers).

Laissez le déclencheur vide pour faire de la procédure une sous-procédure qui ne s’exécute que lorsqu’une autre procédure l’appelle.

### Étapes

Le corps de la procédure est une liste ordonnée d’étapes typées. Plusieurs types d’étapes sont disponibles et vous les combinez pour décrire la tâche.

| Étape              | Rôle                                                                                                                                                                                                                                                                           |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Demander**       | Demande des informations à l’utilisateur et attend. Elle continue de demander jusqu’à ce que l’utilisateur réponde. C’est la seule étape qui marque une pause pour l’utilisateur.                                                                                              |
| **Informer**       | Demande à l’agent de communiquer quelque chose avec ses propres mots, puis passe à l’étape suivante.                                                                                                                                                                           |
| **Dire**           | Demande à l’agent de prononcer un message exact, mot pour mot, puis passe à l’étape suivante. Une étape Dire peut inclure une traduction configurée distinctement pour chaque langue prise en charge par l’agent.                                                              |
| **Outil**          | Appelle un outil précis. Vous pouvez indiquer au LLM en langage clair comment appeler l’outil, ou fixer explicitement les valeurs des paramètres lorsqu’un déterminisme maximal est requis. Vous pouvez aussi définir les étapes à exécuter en cas d’échec de l’appel d’outil. |
| **Si**             | Évalue une ou plusieurs conditions dans l’ordre et exécute les étapes de la première correspondance. Un Sinon facultatif s’exécute lorsqu’aucune condition ne correspond.                                                                                                      |
| **Sous-procédure** | Exécute une autre procédure structurée. Une fois ses étapes terminées, le contrôle revient à l’étape suivante de cette procédure appelante.                                                                                                                                    |
| **Outil système**  | Exécute une action système intégrée. Actuellement, seule la fin de l’appel est prise en charge.                                                                                                                                                                                |
| **Réessayer**      | Réexécute le gestionnaire d’échec d’une étape Outil, y compris l’appel d’outil, jusqu’à trois fois. Disponible uniquement dans le gestionnaire d’échec d’une étape Outil.                                                                                                      |

![Menu des types d’étapes d’une procédure structurée](/docs/_fern-img/14976a6b9979d21fd7c77541a49e7475f8aa0764af4940746d3390804e7c4598.webp)

Toutes les étapes ne peuvent pas apparaître partout. Dans une branche Si, vous pouvez utiliser toute étape sauf un autre Si ou Réessayer. Dans le gestionnaire d’échec d’une étape Outil, vous pouvez utiliser toute étape sauf un Si ou un autre Outil.

## Référence des étapes de l’API

Le `content` d’une procédure structurée est un document encodé en JSON contenant un tableau `steps`. Chaque étape est un objet identifié par son `type`. Le déclencheur est un champ distinct de premier niveau dans la procédure, et ne fait pas partie de `content`. Les payloads de l’API et du SDK utilisent `type: "deterministic"` pour la procédure elle-même.

### Demander

Une étape Demander invite l’agent à solliciter des informations et à attendre que l’utilisateur fournisse une réponse appropriée.

* Type API : `ask`
* `instruction` : chaîne obligatoire et non vide.

```json focus={1-4}
{
  "type": "ask",
  "instruction": "Ask the user for their order ID."
}
```

### Informer

Une étape Informer demande à l’agent de générer un message unique avec ses propres mots. Elle n’attend pas la réponse de l’utilisateur avant de continuer.

* Type API : `tell`
* `instruction` : chaîne obligatoire et non vide.

```json focus={1-4}
{
  "type": "tell",
  "instruction": "Explain that the refund normally takes five to ten business days."
}
```

### Dire

Une étape Dire prononce le texte fourni exactement tel qu’il est écrit, puis continue. Fournissez `message_translations` pour donner à l’agent un message exact dans chaque langue supplémentaire prise en charge, identifié par code de langue.

* Type API : `say`
* `message` : chaîne obligatoire et non vide.
* `message_translations` : objet facultatif associant un code de langue à `{ "value": "..." }`.

```json focus={1-7}
{
  "type": "say",
  "message": "Your refund has been submitted.",
  "message_translations": {
    "es": { "value": "Su reembolso ha sido enviado." }
  }
}
```

### Si, sinon si et sinon

Une étape Si contient une ou plusieurs branches conditionnelles ordonnées. La première branche correspondante s’exécute. Le tableau `fallback` facultatif est la branche Sinon.

* Type API : `branch`
* `branches` : liste obligatoire et non vide de branches conditionnelles.
* `fallback` : liste facultative d’étapes Sinon.
* Chaque branche requiert une `condition` et une liste `steps` non vide.

```json focus={1-23}
{
  "type": "branch",
  "branches": [
    {
      "condition": {
        "type": "llm",
        "condition": "The user is on an annual plan."
      },
      "steps": [
        {
          "type": "say",
          "message": "Your annual plan is eligible for a prorated refund."
        }
      ]
    }
  ],
  "fallback": [
    {
      "type": "tell",
      "instruction": "Explain that the account's plan could not be determined."
    }
  ]
}
```

Le comportement est semblable à if/else-if/else :

1. Les conditions sont évaluées dans l’ordre.
2. La première branche correspondante s’exécute.
3. Si aucune condition ne correspond, `fallback` s’exécute.
4. Lorsqu’une branche se termine, la procédure rejoint la séquence principale.

L’exemple ci-dessus utilise une condition de texte, que le modèle évalue en langage naturel. Les conditions peuvent également être des expressions portant sur des variables dynamiques :

```json focus={1-14}
{
  "type": "expression",
  "expression": {
    "type": "eq_operator",
    "left": {
      "type": "dynamic_variable",
      "name": "plan_tier"
    },
    "right": {
      "type": "string_literal",
      "value": "annual"
    }
  }
}
```

Une condition d’expression teste des variables dynamiques, qui sont renseignées par les résultats d’outils ou définies au démarrage de la conversation. Elle ne peut pas lire la réponse la plus récente de l’utilisateur. Pour créer une branche selon ce que l’utilisateur a dit, utilisez une condition de texte.

Toutes les branches d’une même étape Si doivent utiliser le même type de condition : `llm` ou `expression`.

### Outil

Une étape Outil appelle un outil précis.

* Type API : `tool_call`
* `tool_id` : ID d’outil obligatoire et non vide. L’outil doit être associé à l’agent.
* `tool_name` : nom d’outil obligatoire, correspondant à l’outil.
* `instruction` : instruction facultative décrivant comment appeler l’outil.
* `schema_overrides` : valeurs fixes facultatives pour les paramètres de l’outil.
* `on_failure` : gestionnaire d’échec facultatif.

```json focus={1-6}
{
  "type": "tool_call",
  "tool_id": "tool_abc123",
  "tool_name": "lookup_order",
  "instruction": "Look up the order using the order ID provided by the user."
}
```

#### Valeurs fixes des paramètres

Utilisez `schema_overrides` lorsqu’un paramètre doit toujours prendre une valeur précise. Le modèle ne voit pas un paramètre remplacé et ne le choisit pas. Les clés sont des chemins de paramètres dans le schéma de l’outil ; chaque valeur désigne une source :

| `source`           | Champs                | Comportement                                                                   |
| ------------------ | --------------------- | ------------------------------------------------------------------------------ |
| `constant`         | `constant_value`      | Envoie toujours la valeur donnée.                                              |
| `dynamic_variable` | `dynamic_variable`    | Envoie la valeur actuelle de la variable dynamique nommée.                     |
| `llm`              | `prompt` (facultatif) | Laisse le modèle choisir la valeur, avec un remplacement de prompt facultatif. |
| `omit`             |                       | Omet le paramètre de l’appel.                                                  |

```json focus={1-9}
{
  "type": "tool_call",
  "tool_id": "tool_abc123",
  "tool_name": "update_ticket",
  "schema_overrides": {
    "request_body.status": { "source": "constant", "constant_value": "pending" },
    "request_body.ticket_id": { "source": "dynamic_variable", "dynamic_variable": "ticket_id" }
  }
}
```

#### Gestion des échecs

Sans `on_failure`, un appel d’outil en échec met fin à la conversation. Ajoutez plutôt `on_failure` pour exécuter des étapes de récupération.

* `fallback` : liste obligatoire et non vide d’étapes qui s’exécutent lorsque l’outil échoue.
* `branches` : réservé à la gestion conditionnelle des échecs. Laissez-le vide.

```json focus={1-14}
{
  "type": "tool_call",
  "tool_id": "tool_abc123",
  "tool_name": "lookup_order",
  "on_failure": {
    "branches": [],
    "fallback": [
      {
        "type": "tell",
        "instruction": "Explain that the order could not be retrieved and offer to connect the user with support."
      }
    ]
  }
}
```

Un gestionnaire d’échec peut contenir des étapes Demander, Informer, Dire, Sous-procédure, Outil système et Réessayer. Il ne peut pas contenir d’étapes Outil ou Si. Une fois le gestionnaire exécuté, la procédure continue avec l’étape suivant l’étape Outil.

### Réessayer

Une étape Réessayer réexécute le gestionnaire d’échec qui la contient, y compris l’appel d’outil. Chaque tentative appelle à nouveau l’outil et, s’il échoue à nouveau, exécute de nouveau chaque étape du gestionnaire. Lorsque toutes les tentatives sont épuisées, la conversation se termine.

* Type API : `retry`
* `max_retries` : entier facultatif de 1 à 3. La valeur par défaut est 1.
* La valeur compte les tentatives après l’appel d’outil initial.
* Réessayer n’est valide qu’à l’intérieur de `on_failure`.
* Réessayer doit être la dernière étape de son gestionnaire d’échec, car les étapes suivantes seraient inaccessibles.

```json focus={1-4}
{
  "type": "retry",
  "max_retries": 2
}
```

### Sous-procédure

Une étape Sous-procédure exécute une autre procédure structurée. Lorsque les étapes de cette procédure sont terminées, l’exécution revient à l’étape suivant l’étape Sous-procédure.

* Type API : `sub_procedure`
* `procedure_id` : ID de procédure obligatoire et non vide.
* La cible doit exister sur le même agent.
* La cible doit être une procédure structurée.
* Une procédure ne peut pas s’appeler elle-même.

```json focus={1-4}
{
  "type": "sub_procedure",
  "procedure_id": "agtprc_6qbpwdq8n01bxhk44bgjy6f10ck3"
}
```

### Outil système

Une étape Outil système exécute une action système intégrée.

* Type API : `system_tool`
* `system_tool_name` : nom d’outil système obligatoire.
* Actuellement, seul `end_call` est pris en charge. D’autres outils système pourront être ajoutés ultérieurement.
* `end_call` étant terminal, il doit être la dernière étape de la séquence, de la branche ou du gestionnaire d’échec qui le contient.

```json focus={1-4}
{
  "type": "system_tool",
  "system_tool_name": "end_call"
}
```

## Règles de validation

La publication de l’agent ou l’enregistrement de son brouillon rejette toute procédure structurée qui enfreint l’une de ces règles. L’erreur désigne l’étape concernée par son chemin.

* Deux étapes Si ne peuvent pas être placées à la suite.
* Les étapes Si ne peuvent pas être imbriquées.
* Une étape Si avec des conditions d’expression ne peut pas suivre directement une étape Demander.
* Toutes les conditions d’une même étape Si doivent être du même type : `llm` ou `expression`.
* Réessayer ne peut apparaître qu’à l’intérieur de `on_failure` et doit y être la dernière étape.
* `end_call` doit être la dernière étape de la liste dans laquelle il apparaît.
* Le `fallback` d’un gestionnaire d’échec doit contenir au moins une étape.
* Une sous-procédure doit pointer vers une procédure structurée existante du même agent, sans pointer vers elle-même.
* `tool_id` doit correspondre à un outil de l’agent, `tool_name` doit correspondre et `schema_overrides` doit correspondre au schéma de l’outil.
* La liste `steps`, chaque `instruction` et chaque `message` doivent être non vides.

Pour savoir comment restructurer une procédure qui enfreint l’une de ces règles, consultez les [bonnes pratiques](#best-practices).

## Exemple complet d’API

Cet exemple gère l’annulation d’une commande selon le statut de l’expédition. Il fixe un paramètre d’outil, gère un appel d’outil en échec, appelle une autre procédure structurée, puis met fin à l’appel.

```json maxLines=30
{
  "steps": [
    {
      "type": "ask",
      "instruction": "Ask the user for their order ID."
    },
    {
      "type": "branch",
      "branches": [
        {
          "condition": {
            "type": "llm",
            "condition": "The user says the order has already shipped."
          },
          "steps": [
            {
              "type": "tell",
              "instruction": "Explain that shipped orders must be returned before they can be refunded."
            }
          ]
        },
        {
          "condition": {
            "type": "llm",
            "condition": "The user says the order has not shipped."
          },
          "steps": [
            {
              "type": "tool_call",
              "tool_id": "tool_abc123",
              "tool_name": "cancel_order",
              "instruction": "Cancel the order using the order ID provided by the user.",
              "schema_overrides": {
                "request_body.notify_customer": { "source": "constant", "constant_value": true }
              },
              "on_failure": {
                "branches": [],
                "fallback": [
                  {
                    "type": "tell",
                    "instruction": "Apologize that the cancellation did not go through and say you will try once more."
                  },
                  {
                    "type": "retry",
                    "max_retries": 1
                  }
                ]
              }
            }
          ]
        }
      ],
      "fallback": [
        {
          "type": "ask",
          "instruction": "Ask whether the order has already shipped."
        }
      ]
    },
    {
      "type": "sub_procedure",
      "procedure_id": "agtprc_6qbpwdq8n01bxhk44bgjy6f10ck3"
    },
    {
      "type": "say",
      "message": "Thank you for contacting us. Goodbye.",
      "message_translations": {
        "es": { "value": "Gracias por contactarnos. Adiós." }
      }
    },
    {
      "type": "system_tool",
      "system_tool_name": "end_call"
    }
  ]
}
```

## Exécution d’une procédure structurée

La transformation des étapes d’une procédure structurée dans le format exécuté par l’agent s’appelle la compilation. La plateforme compile chaque procédure structurée lorsque le brouillon de l’agent est enregistré ou lorsque l’agent est publié ; les auteurs n’ont jamais rien à compiler eux-mêmes.

Lorsque la demande de l’utilisateur correspond au déclencheur d’une procédure, la plateforme entre dans la procédure et exécute ses étapes dans l’ordre. Dans une procédure structurée, l’agent se concentre sur chaque étape de manière isolée. Lorsqu’il atteint la fin, la plateforme rend le contrôle au reste de la conversation.

Les arêtes d’un workflow ne peuvent pas se connecter à une procédure structurée ni en partir. Utilisez une étape Sous-procédure pour enchaîner des procédures structurées. La plateforme gère l’entrée depuis un déclencheur correspondant et la finalisation, y compris le retour du contrôle au nœud de workflow où la procédure a démarré.

Les règles suivantes décrivent le comportement des étapes lors de l’exécution.

#### Seule l’étape Demander attend l’utilisateur

Chaque étape autre que Demander s’exécute immédiatement, et le contrôle passe à l’étape suivante au sein du même
tour. Une étape Informer ou Dire délivre son message et continue. Aucune étape ne suspend la
conversation, hormis Demander, et aucune étape ne termine le tour actuel. Si vous avez besoin de la saisie de l’utilisateur,
utilisez une étape Demander. Si la conversation doit se terminer, utilisez l’outil système `end_call`.

#### Atteindre la fin d’une procédure ne termine pas le tour

Lorsque la dernière étape est terminée, la procédure prend fin et l’agent revient au reste de la
conversation alors que le tour reste ouvert ; il peut donc encore parler. Lorsqu’une sous-procédure se termine,
le contrôle revient à l’étape suivante de la procédure qui l’a appelée.

#### Les étapes Outil distinguent uniquement la réussite de l’échec

Une étape Outil ne peut pas créer de branche selon un code de statut ou le corps de la réponse. Si l’outil réussit, la
procédure continue. S’il échoue et que l’étape n’a pas de gestionnaire d’échec, la conversation se termine. Si
elle en a un, les étapes du gestionnaire s’exécutent et la procédure passe à l’étape suivante. Une étape Réessayer dans
le gestionnaire réexécute l’outil et, s’il échoue à nouveau, chaque étape du gestionnaire, jusqu’à ce que l’outil
réussisse ou que les tentatives soient épuisées. Si elles sont épuisées, la conversation se termine.

#### Les étapes Si passent à la suite lorsqu’aucune condition ne correspond

Les conditions sont évaluées dans l’ordre et la première correspondance s’exécute. La branche Sinon s’exécute lorsqu’aucune
condition ne correspond. S’il n’y a pas de Sinon et qu’aucune condition ne correspond, la procédure continue avec l’étape suivant
le Si. Un cas non géré n’est pas une erreur.

#### Les branches Si ne conservent pas l’état

Aucune décision prise dans une branche Si n’est mémorisée par les étapes suivantes. Si une information obtenue dans une branche est
nécessaire plus tard, conservez-la explicitement avec un appel d’outil ou une variable dynamique.

#### Les étapes Demander, Informer et Dire n’ont pas accès aux outils

Seules les étapes Outil peuvent appeler des outils. Il est inutile d’indiquer à une étape Demander, Informer ou Dire de ne pas appeler
d’outils : elle ne le peut pas.

## Gérer une procédure structurée

#### Créer depuis le Dashboard

Ouvrez votre agent dans le [Dashboard](https://elevenlabs.io/app/agents), puis sélectionnez **Procédures**.
Utilisez **+** pour créer une procédure structurée. Ajoutez un déclencheur, sélectionnez un type pour chaque étape et
publiez les modifications de l’agent.

Le Dashboard valide les procédures structurées pendant leur modification. Si une procédure enfreint une
[règle de validation](#validation-rules), le bouton **Publier** affiche un état d’erreur, l’onglet
**Procédures** affiche un badge d’erreur et l’aperçu ne peut pas démarrer tant que la procédure n’est pas
corrigée. Sélectionnez l’indicateur d’erreur pour voir quelle procédure et quelle étape sont concernées.

![Éditeur de procédures structurées avec le bouton Publier en état d’erreur et un badge
indiquant 1 erreur](/docs/_fern-img/e406c33fac3966fab26d5d07e10d364a475fc4a56fd75aad2e23edbb0d1940d5.webp)

![Boîte de dialogue des détails de validation répertoriant la procédure en échec et l’étape qui nécessite un
message](/docs/_fern-img/a1cc889b2d0e68ce23725609b531938d0f7c417b1c6f4375103531eaae4ada63.webp)

#### Gérer via la CLI

La [CLI ElevenLabs](/docs/fr/eleven-agents/operate/cli) crée et publie des procédures
structurées avec les mêmes commandes que les procédures libres. Définissez `type` sur `deterministic` et transmettez les
étapes sous forme de chaîne encodée en JSON dans `content`.

```bash
CONTENT=$(jq -n '{
  trigger: "When the user asks to refund an order",
  steps: [{ type: "ask", instruction: "Ask for the order ID." }]
}')

elevenlabs agents procedures create \
  --agent-id agent_7101k5zvyjhmfg983brhmhkd98n6 \
  --branch-id agtbranch_0901k4aafjxxfxt93gd841r7tv5t \
  --json "$(jq -n --arg content "$CONTENT" '{
    name: "Refund request",
    type: "deterministic",
    trigger: "When the user asks to refund an order",
    content: $content
  }')"

elevenlabs agents update \
  --agent-id agent_7101k5zvyjhmfg983brhmhkd98n6 \
  --branch-id agtbranch_0901k4aafjxxfxt93gd841r7tv5t \
  --json '{"version_description": "Publish refund procedure"}'
```

La publication valide chaque procédure structurée de la branche. Si l’une d’elles est invalide, la commande
se termine avec un code différent de zéro et affiche les erreurs associées à l’ID de procédure. Corrigez le brouillon de la procédure et publiez
à nouveau.

#### Gérer via l’API

Les payloads de l’API et du SDK utilisent `type: "deterministic"` pour les procédures structurées. Leur `content` est
un document encodé en JSON.

### Prérequis

* Une clé API ElevenLabs dans la variable d’environnement `ELEVENLABS_API_KEY`.
* Les `agent_id` et `branch_id` cibles. Consultez [Gestion des versions des agents](/docs/fr/eleven-agents/operate/versioning) pour les opérations sur les branches.
* La version `2.60.0` ou ultérieure du package Python `elevenlabs` ou du package JavaScript `@elevenlabs/elevenlabs-js`.

Les modifications effectuées via l’API restent privées pour votre utilisateur sur la branche sélectionnée jusqu’à la publication d’une nouvelle version de l’agent.

### Créer ou mettre à jour un brouillon

Créez une procédure structurée avec `POST /procedures` et définissez `type` sur `deterministic`.
Mettez à jour une procédure existante avec `PATCH /procedures/{procedure_id}/draft`, comme indiqué ci-dessous.

Définissez `trigger` comme champ de premier niveau. Encodez en JSON le document d’étapes dans `content` plutôt que
d’envoyer un objet imbriqué.

```python focus={6-18}
import json
from elevenlabs import ElevenLabs

elevenlabs = ElevenLabs()

elevenlabs.conversational_ai.agents.procedures.drafts.update(
    agent_id="agent_7101k5zvyjhmfg983brhmhkd98n6",
    branch_id="agtbranch_0901k4aafjxxfxt93gd841r7tv5t",
    procedure_id="agtprc_6qbpwdq8n01bxhk44bgjy6f10ck3",
    name="Refund request",
    type="deterministic",
    trigger="When the user asks to refund an order",
    content=json.dumps(
        {
            "steps": [{"type": "ask", "instruction": "Ask for the order ID."}],
        }
    ),
)
```

```typescript focus={5-17}
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient();

await elevenlabs.conversationalAi.agents.procedures.drafts.update(
  "agent_7101k5zvyjhmfg983brhmhkd98n6",
  "agtbranch_0901k4aafjxxfxt93gd841r7tv5t",
  "agtprc_6qbpwdq8n01bxhk44bgjy6f10ck3",
  {
    name: "Refund request",
    type: "deterministic",
    trigger: "When the user asks to refund an order",
    content: JSON.stringify({
      steps: [{ type: "ask", instruction: "Ask for the order ID." }],
    }),
  }
);
```

```bash focus={1-9}
curl -X PATCH "https://api.elevenlabs.io/v1/convai/agents/agent_7101k5zvyjhmfg983brhmhkd98n6/branches/agtbranch_0901k4aafjxxfxt93gd841r7tv5t/procedures/agtprc_6qbpwdq8n01bxhk44bgjy6f10ck3/draft" \
  -H "xi-api-key: $ELEVENLABS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Refund request",
    "type": "deterministic",
    "trigger": "When the user asks to refund an order",
    "content": "{\"steps\":[{\"type\":\"ask\",\"instruction\":\"Ask for the order ID.\"}]}"
  }'
```

Enregistrer un brouillon de procédure ne valide pas ses étapes. La validation s’exécute lors de la publication ou
lorsque vous enregistrez le brouillon de l’agent avec `POST /v1/convai/agents/{agent_id}/drafts`.

### Publier les modifications

Publiez avec [Mettre à jour l’agent](/docs/fr/api-reference/agents/update). La publication valide chaque
procédure structurée de la branche et, si elles passent toutes la validation, publie les procédures dans la
nouvelle version. La requête ne nécessite aucun champ `workflow`.

```python focus={5-8}
from elevenlabs import ElevenLabs

elevenlabs = ElevenLabs()

elevenlabs.conversational_ai.agents.update(
    agent_id="agent_7101k5zvyjhmfg983brhmhkd98n6",
    branch_id="agtbranch_0901k4aafjxxfxt93gd841r7tv5t",
)
```

```typescript focus={5-7}
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient();

await elevenlabs.conversationalAi.agents.update("agent_7101k5zvyjhmfg983brhmhkd98n6", {
  branchId: "agtbranch_0901k4aafjxxfxt93gd841r7tv5t",
});
```

```bash focus={1-5}
curl -X PATCH \
  "https://api.elevenlabs.io/v1/convai/agents/agent_7101k5zvyjhmfg983brhmhkd98n6?branch_id=agtbranch_0901k4aafjxxfxt93gd841r7tv5t" \
  -H "xi-api-key: $ELEVENLABS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

Si une procédure structurée est invalide, la publication renvoie `400` et aucune donnée n’est écrite :

```json
{
  "detail": {
    "status": "procedure_validation_failed",
    "message": "Structured procedures failed validation.",
    "data": {
      "errors": {
        "agtprc_6qbpwdq8n01bxhk44bgjy6f10ck3": [
          {
            "path": "steps[0].ask.instruction",
            "message": "Step 1: Ask step requires an instruction"
          }
        ]
      }
    }
  }
}
```

`errors` est associé à l’ID de procédure. Chaque entrée indique le champ et l’étape en échec. Corrigez le
brouillon de procédure et publiez à nouveau.

Consultez [Gérer les procédures](/docs/fr/eleven-agents/customization/procedures#manage-procedures) pour connaître le
comportement de suppression et d’abandon des brouillons, ou la
[référence de l’API Procedures](/docs/fr/api-reference/agents/procedures/) pour les schémas complets des points de terminaison.

## Bonnes pratiques

Chaque type d’étape applique déjà son propre comportement, vous avez donc rarement besoin de le préciser. Indiquez l’objectif de chaque étape et laissez le type d’étape s’occuper du reste. Les conseils ci-dessous couvrent les cas qu’il est important de bien traiter.

Pour tester une procédure structurée, suivez [Itérer sur une procédure](/docs/fr/eleven-agents/customization/procedures/free-form-procedures#iterating-on-a-procedure).

### Choisir les types d’étapes

#### Posez une seule question par étape Ask

Une étape Ask attend une réponse. Si vous regroupez plusieurs questions dans une même instruction,
l’agent a tendance à en ignorer certaines ou à les fusionner. Utilisez une étape Ask par information à recueillir.

#### Utilisez Tell pour les affirmations et Ask pour les questions

Une étape Tell délivre son message et passe à la suite sans attendre. Une étape Tell formulée comme une question
n’obtient jamais de réponse. Si une étape nécessite une réponse de l’utilisateur, utilisez Ask.

#### Donnez à une étape Ask une condition de sortie claire lorsque la question ne suffit pas

Une étape Ask avance dès qu’elle reçoit une réponse appropriée. Si ce qui constitue une réponse n’est pas
évident à partir de la question, précisez-le dans l’instruction, par exemple \_Demandez l’ID de commande ; un
ID valide comporte huit chiffres \_.

#### Choisissez Tell pour la formulation, Say pour les mots exacts

Utilisez une étape Tell lorsque l’agent doit composer lui-même le message, et une étape Say lorsque la
formulation doit être reproduite à l’identique ou traduite. Les deux délivrent exactement un message, il est donc inutile
d’indiquer à une étape d’envoyer un seul message.

#### Ne demandez pas aux étapes sans outil d’éviter les outils

Les étapes Ask, Tell et Say ne peuvent pas appeler d’outils. Y écrire *n’appelez aucun outil* ajoute du bruit
à l’instruction sans modifier le comportement.

### Structurer la procédure

#### N’insérez pas de remplissage entre deux étapes If

Deux étapes If ne peuvent pas être placées l’une à la suite de l’autre. Insérer une étape Tell ou Say sans rapport entre elles pour
respecter cette règle amène l’agent à dire quelque chose qu’il ne devrait pas. Intégrez plutôt la seconde décision
dans la première étape If sous forme de branches Else if supplémentaires, ou déplacez-la dans une sous-procédure.

#### Placez les décisions imbriquées dans une sous-procédure

Les étapes If ne peuvent pas être imbriquées. Lorsqu’une décision dépend d’une autre, placez la décision interne dans sa
propre procédure structurée et appelez-la avec une étape Sub-procedure depuis la branche qui en a besoin.

#### Ajoutez un Else lorsque « aucune des réponses ci-dessus » compte

Une étape If sans Else passe à l’étape suivante lorsqu’aucune condition ne correspond. Si le cas sans correspondance
doit se comporter différemment, ajoutez-lui une branche Else.

#### Conservez tout ce dont une étape ultérieure a besoin

Les décisions prises dans une branche If ne sont pas mémorisées par la suite. Si une étape ultérieure dépend de
quelque chose appris dans une branche, enregistrez-le avec un appel d’outil ou une variable dynamique dans cette branche.

#### Placez les conditions d’expression après l’outil qui les renseigne

Les conditions d’expression testent des variables dynamiques. Placez une étape If qui les utilise juste après l’étape Tool
qui définit ces variables. Pour créer des branches selon ce que l’utilisateur a dit, utilisez une condition de texte.

#### Extrayez les étapes communes dans une sous-procédure

Lorsque plusieurs procédures structurées partagent la même séquence, comme un transfert vers un intervenant humain, placez-la
dans une procédure structurée avec un déclencheur vide et appelez-la depuis chacune d’elles. Les séquences
copiées divergent au fil du temps.

### Travailler avec des outils

#### Contrôlez une étape Tool avec une étape If, et non avec son instruction

Une étape Tool appelle toujours son outil. Une condition écrite dans l’instruction, telle que \_ignorez cette étape
si le ticket est déjà étiqueté \_, ne peut pas empêcher l’appel. Si l’appel ne doit pas systématiquement
avoir lieu, placez la condition dans une étape If avant l’étape Tool.

#### Définissez les valeurs des paramètres au lieu de les décrire

Lorsqu’un paramètre doit toujours avoir une valeur précise, définissez-la avec un remplacement `constant` dans
`schema_overrides`. Une instruction telle que *définissez toujours le statut sur en attente* demande au modèle de
s’y conformer ; un remplacement est appliqué et ne peut pas être ignoré.

#### Ajoutez un gestionnaire d’échec à chaque étape Tool

Sans `on_failure`, tout échec d’outil met fin à la conversation. Ajoutez un gestionnaire qui indique à l’utilisateur
ce qui s’est passé, puis réessaie, effectue un transfert ou poursuit.

#### Limitez les étapes Tool à l’appel d’outil

Une étape Tool exécute uniquement l’outil ; l’agent ne peut ni parler ni prendre de décision pendant son exécution. Pour parler à
l’utilisateur ou créer une branche selon ce que l’outil a renvoyé, placez cette action dans une étape distincte avant ou après l’étape
Tool.

### Rédiger les instructions

#### Décrivez uniquement l’étape en cours

La procédure contrôle ce qui s’exécute ensuite, et l’agent n’a pas connaissance des étapes ultérieures pendant l’exécution
de l’étape en cours. Laissez l’ordre des étapes assurer le séquencement.

#### N’essayez pas de terminer le tour de parole avec du texte

Les phrases écrites dans les instructions d’étape, telles que *ceci est le dernier message de ce tour de parole*, demandent
à l’agent d’appliquer une limite que la plateforme ne prend pas en charge. Utilisez une étape Ask pour attendre l’utilisateur ou
l’outil système `end_call` pour terminer la conversation.

#### Conservez les règles globales dans le prompt système

Le ton, la mise en forme, les formules de clôture et les politiques de refus appartiennent au [prompt système](/docs/fr/eleven-agents/best-practices/prompting-guide). Une instruction d’étape doit uniquement indiquer
ce qui est spécifique à cette étape.

### Composer des procédures

Les conseils généraux pour composer des procédures s’appliquent également aux procédures structurées ; consultez [Composer des procédures](/docs/fr/eleven-agents/customization/procedures/free-form-procedures#composing-procedures) sur la page consacrée aux procédures de forme libre.

Un modèle est spécifique au mélange des types : une procédure de forme libre peut faire référence à une procédure structurée. Conservez la gestion des cas ouverts dans une procédure de forme libre et déléguez à une procédure structurée les parties qui doivent s’exécuter de la même manière à chaque fois, telles que la vérification d’identité ou le transfert.

## Limites

* Les étapes If ne peuvent pas être imbriquées, et deux étapes If ne peuvent pas être placées l’une à la suite de l’autre.
* Le seul outil système pris en charge est `end_call`.
* Les procédures structurées ne peuvent pas faire référence à des documents de la base de connaissances.
* Il n’est pas possible de terminer le tour de parole en cours lorsqu’une procédure se termine ; l’agent maintient le tour de parole ouvert et peut continuer à parler.
* Les arêtes de workflow ne peuvent pas se connecter à une procédure structurée ni en partir. Utilisez une étape Sub-procedure pour enchaîner les procédures structurées ; l’entrée et l’achèvement sont gérés par la plateforme.
* Le démarrage d’une procédure ajoute de la latence : l’agent effectue un appel d’outil pour y entrer, puis suit le workflow généré.

### Prise en charge par les fournisseurs de modèles

Les procédures structurées imposent des appels d’outils internes lors de l’entrée dans une sous-procédure et de l’achèvement d’une procédure. Les principales familles de modèles OpenAI, Anthropic, Gemini et Grok prennent en charge le choix forcé d’outil. D’autres modèles ou fournisseurs personnalisés peuvent ne pas le garantir, ce qui peut rendre les transitions entre sous-procédures ou l’achèvement des procédures moins fiables. Vérifiez la prise en charge du choix forcé d’outil lorsque vous utilisez un autre fournisseur de modèles.

Consultez [Procédures](/docs/fr/eleven-agents/customization/procedures#limitations) pour connaître les limites qui s’appliquent à toutes les procédures, notamment la limite de taille du contenu et les différences entre les procédures structurées et celles de forme libre.