Workflows como código
Información general
Un flujo de trabajo se almacena como un grafo de nodos y aristas. Escribir ese grafo a mano implica que debes mantener coherentes por tu cuenta los ID de las aristas, las listas edge_order y los objetos de condición. El constructor Workflow de los SDK de Python y JavaScript te permite describir el mismo grafo mediante llamadas a métodos encadenadas. Después genera el valor workflow que agents.create() y agents.update() ya aceptan.
Úsalo para:
- Crear un flujo de trabajo en código y revisarlo como cualquier otro cambio de código.
- Cargar el flujo de trabajo de un agente, modificar un nodo y volver a enviarlo sin alterar el resto del grafo.
- Guardar flujos de trabajo como JSON en el control de versiones y validarlos en CI.
El constructor se ejecuta por completo en el SDK. No llama a nuevas rutas de API, y todo lo que crea puede abrirse y editarse en el editor visual del panel.
Requisitos
- Python: el paquete
elevenlabs. El constructor se importa desdeelevenlabs.agent_workflows. - JavaScript: el paquete
@elevenlabs/elevenlabs-js. El constructor se exporta desde la raíz del paquete.
Crear un flujo de trabajo
El objeto Workflow representa el nodo inicial. Cada verbo añade un nodo y lo devuelve, por lo que puedes encadenar desde él el siguiente paso:
Los métodos de enrutamiento deciden qué arista lleva al siguiente nodo:
Los verbos llamados directamente en el flujo de trabajo se ramifican desde el nodo inicial con una arista incondicional. Este ejemplo dirige a quienes llaman a una consulta de pedidos, vuelve a intentar la identificación si la consulta falla y transfiere a quienes son VIP o están frustrados:
build() valida todo el grafo y devuelve el modelo de solicitud. También:
- Asigna al nodo inicial el ID
start_node, que requiere la API. - Genera ID de arista con el formato
source__target. - Rellena el
edge_orderde cada nodo en el orden en que añadiste las aristas. - Posiciona cualquier nodo que no tenga posición para que el grafo se organice de izquierda a derecha en el editor visual.
Escribir un flujo de trabajo como una sola cadena
up() devuelve el nodo desde el que se encadenó el actual, para que puedas describir un flujo de trabajo completo en una expresión en lugar de guardar cada nodo en una variable. Dentro de una sola cadena, usa go_to() / goTo() con un ID de nodo, ya que no hay ninguna variable que pasar:
Para un identificador de nodo de wf.node(id), up() devuelve el nodo del que procede la primera arista que entra en él. Para el nodo inicial, devuelve el nodo inicial.
Opciones de nodo
Los ajustes opcionales se indican como argumentos con nombre en Python y en un objeto de opciones final en JavaScript. Sus nombres coinciden con los campos del nodo en la API:
Cada verbo también acepta position si quieres colocar el nodo manualmente. Workflow(prevent_subagent_loops=True) en Python, o new Workflow({ preventSubagentLoops: true }) en JavaScript, evita que la conversación vuelva a entrar en un subagente que ya ha visitado.
Destinos de transferencia
Condiciones
when() acepta una cadena simple, un Condition o un Expr:
- Una cadena es una condición de LLM: el LLM decide si se cumple.
Condition.llm(text, label=...)es lo mismo, con una etiqueta que se muestra en la arista del editor visual. UsaCondition.expr(expr, label=...)para etiquetar una expresión.- Un
Exprse evalúa con variables dinámicas, sin llamar al LLM.
Crea expresiones a partir de Expr.variable(name) y Expr.literal(value). Compáralas con eq, neq, gt, gte, lt y lte, y realiza operaciones aritméticas con add, sub, mul y div. Combínalas con all_of / allOf, any_of / anyOf e if_else / ifElse. Los valores simples se envuelven en Expr.literal() automáticamente. Expr.llm(description) pide al LLM que extraiga un valor de la conversación; pasa type y enum para obtener una cadena, un número o uno de un conjunto fijo en lugar de un booleano.
Bucles y aristas hacia atrás
La API permite una arista entre dos nodos cualesquiera, en cualquiera de las dos direcciones. Para que la conversación pueda volver por donde vino, asigna a la arista una condición hacia atrás con back:
go_to() / goTo() se encarga del caso habitual por ti. Cuando el nodo de destino ya tiene una arista que lleva hasta aquí, la nueva arista se convierte en la condición hacia atrás de esa arista. En el primer ejemplo, failed.go_to(identify) se envía como la condición hacia atrás de la arista identify → lookup_order. Cualquier otra segunda arista entre los mismos dos nodos, y cualquier arista de un nodo hacia sí mismo, no supera la validación.
Editar un agente existente
Workflow.from_agent() / Workflow.fromAgent() carga el flujo de trabajo de un agente devuelto por agents.get(). Se conservan los ID de nodo, los ID de arista, las posiciones del editor y el orden de las aristas, por lo que al volver a enviarlo solo se modifica lo que has cambiado.
insert_between() / insertBetween() pasa a tu función una rama que contiene la condición de la arista sustituida. La función devuelve el último nodo que añadió, que después se conecta al destino original. El método devuelve ese nodo, o None / undefined si no hay ninguna arista entre los dos nodos.
Guardar flujos de trabajo en el control de versiones
to_json_string() / toJSONString() escribe el flujo de trabajo en el formato de transmisión de la API: claves en snake_case, ordenadas en todos los niveles y con sangría de 2 espacios. Tiene la misma estructura que usan la API REST y la CLI, y ambos SDK escriben archivos idénticos byte a byte para el mismo flujo de trabajo, por lo que las diferencias se mantienen pequeñas. Workflow.from_json() / Workflow.fromJSON() lo vuelve a leer y también acepta una configuración de agente completa con una clave workflow, como un archivo del directorio agent_configs/ de la CLI.
Una configuración habitual:
Crear el archivo inicial
Carga el agente con from_agent() / fromAgent() y escríbelo, o extráelo con elevenlabs agents pull.
Editar
Modifica el JSON directamente, o cárgalo con from_json() / fromJSON() y edítalo con el
constructor en un script.
Visualizar un flujo de trabajo
La CLI dibuja un archivo de flujo de trabajo como un diagrama de flujo para que puedas comprobar lo que ha creado tu código sin abrir el panel. Acepta un archivo de flujo de trabajo independiente escrito por to_json_string() / toJSONString(), o una configuración de agente con una clave workflow:
De forma predeterminada, dibuja cuadros y flechas en la terminal, con cada condición de arista numerada en su arista y escrita en una leyenda debajo. Usa --format mermaid para mostrar en su lugar el código fuente de Mermaid, o --format mermaid-md para envolverlo en un bloque de código delimitado que GitHub renderiza, por ejemplo, en un comentario de pull request:
El comando solo lee archivos locales, por lo que no necesita una clave de API y puede ejecutarse en CI.
Validación
Las llamadas encadenadas nunca fallan por sí solas. build(), to_json() / toJSON() y to_json_string() / toJSONString() comprueban todo el grafo y generan o lanzan un único WorkflowValidationError cuya lista issues enumera cada problema, cada uno con un code, un message y el node_id / nodeId al que se refiere.
Los errores incluyen:
- Dos aristas entre el mismo par de nodos o una arista de un nodo hacia sí mismo.
- Una arista que entra en el nodo inicial o sale de un nodo final.
- Una arista desde un nodo de herramienta que no es de éxito ni de error, o una arista de éxito o error desde cualquier otro tipo de nodo.
- Dos nodos con el mismo ID o una arista hacia un nodo que no existe.
Los nodos a los que no se puede llegar desde el nodo inicial se notifican como advertencias, mediante on_warning / onWarning, y no detienen la creación.
Tipos de nodo más recientes que tu SDK
Un flujo de trabajo cargado desde la API o desde un archivo puede contener tipos de nodo que tu versión del SDK aún no conoce. Se conservan sin cambios al pasar por from_json() / fromJSON() y to_json_string() / toJSONString(), y build() informa de cada uno como una advertencia. El modelo de solicitud tipado no puede incluirlos, así que actualiza el SDK o envía directamente el formato de transmisión: