Saltearse al contenido

Llamar a un flujo por API

Un flujo con una versión desplegada se puede ejecutar desde cualquier aplicación con una petición HTTP. La forma recomendada es lanzarlo en segundo plano y consultar después su estado: la petición responde al momento y tu aplicación no se queda esperando con la conexión abierta. Esta página explica cómo hacerlo, qué devuelve cada paso y cómo saber en qué punto está una ejecución. Los ejemplos son respuestas reales, recortadas para que se lean mejor.

La ventana Acceso a API del flujo genera el código de la llamada con tu flujo, tu clave y tu servidor ya puestos. Qué pestañas aparecen en ella depende de los componentes del flujo: lo explica Publicar un flujo.

Antes de empezar

  • Una versión desplegada. Las llamadas ejecutan la versión desplegada, no el borrador que ves en el editor. Si cambias el flujo, despliega una versión nueva para que las llamadas la usen. Ver Versiones y publicación. La única excepción es la ejecución de prueba.
  • Una clave API. Va en la cabecera x-api-key. Ver Claves API.
  • El identificador del flujo. Es el que aparece en la URL del editor y en el código de Acceso a API. Los flujos se llaman siempre por su identificador, no por su nombre.

Todas las rutas empiezan por https://TU-SERVIDOR/api/v1/. En el código de Acceso a API ya aparece la dirección de tu servidor.

Qué llamada usar

Quieres…Llama a
Ejecutar el flujo y recoger el resultadoPOST /background_run/{flow_id} y después su estado
Ir mostrando la respuesta mientras se escribeLo mismo, con el streaming activado
Que otro servicio lo dispare al ocurrir algoPOST /webhook/{flow_id}
Probar el borrador sin desplegarloPOST /test_run/{flow_id}
Detener una ejecución en marchaPOST /run/{task_id}/cancel

Lanzar la ejecución

Ventana de terminal
curl -X POST "https://TU-SERVIDOR/api/v1/background_run/FLOW_ID" \
-H "x-api-key: TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{"input_value": "Hola, ¿tenéis hueco para un corte el viernes por la tarde?", "session_id": "cliente-42"}'

La respuesta llega al momento, con el identificador de la ejecución y la dirección donde consultar su estado:

{
"taskid": "98bd2e8a-0539-46a2-9e97-665a286d4351",
"message": "Flow execution started.",
"statusurl": "/api/v1/background_run/98bd2e8a-0539-46a2-9e97-665a286d4351/status"
}

El taskid es también el identificador de la ejecución en el registro de ejecuciones.

El cuerpo de la petición

Todos los campos son opcionales.

CampoQué hace
input_valueEl texto de entrada, lo que escribiría el usuario en el chat.
session_idIdentifica la conversación. Usa el mismo valor en cada mensaje de un mismo usuario para que el flujo recuerde lo anterior. Si no lo envías, NappAI genera uno nuevo y lo devuelve en el resultado.
conversation_idAgrupa los mensajes en la vista de conversaciones. Por defecto, el mismo valor que session_id.
tweaksCambia campos de los componentes solo para esta llamada. Ver Cambiar campos en una llamada.
filesIdentificadores de ficheros ya subidos a la conversación.
input_typechat (por defecto), text o any.
output_typeQué salidas devuelve: chat (por defecto, los Chat Output), text, any (todas las salidas) o debug (todos los componentes).

Consultar el estado

Haz un GET a la statusurl, por ejemplo cada segundo o cada pocos segundos, hasta que llegue a un estado final:

Ventana de terminal
curl "https://TU-SERVIDOR/api/v1/background_run/98bd2e8a-0539-46a2-9e97-665a286d4351/status"
EstadoQué significa¿Final?
queuedEn cola: ningún servidor la ha empezado todavía.No
runningSe está ejecutando.No
pausedEstá esperando a que termine una llamada o a que alguien responda una aprobación. Después continúa sola, con el mismo identificador.No
doneTerminó. El resultado va en result.Sí
errorFalló. El motivo va en message.Sí
cancelledSe canceló.Sí
not foundNo existe ninguna ejecución con ese identificador.Sí

El estado va en el campo status. Así evoluciona una ejecución normal:

{ "status": "queued", "message": "Task is waiting in the queue for a worker" }
{ "status": "running" }
{ "status": "done", "result": { "session_id": "cliente-42", "outputs": [ … ] } }

Una en pausa trae lo que el flujo ha devuelto hasta ese momento y qué está esperando:

{
"status": "paused",
"paused": { "kind": "approval", "pause_id": "0ce2cdac-2e14-4b97-ba9c-7424c4790e55", "component_id": "AdvancedAgent-pq02" },
"result": { "session_id": "…", "outputs": [ … ] }
}

kind es approval (o tool_approval) cuando espera una aprobación, y outbound_call cuando espera a que termine una llamada saliente. Al reanudarse vuelve a pasar por queued y running, y termina en done.

Una que ha fallado dice qué componente falló y por qué:

{ "status": "error", "message": "Error building Component OpenAI: Error code: 401 - Incorrect API key provided", "traceback": "…" }

El resultado

Cuando el estado es done, result trae lo que devolvió el flujo:

{
"status": "done",
"result": {
"session_id": "cliente-42",
"outputs": [
{
"inputs": { "input_value": "Hola, ¿tenéis hueco para un corte el viernes por la tarde?", "files": [] },
"outputs": [
{
"results": {
"message": {
"text": "Claro, para un corte el viernes por la tarde tenemos hueco; llama al 960 000 000 y te confirmamos la hora exacta.",
"sender": "Machine",
"sender_name": "AI",
"session_id": "cliente-42",
"files": []
}
},
"artifacts": {
"message": "Claro, para un corte el viernes por la tarde tenemos hueco; llama al 960 000 000 y te confirmamos la hora exacta.",
"sender": "Machine",
"sender_name": "AI",
"files": [],
"type": "object"
},
"component_display_name": "Chat Output",
"component_id": "ChatOutput-uc3ue"
}
]
}
]
}
}

La respuesta del flujo está en result.outputs[0].outputs[0].results.message.text. Hay un elemento en outputs[0].outputs por cada componente de salida devuelto, y component_id indica cuál es cada uno.

Respuesta en stream

Para ir mostrando el texto mientras el modelo lo escribe:

  1. Activa el streaming en el componente que genera la respuesta: es el campo Stream, en las opciones avanzadas de los modelos y del Agent. También puedes activarlo solo en esta llamada con un tweak: "tweaks": {"AdvancedAgent-2jhmg": {"use_stream": true}} en un Agent, o {"stream": true} en un modelo.

  2. Lanza la ejecución y consulta su estado como siempre. Pasa a done en cuanto empieza a escribirse la respuesta, sin el texto: en su lugar trae "type": "stream" y una dirección en stream_url.

    "artifacts": {
    "message": "",
    "stream_url": "/api/v1/build/895da449-…_e55d7896-…/ChatOutput-uc3ue/streamv2",
    "type": "stream"
    }
  3. Abre esa dirección con un GET, añadiendo delante tu servidor. Devuelve un stream de eventos (text/event-stream):

    event: message
    data: {"message":"Streaming vertex ChatOutput-uc3ue"}
    event: message
    data: {"chunk":"Tenemos corte de pelo por 18 €, color por 35 € y peinado por 15 €."}
    event: close
    data: {"message":"Stream closed"}
EventoQué trae
message con messageEl aviso de que empieza el stream.
message con chunkUn trozo del texto. Ve concatenándolos en orden. Según el componente, llegan muchos trozos pequeños o uno solo con todo el texto.
message con mediaUn fichero de la conversación (por ejemplo, una imagen generada).
cancelledLa ejecución se canceló.
errorAlgo falló; el motivo va en error.
closeSe acabó el stream. Puede llegar más de una vez: quédate con el primero.

Si pasan 30 segundos sin datos, llega una línea : keep-alive para que la conexión no se corte; ignórala.

Cancelar una ejecución

Ventana de terminal
curl -X POST "https://TU-SERVIDOR/api/v1/run/TASK_ID/cancel" -H "x-api-key: TU_CLAVE"
{ "status": "ok", "task_id": "7e18b6fa-3042-45ba-8b9f-43eaae93dae7", "message": "Cancellation signal sent" }

La ejecución se detiene en unos segundos y su estado pasa a cancelled:

{ "status": "cancelled", "message": "Task cancelled by user" }

Probar el borrador (test_run)

POST /test_run/{flow_id} ejecuta el borrador, lo que ves ahora en el editor, sin desplegar una versión. Acepta el mismo cuerpo y devuelve un taskid y la misma statusurl, que se consulta igual.

{ "taskid": "1a4f4e91-ca98-4c68-bd89-b7e3a2cd100c", "message": "Test run started.", "statusurl": "/api/v1/background_run/1a4f4e91-ca98-4c68-bd89-b7e3a2cd100c/status" }

Para probarlo con un entorno concreto, usa POST /test_run/{environment_id}/{flow_id}. Es lo que genera el modo Test de Acceso a API.

Webhooks

POST /webhook/{flow_id} es la dirección para que otro servicio dispare el flujo. El flujo necesita un componente Webhook Input, que recibe lo que llega en la petición:

{ "headers": { … }, "query_params": { … }, "body": { "cliente": "Ana", "input_value": "Quiero cita el sábado" } }

NappAI quita de las cabeceras y de los parámetros la clave API y las cookies antes de pasarlos al flujo.

Lo que recibe el servicio que llama depende de si el flujo tiene un componente Webhook Response:

  • Sin Webhook Response, la respuesta es inmediata (HTTP 202) y el flujo sigue en segundo plano:

    {
    "taskid": "457708c0-e188-4ad5-b428-f77fd6c5ce8c",
    "status": "Task started in the background",
    "message": "Flow execution started.",
    "statusurl": "/api/v1/webhook_task/457708c0-e188-4ad5-b428-f77fd6c5ce8c"
    }

    Su estado se consulta en statusurl, con los mismos estados.

  • Con Webhook Response, la petición espera a que el flujo termine y devuelve exactamente lo que le llega a ese componente. Úsalo solo cuando el servicio que llama necesita una respuesta concreta en la misma petición.

Los webhooks de servicios como Gmail, Outlook, Teams o Shopify no se llaman así: se publican desde el propio componente. Ver Publicar un flujo.

Cambiar campos en una llamada (tweaks)

tweaks cambia el valor de campos de los componentes solo para esa llamada, sin tocar la versión desplegada. La clave es el identificador del componente, que ves en el propio componente y en el código de Acceso a API:

{
"input_value": "Hola",
"tweaks": {
"AdvancedAgent-2jhmg": { "use_stream": true },
"TextInput-entrada": { "input_value": "Valencia" }
}
}

Solo cambian los campos que existen en ese componente. En vez del identificador también puedes poner el nombre visible del componente.

Errores al lanzarla

Si la ejecución ni siquiera empieza, la respuesta trae el motivo en message:

HTTPMensajeQué hacer
403An API key must be passed as query or headerFalta la cabecera x-api-key.
403Invalid or missing API keyLa clave no existe, se ha regenerado o va sin codificar en la URL.
429This flow reached the runs per minute of its execution profileEl flujo ha superado las ejecuciones por minuto de su perfil de ejecución. Espera y reintenta.
500Flow … not foundEl identificador no existe, el flujo no tiene versión desplegada o tu clave no tiene acceso a él.
{ "message": "Invalid or missing API key", "type": "http_error", "status_code": 403 }

Si la ejecución empieza y luego falla un componente, la petición se acepta igual: el fallo aparece después en el estado error, con el componente y el motivo, y en el registro de ejecuciones.

Buenas prácticas

  • Reutiliza el mismo session_id para todos los mensajes de un mismo usuario: así el flujo recuerda la conversación.
  • Trata queued, running y paused como “sigue en marcha”, y deja de consultar en done, error o cancelled.
  • Consulta el estado cada uno o pocos segundos; más a menudo no lo hace terminar antes.
  • Guarda la clave en el servidor de tu aplicación, nunca en el código que se ejecuta en el navegador.