Cookbook
Storylines · for AI agents

Compilar un flujo en una Historia

Convierte un proceso de varios pasos en un grafo dirigido con estado: crea, valida y publica.

MCP tools:create_storylinevalidate_storylinepublish_storylinelist_storylinesupdate_storyline

Una Storyline es un grafo dirigido adjunto a un agente: convierte "responder una pregunta" en "llevar a cabo toda una tarea de principio a fin" (recolección de datos, tutoría, coaching…). Los nodos son pasos (cada uno con su propia tarea, habilidades, base de conocimientos y herramientas, además de dimensiones de perfil modificables); las salidas llevan condiciones (ai / user_choice / rule / callback / goto_storyline). El tiempo de ejecución nunca edita el alma ni el límite de seguridad del agente — es constante desde el primer nodo hasta el último, lo cual es exactamente lo que necesita un producto regulado o dirigido a menores.

Crear un borrador

create_storyline(
  agent_name="Support", key="loan-intake", name="Loan intake",
  profile_schema={"docs_ready": {"type": "bool"}},          # dims that accumulate across nodes
  graph={"nodes": [
    {"node_key": "n1", "title": "Understand need", "flags": {"is_entry": True},
     "on_enter_opening": "Hi — which kind of loan are you applying for?",
     "exits": [{"kind": "ai", "label": "need clear", "to_node_key": "n2",
                "ai_criteria": "the user stated the loan type and rough amount"}]},
    {"node_key": "n2", "title": "Collect documents",
     "task": "Collect the checklist items; chase missing ones across turns.",
     "exits": [{"kind": "user_choice", "label": "documents ready", "to_node_key": "n3",
                "user_choice": {"button_text": "I've uploaded everything"},
                "writes": [{"ref": "dim", "key": "docs_ready", "op": "set", "value": True}]}]},
    {"node_key": "n3", "title": "Hand off", "task": "Summarise the case and hand off to a human.",
     "flags": {"is_terminal": True}, "exits": []}
  ]},
  allow_agent_enroll=True,
  enroll_trigger="the visitor says they want to apply for a loan",
)

★ Validar, luego publicar ★

validate_storyline(storyline_id="…")   # → {"ok": true} is required to publish
publish_storyline(storyline_id="…")    # freezes an immutable version and goes live

Inscripción — quién entra y cuándo (requiere publicación)

  • is_default=True — uno por agente; inscripción automática en la primera conversación.
  • allow_agent_enroll=True + enroll_trigger — el agente inscribe al usuario cuando juzga que se cumple el desencadenante.
  • entry="user" (o "both") — el flujo aparece en el menú de flujos guiados del widget de chat y en el menú desplegable de nueva conversación, por lo que el usuario lo inicia deliberadamente (un botón, no un juicio del modelo). Asigna un display_name y una description de una línea — eso es lo que muestra el menú. Combínalo con concurrency="session" para flujos de "un caso por conversación": cada selección abre un caso nuevo.
  • Asignación manual en la consola.

Lo que ve el usuario — visibilidad, banner y el mapa de solo lectura

user_visibility controla la presentación al usuario final de un flujo en ejecución (por defecto invisible):

  • invisible — ninguna interfaz de usuario; el flujo se ejecuta en silencio (comportamiento anterior).
  • named — un banner delgado sobre el chat muestra el nombre del flujo. Nada más.
  • trail — banner + un botón View que abre un mapa de solo lectura: los pasos ya realizados llevan sus títulos; las ramas no realizadas y los pasos futuros son bloques grises anónimos (ocultos en el servidor — el usuario ve lo largo que es el flujo, no qué hay dentro).
  • full — banner con paso x / y + el mapa completo: cada paso con nombre, codificado por colores según hecho / actual / próximo.

Extras: allow_exit=True añade un botón Salir al banner (un flujo salido no se vuelve a inscribir automáticamente en esa conversación; un flujo seleccionado por el usuario puede volver a entrarse desde el menú, manteniendo el progreso). show_profile=True lista los valores actuales de las dimensiones de perfil debajo del mapa (números como barras de progreso cuando el esquema declara min/max). Por nodo, rewind: "reset" | "keep" permite al usuario hacer clic en un paso realizado en el mapa completo y volver a él — reset restaura la instantánea del perfil tomada al llegar, keep mantiene los datos recopilados (flujos de estudio/revisión). Los efectos secundarios del mundo real (registros archivados, documentos enviados) nunca se revierten, así que marca solo los pasos sin efectos secundarios. En canales IM (Telegram/WhatsApp) el comando /storyline informa del flujo actual y, para trail/full, devuelve un enlace firmado de corta duración al mismo mapa de solo lectura.

El nombre del parámetro heredado learner_visibility y sus valores hidden / completed_only siguen siendo aceptados (mapean a invisible / trail) pero están obsoletos — usa user_visibility.

Concurrencia — ¿sigue el progreso a la persona o al caso?

concurrency decide cuántas ejecuciones puede tener un mismo usuario en esta línea:

  • "user" (por defecto) — una ejecución por persona; cada conversación continúa el mismo progreso. Adecuado para currículos, incorporación, KYC: "hasta dónde ha llegado esta persona".
  • "session"una ejecución por conversación; un nuevo chat inicia un caso nuevo e independiente. Adecuado para solicitudes de licencia, tickets de soporte, flujos por producto: "hasta dónde ha llegado este caso". El mismo usuario puede ejecutar tres solicitudes de producto en tres chats, cada uno con su propio progreso y pizarra.

Coloca el estado donde corresponde: estado del caso en la pizarra (vive y muere con la ejecución — el nombre del producto, la lista de documentos de esta solicitud), hechos sobre la persona en las dimensiones de perfil (siguen al usuario entre ejecuciones y storylines — detalles de la empresa, identidad verificada). Un caso por conversación es deliberado: para abrir otro caso, abre otro chat. Cambiar concurrency afecta solo a las inscripciones futuras; las ejecuciones ya en curso mantienen su clave.

Listas de verificación, decisiones condicionadas, archivos y acciones deterministas

Cuatro capacidades a nivel de nodo convierten "la IA decide cuándo hemos terminado" en un estado acumulado y determinista:

  • checklist[{key, label}, …] en un nodo. Cada turno la plataforma marca los elementos como completados según lo que el visitante proporciona realmente (subidas, o descripciones con detalles concretos — las promesas no cuentan), y una regla de salida {"op": ">=", "left": {"ref": "checklist"}, "right": {"value": 1}} avanza cuando todo está marcado. El mapa de solo lectura muestra al usuario una lista viva ✓/○. Esta es la forma adecuada para flujos de solicitud/aprobación: el paso 1 anuncia lo que se necesita, el paso 2 recopila elemento por elemento mediante la lista de verificación.
  • choices_offer: "on_ready" — ritmo estilo juego para los botones de elección: permanecen ocultos (y la coincidencia por texto está desactivada — no se puede saltar escribiendo la palabra del botón) hasta que el paso esté completo — lista de verificación terminada, o se juzga verdadero un choices_ready_criteria que proporciones. Usa user_choice para decisiones genuinas entre alternativas; un único botón "continuar" es una señal de alerta.
  • {"ref": "files"} en reglas de salida — el número de archivos/imágenes subidas mientras se está en este nodo (se reinicia en la transición). files >= 2 es un umbral completamente determinista de "documentos recibidos".
  • questions — chips de rompehielos por nodo (máx. 6): las preguntas que el usuario probablemente haría en este paso, mostradas como sugerencias seleccionables mientras está en él. Combínalo con on_enter_opening para que cada paso se presente y ofrezca una vía de entrada — un usuario nunca debería preguntarse "qué se supone que debo hacer aquí".
  • on_enter_actions / on_complete_actions[{tool, args}] la plataforma ejecuta de forma determinista cuando se entra en el paso / se completa el flujo (p. ej. archivar el lead con mcp__agent4__submit_lead en el paso terminal). Los argumentos de cadena interpolan claves de dimensión y pizarra con plantillas de llaves. Los errores se registran y nunca rompen el chat.

El contexto se mantiene plano sin importar lo larga que sea la storyline: cada turno inyecta solo el nodo actual (tarea, recursos, opciones), las dimensiones de perfil y una pizarra de tamaño limitado — nunca el grafo completo ni los pasos anteriores. Los viajes largos (un año escolar, un arco de juego de toda la temporada) deben encadenarse como storylines (on_complete: goto_next): la pizarra de cada línea comienza de nuevo mientras las dimensiones de perfil se mantienen, lo cual es exactamente "resumir el pasado, mantener el presente tal cual".

El juez de salida ahora ve una ventana de conversación reciente y el estado recopilado, no solo el último mensaje — pero mantén ai_criteria sobre lo que el visitante dijo o hizo; el mecanismo de lista de verificación anterior sigue siendo más fuerte que cualquier criterio textual.

Errores de diseño — cada uno de estos ha producido un flujo atascado en producción

Tú (el que construye el agente) eres el autor más probable de estos errores. Comprueba cada uno antes de publicar:

  1. Una salida rule necesita un escritor. readiness >= 100 es un callejón sin salida a menos que algo escriba realmente readiness: una writes de la salida (determinista — preferido), profile_writes de un nodo con source: "ai" (puntuado a partir de la conversación), otra storyline o ediciones manuales en la consola. validate_storyline ahora marca esto como warn.rule_unwritten_dim — trata esa advertencia como un error a menos que sepas que existe un escritor externo. Este error exacto se envió una vez: una recolección de datos de tres pasos cuyo segundo paso condicionaba en una dimensión que nadie escribía; los usuarios nunca podían superarlo.
  2. Las dimensiones puntuadas por IA casi nunca alcanzan límites exactos. Si la dimensión es puntuada por el modelo, >= 100 (o == max) prácticamente nunca se dispara — los modelos puntúan de forma conservadora. Condiciona en un umbral realista (>= 70), o haz que la finalización del paso sea una user_choice y usa las writes de la salida para establecer el valor de forma determinista.
  3. user_choice coincide exactamente con el texto del botón — y la etiqueta debe decir qué hace. El mensaje del visitante debe ser igual a button_text. En las líneas visibles el widget renderiza estos como botones reales, así que escribe frases verbales completas y precisas — "Start document collection", no "Start" (¿comenzar qué? — feedback real de las pruebas). Mantenlos distintos y en el lenguaje de la audiencia. En las líneas invisible no hay botones — repite las opciones en la task del nodo. Prefiere user_choice para decisiones genuinas (qué rama, enviar vs. seguir editando); "he terminado este paso" es trabajo de las salidas de IA/reglas, no de un botón.
  4. Publicar no toca las ejecuciones ya en curso. Las inscripciones se fijan a la revisión en la que comenzaron — una publicación de corrección de errores solo llega a las ejecuciones nuevas. Para mover a los usuarios existentes, llama a POST /storylines/{id}/enrollments/migrate (reset de vuelta a la entrada o move a un nodo — ambas vuelven a fijar la ejecución a la revisión publicada actual).
  5. Recorre la línea como usuario antes de entregarla. Abre la página /s/ del enlace compartido, entra en el flujo, haz clic en cada botón y rama hasta el final. La simulación de ejecución del editor simula el grafo; solo la página real ejerce los mensajes de apertura, botones, visibilidad y finalización juntos.

Las salidas están ordenadas por prioridad (orden de la lista): las deterministas rule / user_choice / callback se juzgan primero, ai al final. Construye if/else, bucles de reintento y uniones AND a partir de salidas deterministas — no apuestes por el LLM. Edita un borrador con update_storyline (semántica PUT; mantén cada node_key estable, ya que las salidas y el embudo lo referencian).

Informa de vuelta. Devuelve el enlace de consola de la Storyline publicada — https://console.agent4.io/#/storylines/<id> (el id de create_storyline) — con un resumen de una línea del flujo y cómo un usuario entra en él.