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

# Procedimientos estructurados

## Descripción general

Un procedimiento estructurado es un [procedimiento](/docs/es/eleven-agents/customization/procedures) que ejecuta una secuencia fija de pasos. Un [procedimiento de formato libre](/docs/es/eleven-agents/customization/procedures/free-form-procedures) ofrece indicaciones en lenguaje natural que el agente interpreta y adapta a la situación. Un procedimiento estructurado es una lista ordenada de pasos tipados que el agente ejecuta en orden cada vez que se aplica el procedimiento.

Usa un procedimiento estructurado cuando determinados pasos deban ocurrir siempre de la misma forma en cada llamada: verificar la identidad de quien llama, escalar un ticket o aceptar un pago. Lo creas como una lista breve de pasos en lenguaje sencillo.

Como todos los procedimientos, un procedimiento estructurado tiene un activador que describe cuándo se aplica. Cuando una conversación coincide con el activador, el agente ejecuta los pasos del procedimiento en orden y, después, vuelve al resto de la conversación.

![Editor de procedimientos
estructurados](/docs/_fern-img/bc996f67b2afad8f1de5abe8febcf8af3766b4f098627b0ae60e0456b3c2703b.webp)

## Cuándo usar un procedimiento estructurado

Usa un procedimiento estructurado cuando determinados pasos deban ejecutarse siempre de la misma forma, pero aun así quieras crearlo rápidamente con pasos sencillos. Los procedimientos estructurados son más fáciles de escribir que un workflow, pero menos flexibles. Para saber cómo se comparan con los procedimientos de formato libre, los workflows y el prompt del sistema, consulta [Cuándo usar procedimientos](/docs/es/eleven-agents/customization/procedures#when-to-use-procedures).

## Anatomía de un procedimiento estructurado

Un procedimiento estructurado tiene tres partes: un nombre, un activador y una lista ordenada de pasos.

### Nombre

Una etiqueta breve que identifica el procedimiento en el panel. El nombre nunca se envía al LLM, por lo que no afecta al comportamiento del agente.

### Activador

Una descripción en lenguaje natural de cuándo debe ejecutar el agente este procedimiento, por ejemplo, *Cuando el usuario pide reembolsar un pedido*. El agente compara la intención del usuario con el activador de cada procedimiento y ejecuta el que coincide, así que los activadores deben ser concretos y distintos. El agente solo ve el texto del activador, nunca el nombre ni el ID del procedimiento. Un activador funciona igual que en cualquier procedimiento; consulta [Redactar activadores](/docs/es/eleven-agents/customization/procedures/free-form-procedures#writing-triggers).

Deja el activador vacío para convertir el procedimiento en un subprocedimiento que solo se ejecuta cuando otro procedimiento lo llama.

### Pasos

El cuerpo del procedimiento es una lista ordenada de pasos con tipos definidos. Hay varios tipos de pasos y puedes combinarlos para describir la tarea.

| Paso              | Qué hace                                                                                                                                                                                                                                                                           |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Ask**           | Pide información al usuario y espera. Sigue preguntando hasta que el usuario responde. Es el único paso que se pausa para el usuario.                                                                                                                                              |
| **Tell**          | Hace que el agente comunique algo con sus propias palabras y pasa al siguiente paso.                                                                                                                                                                                               |
| **Say**           | Hace que el agente diga un mensaje exacto palabra por palabra y pasa al siguiente paso. Un paso Say puede incluir una traducción configurada específicamente para cada idioma que admita el agente.                                                                                |
| **Tool**          | Llama a una herramienta concreta. Puedes indicar al LLM en lenguaje natural cómo llamar a la herramienta o fijar explícitamente valores de parámetros cuando se requiera la máxima determinación. También puedes definir pasos para ejecutar si falla la llamada a la herramienta. |
| **If**            | Evalúa una o varias condiciones en orden y ejecuta los pasos de la primera coincidencia. Se ejecuta un Else opcional cuando no hay ninguna coincidencia.                                                                                                                           |
| **Sub-procedure** | Ejecuta otro procedimiento estructurado. Cuando se completan sus pasos, el control vuelve al siguiente paso de este procedimiento (el que realiza la llamada).                                                                                                                     |
| **System tool**   | Realiza una acción integrada del sistema. Actualmente, solo se admite finalizar la llamada.                                                                                                                                                                                        |
| **Retry**         | Vuelve a ejecutar el controlador de fallos de un paso Tool, incluida la llamada a la herramienta, hasta tres veces. Solo está disponible dentro del controlador de fallos de un paso Tool.                                                                                         |

![Menú de tipos de pasos de procedimientos estructurados](/docs/_fern-img/14976a6b9979d21fd7c77541a49e7475f8aa0764af4940746d3390804e7c4598.webp)

No todos los pasos pueden aparecer en cualquier lugar. Dentro de una rama If, puedes usar cualquier paso excepto otro If o un Retry. Dentro del controlador de fallos de un paso Tool, puedes usar cualquier paso excepto un If u otro Tool.

## Referencia de pasos de la API

El `content` de un procedimiento estructurado es un documento codificado en JSON que contiene una matriz `steps`. Cada paso es un objeto identificado por su `type`. El activador es un campo independiente de nivel superior en el procedimiento, no forma parte de `content`. Las cargas útiles de la API y el SDK usan `type: "deterministic"` para el propio procedimiento.

### Ask

Un paso Ask indica al agente que solicite información y espere hasta que el usuario proporcione una respuesta adecuada.

* Tipo de API: `ask`
* `instruction`: Cadena obligatoria y no vacía.

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

### Tell

Un paso Tell indica al agente que genere un único mensaje con sus propias palabras. No espera una respuesta del usuario antes de continuar.

* Tipo de API: `tell`
* `instruction`: Cadena obligatoria y no vacía.

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

### Say

Un paso Say reproduce el texto proporcionado exactamente como está escrito y después continúa. Proporciona `message_translations` para dar al agente un mensaje exacto para cada idioma adicional que admita, con la clave del código de idioma.

* Tipo de API: `say`
* `message`: Cadena obligatoria y no vacía.
* `message_translations`: Objeto opcional que asigna un código de idioma a `{ "value": "..." }`.

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

### If, else if y else

Un paso If contiene una o varias ramas condicionales ordenadas. Se ejecuta la primera rama que coincide. La matriz opcional `fallback` es la rama Else.

* Tipo de API: `branch`
* `branches`: Lista obligatoria y no vacía de ramas condicionales.
* `fallback`: Lista opcional de pasos Else.
* Cada rama requiere una `condition` y una lista `steps` no vacía.

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

Esto se comporta como if/else-if/else:

1. Las condiciones se evalúan en orden.
2. Se ejecuta la primera rama que coincide.
3. Si no coincide ninguna condición, se ejecuta `fallback`.
4. Cuando termina una rama, el procedimiento vuelve a unirse a la secuencia principal.

El ejemplo anterior usa una condición de texto, que el modelo evalúa en lenguaje natural. Las condiciones también pueden ser expresiones sobre variables dinámicas:

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

Una condición de expresión comprueba variables dinámicas, que se rellenan con los resultados de herramientas o se establecen al iniciar la conversación. No puede leer la respuesta más reciente del usuario. Para ramificar según lo que haya dicho el usuario, usa una condición de texto.

Todas las ramas de un mismo paso If deben usar el mismo tipo de condición: `llm` o `expression`.

### Tool

Un paso Tool llama a una herramienta concreta.

* Tipo de API: `tool_call`
* `tool_id`: ID de herramienta obligatorio y no vacío. La herramienta debe estar vinculada al agente.
* `tool_name`: Nombre de herramienta obligatorio que debe coincidir con la herramienta.
* `instruction`: Instrucción opcional que describe cómo llamar a la herramienta.
* `schema_overrides`: Valores fijos opcionales para los parámetros de la herramienta.
* `on_failure`: Controlador de fallos opcional.

```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."
}
```

#### Valores fijos de parámetros

Usa `schema_overrides` cuando un parámetro deba tener siempre un valor específico. El modelo no ve ni elige un parámetro sobrescrito. Las claves son rutas de parámetros en el esquema de la herramienta; cada valor indica una fuente:

| `source`           | Campos              | Comportamiento                                                              |
| ------------------ | ------------------- | --------------------------------------------------------------------------- |
| `constant`         | `constant_value`    | Envía siempre el valor indicado.                                            |
| `dynamic_variable` | `dynamic_variable`  | Envía el valor actual de la variable dinámica indicada.                     |
| `llm`              | `prompt` (opcional) | Permite que el modelo elija el valor, con una anulación de prompt opcional. |
| `omit`             |                     | Omite el parámetro de la llamada.                                           |

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

#### Gestión de fallos

Sin `on_failure`, una llamada a una herramienta que falla finaliza la conversación. Añade `on_failure` para ejecutar en su lugar pasos de recuperación.

* `fallback`: Lista obligatoria y no vacía de pasos que se ejecutan cuando falla la herramienta.
* `branches`: Reservado para la gestión condicional de fallos. Déjalo vacío.

```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 controlador de fallos puede contener pasos Ask, Tell, Say, Sub-procedure, System tool y Retry. No puede contener pasos Tool ni If. Después de ejecutar el controlador, el procedimiento continúa con el paso posterior al paso Tool.

### Retry

Un paso Retry vuelve a ejecutar el controlador de fallos que lo contiene, incluida la llamada a la herramienta. Cada intento vuelve a llamar a la herramienta y, si vuelve a fallar, ejecuta de nuevo todos los pasos del controlador. Cuando se agotan los intentos, la conversación termina.

* Tipo de API: `retry`
* `max_retries`: Entero opcional de 1 a 3. El valor predeterminado es 1.
* El valor cuenta los intentos posteriores a la llamada original a la herramienta.
* Retry solo es válido dentro de `on_failure`.
* Retry debe ser el último paso de su controlador de fallos, ya que los pasos posteriores serían inaccesibles.

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

### Sub-procedure

Un paso Sub-procedure ejecuta otro procedimiento estructurado. Cuando se completan los pasos de ese procedimiento, la ejecución vuelve al paso posterior al paso Sub-procedure.

* Tipo de API: `sub_procedure`
* `procedure_id`: ID de procedimiento obligatorio y no vacío.
* El destino debe existir en el mismo agente.
* El destino debe ser un procedimiento estructurado.
* Un procedimiento no puede invocarse a sí mismo.

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

### System tool

Un paso System tool realiza una acción integrada del sistema.

* Tipo de API: `system_tool`
* `system_tool_name`: Nombre de herramienta del sistema obligatorio.
* Actualmente, solo se admite `end_call`. Es posible que se añadan más herramientas del sistema más adelante.
* Como `end_call` es terminal, debe ser el último paso de la secuencia, rama o controlador de fallos que lo contiene.

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

## Reglas de validación

Al publicar el agente o guardar el borrador del agente, se rechaza cualquier procedimiento estructurado que incumpla alguna de estas reglas. El error identifica el paso problemático mediante su ruta.

* No se pueden colocar dos pasos If consecutivos.
* Los pasos If no se pueden anidar.
* Un paso If con condiciones de expresión no puede seguir directamente a un paso Ask.
* Todas las condiciones de un mismo paso If deben ser del mismo tipo: `llm` o `expression`.
* Retry solo puede aparecer dentro de `on_failure` y debe ser el último paso allí.
* `end_call` debe ser el último paso de la lista en la que aparezca.
* El `fallback` de un controlador de fallos debe contener al menos un paso.
* Un Sub-procedure debe apuntar a un procedimiento estructurado existente en el mismo agente y no a sí mismo.
* `tool_id` debe ser una herramienta del agente, `tool_name` debe coincidir y `schema_overrides` debe coincidir con el esquema de la herramienta.
* La lista `steps`, cada `instruction` y cada `message` no pueden estar vacíos.

Para saber cómo reestructurar un procedimiento que incumple una de estas reglas, consulta [Buenas prácticas](#best-practices).

## Ejemplo completo de API

Este ejemplo gestiona la cancelación de un pedido según el estado del envío. Fija un parámetro de herramienta, se recupera de una llamada a una herramienta fallida, invoca otro procedimiento estructurado y luego finaliza la llamada.

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

## Cómo se ejecuta un procedimiento estructurado

Convertir los pasos de un procedimiento estructurado al formato que ejecuta el agente se denomina compilación. La plataforma compila todos los procedimientos estructurados al publicar; no tienes que compilar nada tú. Actualmente, el resultado compilado se muestra como nodos de solo lectura en la pestaña **Workflow**.

Cuando la solicitud del usuario coincide con el activador de un procedimiento, el agente entra en el procedimiento y ejecuta sus pasos en orden. Mientras está dentro del procedimiento estructurado, el agente se centra en cada paso de forma aislada. Cuando llega al final, vuelve al resto de la conversación.

Las siguientes reglas describen cómo se comportan los pasos en tiempo de ejecución.

#### Solo Ask espera al usuario

Todos los pasos excepto Ask se ejecutan inmediatamente y el control pasa al siguiente paso dentro
del mismo turno. Un paso Tell o Say transmite su mensaje y continúa. No hay ningún paso que pause
la conversación aparte de Ask, ni ningún paso que finalice el turno actual. Si necesitas que el usuario
introduzca información, usa un paso Ask. Si la conversación debe terminar, usa la herramienta del sistema `end_call`.

#### Llegar al final de un procedimiento no finaliza el turno

Cuando se completa el último paso, el procedimiento termina y el agente vuelve al resto de la
conversación con el turno todavía abierto, por lo que puede decir algo más. Cuando se completa un subprocedimiento,
el control vuelve al siguiente paso del procedimiento que lo llamó.

#### Los pasos Tool solo distinguen entre éxito y fallo

Un paso Tool no puede ramificarse según un código de estado ni el cuerpo de la respuesta. Si la herramienta tiene éxito,
el procedimiento continúa. Si falla y el paso no tiene un controlador de fallos, la conversación termina. Si
tiene uno, se ejecutan los pasos del controlador y el procedimiento continúa con el siguiente paso. Un Retry dentro
del controlador vuelve a ejecutar la herramienta y, si vuelve a fallar, todos los pasos del controlador, hasta que la herramienta
tenga éxito o se agoten los intentos. Si se agotan, la conversación termina.

#### Los pasos If continúan cuando no hay ninguna coincidencia

Las condiciones se evalúan en orden y se ejecuta la primera coincidencia. La rama Else se ejecuta cuando no hay ninguna
coincidencia. Si no hay Else y no coincide nada, el procedimiento continúa con el paso posterior
al If. Un caso no gestionado no es un error.

#### Las ramas If no mantienen el estado

Las decisiones tomadas dentro de una rama If no se recuerdan en los pasos posteriores. Si se necesita más adelante
algo aprendido en una rama, persístelo explícitamente con una llamada a una herramienta o una variable dinámica.

#### Los pasos Ask, Tell y Say no tienen herramientas

Solo los pasos Tool pueden llamar a herramientas. No es necesario indicar a un paso Ask, Tell o Say que no llame a
herramientas; no puede hacerlo.

## Gestionar un procedimiento estructurado

#### Crear desde el panel

Abre tu agente en el [panel](https://elevenlabs.io/app/agents) y selecciona **Procedures**.
Usa **+** para crear un procedimiento estructurado. Añade un activador, selecciona un tipo para cada paso y
publica los cambios del agente.

El panel valida los procedimientos estructurados mientras los editas. Si un procedimiento incumple una
[regla de validación](#validation-rules), el botón **Publish** muestra un estado de error, la pestaña
**Procedures** muestra una insignia de error y no se puede iniciar la vista previa hasta que se corrija
el procedimiento. Selecciona el indicador de error para ver qué procedimiento y paso se ven afectados.

![Editor de procedimientos estructurados con el botón Publish en estado de error y una insignia de 1 Error](/docs/_fern-img/e406c33fac3966fab26d5d07e10d364a475fc4a56fd75aad2e23edbb0d1940d5.webp)

![Cuadro de diálogo con los detalles de validación que muestra el procedimiento fallido y el paso que necesita un mensaje](/docs/_fern-img/a1cc889b2d0e68ce23725609b531938d0f7c417b1c6f4375103531eaae4ada63.webp)

#### Gestionar desde la CLI

La [CLI de ElevenLabs](/docs/es/eleven-agents/operate/cli) crea y publica procedimientos
estructurados con los mismos comandos que los de formato libre. Establece `type` en `deterministic` y pasa los
pasos como una cadena codificada en JSON en `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 publicación valida cada procedimiento estructurado de la rama. Si alguno no es válido, el comando
finaliza con un valor distinto de cero e imprime los errores agrupados por ID de procedimiento. Corrige el borrador del procedimiento y vuelve a publicar.

#### Gestionar mediante la API

Las cargas útiles de la API y el SDK usan `type: "deterministic"` para los procedimientos estructurados. Su `content` es
un documento codificado en JSON.

### Requisitos previos

* Una clave de API de ElevenLabs en la variable de entorno `ELEVENLABS_API_KEY`.
* Los valores `agent_id` y `branch_id` de destino. Consulta [Control de versiones de agentes](/docs/es/eleven-agents/operate/versioning) para las operaciones de ramas.
* La versión `2.60.0` o posterior del paquete de Python `elevenlabs` o del paquete de JavaScript `@elevenlabs/elevenlabs-js`.

Las ediciones mediante la API son privadas para tu usuario en la rama seleccionada hasta que publiques una nueva versión del agente.

### Crear o actualizar un borrador

Crea un procedimiento estructurado con `POST /procedures` y establece `type` en `deterministic`.
Actualiza un procedimiento existente con `PATCH /procedures/{procedure_id}/draft`, como se muestra a continuación.

Establece `trigger` como campo de nivel superior. Codifica en JSON el documento de pasos en `content` en lugar de
enviar un objeto anidado.

```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.\"}]}"
  }'
```

Guardar un borrador de procedimiento no valida sus pasos. La validación se ejecuta al publicar o
al guardar el borrador del agente con `POST /v1/convai/agents/{agent_id}/drafts`.

### Publicar los cambios

Publica con [Actualizar agente](/docs/es/api-reference/agents/update). La publicación valida todos los
procedimientos estructurados de la rama, los compila y almacena el resultado con la nueva
versión. La solicitud no necesita ningún campo `workflow`; la compilación se realiza como parte de la publicación.
Consulta [Cómo se ejecuta un procedimiento estructurado](#how-a-structured-procedure-runs) para saber qué significa
compilar.

```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 un procedimiento estructurado no es válido, la publicación devuelve `400` y no se escribe nada:

```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á agrupado por ID de procedimiento. Cada entrada identifica el campo y el paso que han fallado. Corrige el
borrador del procedimiento y vuelve a publicar.

> **Note**
>
> La ruta `/procedures/compile` de versiones anteriores de esta API sigue funcionando, pero es
> heredada y terminará por quedar obsoleta. La publicación gestiona la compilación; no llames a la
> ruta de compilación en código nuevo.

Consulta [Gestionar procedimientos](/docs/es/eleven-agents/customization/procedures#manage-procedures) para obtener información sobre
la eliminación y el descarte de borradores, o la
[referencia de la API de Procedures](/docs/es/api-reference/agents/procedures/) para consultar los esquemas completos de las rutas.

## Buenas prácticas

Cada tipo de paso ya aplica su propio comportamiento, así que rara vez necesitas detallarlo. Escribe la intención de cada paso y deja que el tipo de paso se encargue del resto. Las indicaciones siguientes cubren los casos que conviene configurar bien.

Para probar un procedimiento estructurado, sigue [Iterar en un procedimiento](/docs/es/eleven-agents/customization/procedures/free-form-procedures#iterating-on-a-procedure).

### Elegir tipos de paso

#### Haz una pregunta por cada paso Ask

Un paso Ask espera una respuesta. Si agrupas varias preguntas en una sola instrucción, el
agente suele omitir algunas o combinarlas. Usa un Ask para cada dato.

#### Usa Tell para afirmaciones y Ask para preguntas

Un paso Tell transmite su mensaje y continúa sin esperar. Un Tell formulado como pregunta
nunca recibe respuesta. Si un paso necesita una respuesta del usuario, es un Ask.

#### Da a un Ask una condición de salida clara cuando la pregunta no sea suficiente

Un paso Ask avanza cuando recibe una respuesta adecuada. Si no queda claro qué se considera una respuesta
a partir de la pregunta, indícalo en la instrucción; por ejemplo: \_Pide el ID del pedido; un
ID válido tiene ocho dígitos \_.

#### Elige Tell para formular mensajes y Say para palabras exactas

Usa un paso Tell cuando el agente deba redactar el mensaje por sí mismo y un paso Say cuando
el texto deba ser literal o traducido. Ambos transmiten exactamente un mensaje, así que no hace falta
indicar a un paso que envíe un único mensaje.

#### No indiques a pasos que no son Tool que eviten herramientas

Los pasos Ask, Tell y Say no pueden llamar a herramientas. Escribir *no llames a ninguna herramienta* en ellos añade ruido
a la instrucción sin cambiar el comportamiento.

### Estructurar el procedimiento

#### No rellenes el espacio entre dos pasos If

No se pueden colocar dos pasos If seguidos. Insertar un Tell o Say sin relación entre ellos para
cumplir la regla hace que el agente diga algo que no debería. En su lugar, incorpora la segunda decisión
en el primer If como ramas Else if adicionales, o muévela a un subprocedimiento.

#### Incluye las decisiones anidadas en un subprocedimiento

Los pasos If no se pueden anidar. Cuando una decisión depende de otra, incluye la decisión interna en su
propio procedimiento estructurado y llámalo con un paso Sub-procedure desde la rama que lo necesite.

#### Añade un Else cuando importe 'ninguna de las anteriores'

Un paso If sin Else continúa al siguiente paso cuando no coincide nada. Si el caso sin coincidencia
debe comportarse de otra forma, añade una rama Else para él.

#### Conserva todo lo que necesite un paso posterior

Las decisiones tomadas dentro de una rama If no se recuerdan después. Si un paso posterior depende de
algo aprendido en una rama, regístralo con una llamada a herramienta o una variable dinámica dentro de la rama.

#### Coloca las condiciones de expresión después de la herramienta que las rellena

Las condiciones de expresión comprueban variables dinámicas. Coloca un paso If que las use justo después del paso Tool
que establece esas variables. Para bifurcar según lo que haya dicho el usuario, usa una condición de texto.

#### Extrae los pasos compartidos a un subprocedimiento

Cuando varios procedimientos estructurados compartan la misma secuencia, como escalar a una persona, inclúyela
en un procedimiento estructurado con un activador vacío y llámalo desde cada uno. Las secuencias
copiadas acaban divergiendo con el tiempo.

### Trabajar con herramientas

#### Controla un paso Tool con un If, no con su instrucción

Un paso Tool siempre llama a su herramienta. Una condición escrita en la instrucción, como \_omite esto
si el ticket ya tiene una etiqueta \_, no puede impedir la llamada. Si la llamada no debe
producirse siempre, incluye la condición en un paso If antes del paso Tool.

#### Fija los valores de los parámetros en lugar de describirlos

Cuando un parámetro deba tener siempre un valor específico, establécelo con una anulación `constant` en
`schema_overrides`. Una instrucción como *establece siempre el estado como pendiente* pide al modelo que
la cumpla; una anulación se aplica obligatoriamente y no se puede omitir.

#### Da a cada paso Tool un controlador de errores

Sin `on_failure`, cualquier error de la herramienta termina la conversación. Añade un controlador que indique al usuario
qué ha ocurrido y vuelva a intentarlo, escale el caso o continúe.

#### Limita los pasos Tool a la llamada a la herramienta

Un paso Tool solo ejecuta la herramienta; el agente no puede hablar ni tomar una decisión durante él. Para hablar con
el usuario o bifurcar según lo que haya devuelto la herramienta, inclúyelo en un paso independiente antes o después del
paso Tool.

### Redactar instrucciones

#### Describe solo el paso actual

El procedimiento controla qué se ejecuta después y el agente no conoce los pasos posteriores mientras ejecuta
el actual. Deja que el orden de los pasos se encargue de la secuencia.

#### No intentes terminar el turno con texto

Las frases escritas en las instrucciones de los pasos, como *este es el último mensaje de este turno*, piden
al agente que aplique un límite que la plataforma no admite. Usa un paso Ask para esperar al usuario o
la herramienta del sistema `end_call` para finalizar la conversación.

#### Mantén las reglas globales en el prompt del sistema

El tono, el formato, las despedidas y las políticas de rechazo corresponden al [prompt del sistema](/docs/es/eleven-agents/best-practices/prompting-guide). La instrucción de un paso debe indicar solo
lo específico de ese paso.

### Combinar procedimientos

Las indicaciones generales para combinar procedimientos también se aplican a los procedimientos estructurados; consulta [Combinar procedimientos](/docs/es/eleven-agents/customization/procedures/free-form-procedures#composing-procedures) en la página de procedimientos de formato libre.

Un patrón es específico de la combinación de tipos: un procedimiento de formato libre puede hacer referencia a uno estructurado. Mantén la gestión abierta en un procedimiento de formato libre y delega en un procedimiento estructurado las partes que deben ejecutarse siempre de la misma manera, como la verificación de identidad o la escalada.

## Limitaciones

* Los pasos If no se pueden anidar ni se pueden colocar dos pasos If seguidos.
* La única herramienta del sistema compatible es `end_call`.
* Los procedimientos estructurados no pueden hacer referencia a documentos de la base de conocimiento.
* No hay forma de finalizar el turno actual cuando termina un procedimiento; el agente mantiene el turno abierto y puede seguir hablando.
* No se puede iniciar un procedimiento estructurado desde un nodo específico del workflow en el panel.
* Iniciar un procedimiento añade latencia: el agente realiza una llamada a herramienta para entrar en él y después avanza por el workflow generado.

### Compatibilidad con proveedores de modelos

Los procedimientos estructurados fuerzan llamadas a herramientas internas al entrar en un subprocedimiento y al completar un procedimiento. Las principales familias de modelos de OpenAI, Anthropic, Gemini y Grok admiten la elección forzada de herramientas. Es posible que otros modelos o proveedores personalizados no la garanticen, lo que puede hacer menos fiables las transiciones entre subprocedimientos o la finalización de procedimientos. Verifica la compatibilidad con la elección forzada de herramientas cuando uses otro proveedor de modelos.

Consulta [Procedimientos](/docs/es/eleven-agents/customization/procedures#limitations) para conocer los límites que se aplican a todos los procedimientos, incluido el límite de tamaño del contenido y las diferencias entre procedimientos estructurados y de formato libre.