Agentes y flujos de trabajo

Crea y gestiona agentes, y programa, ejecuta y supervisa tareas de flujo de trabajo con la API REST.

10 min de lectura · Actualizado el 28 de septiembre de 2026

Un agente es un asistente guardado: un prompt de sistema, un modelo, las herramientas integradas que puede usar, servidores MCP remotos, bases de conocimiento y archivos. Una tarea de flujo de trabajo es una ejecución de IA desatendida: unas instrucciones fijas que se envían a un modelo según una programación cron o bajo demanda, y cada ejecución queda registrada. Esta es la parte de la API de Agentes y Flujos de trabajo en la aplicación.

Todas las rutas son relativas a https://api.stickyprompts.com/api/v1. Todas las solicitudes se ejecutan como el usuario propietario de la clave de API.

Convenciones

  • :id acepta tanto el ID numérico como el slug. Un valor exclusivamente numérico siempre se trata como ID.
  • Los objetos serializan sus campos base con mayúscula inicial (ID, CreatedAt, UpdatedAt, DeletedAt, que siempre es null en las filas activas); todos los demás campos están en snake_case.
  • Las listas paginadas aceptan page (1 de forma predeterminada) y size (10 de forma predeterminada), devuelven un array JSON sin envoltorio e indican los totales en los headers de respuesta X-Total-Count, X-Page y X-Page-Size.
  • Los errores tienen la forma {"error": "<message>"}. Los rechazos por guardrails y por residencia de datos añaden un código legible por máquina: {"error": "...", "code": "..."}.

Agentes

La API gestiona la configuración de un agente. Para chatear con un agente, envía su agent_id al iniciar una conversación o menciónalo con su tag (@mention): consulta Conversaciones y mensajes.

El objeto Agent

{
  "ID": 412,
  "CreatedAt": "2026-09-28T09:14:03.512Z",
  "UpdatedAt": "2026-09-28T09:14:03.512Z",
  "DeletedAt": null,
  "user_id": 88,
  "name": "Support Triage",
  "slug": "k7Xq2bd",
  "tag": "support-triage",
  "icon": "headset",
  "color": "#3B82F6",
  "description": "Classifies Northwind support tickets and drafts replies",
  "system_prompt": "You are the first-line support agent for Northwind Analytics...",
  "ai_model_id": 31,
  "ai_model": { "ID": 31, "name": "...", "...": "..." },
  "tools": [{ "name": "web_search", "use": true }],
  "knowledge_base_limit_node_ids": null,
  "world_knowledge": false,
  "knowledge_bases": [{ "ID": 7, "...": "..." }]
}
CampoTipoNotas
user_iduintEl propietario.
namestringHasta 500 caracteres.
slugstringLo genera el servidor; se puede usar como :id.
tagstringEl @handle: ^[a-z0-9][a-z0-9-_]*$, de 1 a 50 caracteres.
iconstringPor ejemplo cpu, rocket, folder, database, headset. El predeterminado es cpu.
colorstringColor hexadecimal de la paleta, por ejemplo #F59E0B (el predeterminado).
descriptionstring o nullSe muestra en la tarjeta del agente.
system_promptstringPuede estar enmascarado por los guardrails de tu espacio de trabajo.
ai_model_id, ai_modeluint, objetoEl modelo. En GET /agents, el objeto ai_model no se carga y se devuelve con valores cero: en esa ruta, lee ai_model_id.
toolsarray o null{"name", "use"}. Nombres: web_search, image_generation, video_generation, speech_generation, music_generation, remote_mcp.
knowledge_base_limit_node_idsuint[] o nullLimita la recuperación a estos nodos de la base de conocimiento.
world_knowledgeboolSi el agente puede ir más allá de sus bases de conocimiento.
mcp_servers, knowledge_bases, filesarraySe omiten cuando están vacíos; no se cargan en el endpoint de listado.
is_sharedboolSolo en GET /agents y GET /agents/:id: true cuando el agente pertenece a otra persona y lo ha compartido contigo.

POST /agents

POST /api/v1/agents

Crea un agente.

Cuerpo
name string obligatorio
No puede estar en blanco.
ai_model_id uint obligatorio
Obligatorio en la práctica. Se comprueba con la política de residencia de datos de tu espacio de trabajo para agentes. Aquí no se comprueba explícitamente que el modelo exista.
tag string opcional
El @handle. Si se omite, se deriva de name (en minúsculas, con los demás caracteres sustituidos por -, un máximo de 50 y agent como valor de reserva).
icon string opcional por defecto cpu
Nombre del icono.
color string opcional por defecto #F59E0B
Color hexadecimal.
description string opcional
Descripción de una línea.
system_prompt string opcional
La descripción del puesto del agente. Pasa por el filtro de datos sensibles de tu espacio de trabajo.
tools array opcional
[{"name", "use"}].
mcp_server_ids uint[] opcional
Servidores MCP remotos que se vinculan. Solo se vinculan los servidores de los que eres propietario; los demás se ignoran sin avisar.
knowledge_base_ids uint[] opcional
Bases de conocimiento que se vinculan. Solo se vinculan las bases a las que tienes acceso; las demás se descartan sin avisar.
file_ids uint[] opcional
Archivos que se adjuntan. Solo se adjuntan los archivos de los que eres propietario; los demás se ignoran sin avisar.
knowledge_base_limit_node_ids uint[] opcional
Limita la recuperación a estos nodos.
world_knowledge bool opcional por defecto false
Permite usar conocimiento más allá de las bases de conocimiento.
curl -X POST https://api.stickyprompts.com/api/v1/agents \
  -H "Authorization: Bearer $STICKY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support Triage",
    "tag": "support-triage",
    "icon": "headset",
    "description": "Classifies Northwind support tickets and drafts replies",
    "system_prompt": "You are the first-line support agent for Northwind Analytics. Classify each ticket, rate urgency 1-3 and draft a reply.",
    "ai_model_id": 31,
    "tools": [{ "name": "web_search", "use": false }],
    "knowledge_base_ids": [7]
  }'
import os, requests

r = requests.post(
    "https://api.stickyprompts.com/api/v1/agents",
    headers={"Authorization": f"Bearer {os.environ['STICKY_API_KEY']}"},
    json={
        "name": "Support Triage",
        "tag": "support-triage",
        "icon": "headset",
        "description": "Classifies Northwind support tickets and drafts replies",
        "system_prompt": "You are the first-line support agent for Northwind Analytics. "
                         "Classify each ticket, rate urgency 1-3 and draft a reply.",
        "ai_model_id": 31,
        "tools": [{"name": "web_search", "use": False}],
        "knowledge_base_ids": [7],
    },
)
r.raise_for_status()
agent = r.json()
print(agent["ID"], agent["tag"])
const agent = await fetch("https://api.stickyprompts.com/api/v1/agents", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.STICKY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Support Triage",
    tag: "support-triage",
    icon: "headset",
    description: "Classifies Northwind support tickets and drafts replies",
    system_prompt:
      "You are the first-line support agent for Northwind Analytics. Classify each ticket, rate urgency 1-3 and draft a reply.",
    ai_model_id: 31,
    tools: [{ name: "web_search", use: false }],
    knowledge_base_ids: [7],
  }),
}).then((r) => r.json());
console.log(agent.ID, agent.tag);

Respuesta. 201 Created con el objeto Agent (sin is_shared).

Errores. 400 en estos casos: cuerpo que no es JSON, "Agent name is required", etiqueta no válida, incumplimiento de la residencia de datos ({"error": "...", "code": "NO_ENDPOINT_AVAILABLE"}, "NO_PROVIDER_ASSIGNED" y similares) o datos sensibles en system_prompt ({"error", "code"}). 500 "Failed to create agent".

GET /agents

GET /api/v1/agents
Permiso agents_get Herramienta MCP list_agents

Lista los agentes de los que eres propietario y los compartidos contigo (directamente, a través de uno de tus equipos o con todo tu espacio de trabajo). La herramienta MCP list_agents solo devuelve tus propios agentes.

Parámetros de consulta
search string en query opcional
Busca la subcadena en name, sin distinguir mayúsculas de minúsculas.
shared string en query opcional
false: solo los agentes de los que eres propietario. true: solo los agentes de otras personas compartidos contigo. Si se omite: ambos.
usage_sort string en query opcional
Con true, ordena por número de mensajes enviados con el agente, de mayor a menor. Si no, no hay un orden explícito.
page integer en query opcional por defecto 1
Número de página.
size integer en query opcional por defecto 10
Elementos por página.

Respuesta. 200 con un array de objetos Agent, cada uno con is_shared. En esta ruta no se cargan ai_model, mcp_servers, knowledge_bases ni files.

GET /agents/:id

GET /api/v1/agents/:id
Permiso agents_get Herramienta MCP get_agent

Devuelve un agente del que eres propietario o que se ha compartido contigo, con todo cargado: ai_model, mcp_servers, knowledge_bases, files e is_shared.

Parámetros de ruta
id string en path obligatorio
ID o slug del agente.

Errores. 404 "Agent not found", 403 "You don't have access to this agent".

PATCH /agents/:id

PATCH /api/v1/agents/:id

Actualiza un agente. Solo el propietario puede actualizarlo; compartirlo no concede permisos de edición. El cuerpo acepta los mismos campos que la creación, todos opcionales: los campos omitidos o con null no cambian. name no puede estar en blanco; system_prompt pasa por el filtro de datos sensibles y ai_model_id, por la comprobación de residencia de datos.

Parámetros de ruta
id string en path obligatorio
ID o slug del agente.
Cuerpo
name string opcional
Nombre nuevo. No puede estar en blanco.
system_prompt string opcional
Prompt de sistema nuevo.
ai_model_id uint opcional
Modelo nuevo.
mcp_server_ids uint[] opcional
Si se omite, se deja como está. Cualquier array, incluido [], sustituye el conjunto completo.
knowledge_base_ids uint[] opcional
Si se omite, se deja como está. Cualquier array, incluido [], sustituye el conjunto completo.
file_ids uint[] opcional
Si se omite, se deja como está. Cualquier array, incluido [], sustituye el conjunto completo.
tag string opcional
Igual que al crear.
icon string opcional
Igual que al crear.
color string opcional
Igual que al crear.
description string opcional
Igual que al crear.
tools array opcional
Igual que al crear.
knowledge_base_limit_node_ids uint[] opcional
Igual que al crear.
world_knowledge bool opcional
Igual que al crear.

Respuesta. 200 con el objeto Agent con todo cargado (sin is_shared).

Errores. 400, 403 "You are not authorized to update this agent", 404 "Agent not found", 500.

DELETE /agents/:id

DELETE /api/v1/agents/:id

Elimina de forma lógica (soft delete) un agente del que eres propietario. Se eliminan sus vínculos con servidores MCP, bases de conocimiento y archivos; los archivos y las bases de conocimiento en sí no se eliminan.

Parámetros de ruta
id string en path obligatorio
ID o slug del agente.

Respuesta. 204 No Content. Errores. 403 "You are not authorized to delete this agent".

Tareas de flujo de trabajo

Una tarea de flujo de trabajo envía sus instructions a un modelo, sin supervisión. Así funciona una ejecución:

  • Se crea de inmediato una ejecución con status: "running"; el trabajo se hace en segundo plano.
  • Primero se comprueba la cuota del propietario (si falla, error_text: "quota exceeded: <reason>"); después se crea una conversación oculta y no interactiva con el modelo de la tarea y se envían las instructions como mensaje.
  • Se habilitan todas las herramientas integradas (web_search, image_generation, video_generation, speech_generation, music_generation) y todos los servidores MCP remotos que ha configurado el propietario. El modelo ignora las herramientas que no admite.
  • Una ejecución tiene un tiempo de espera máximo estricto de 45 minutos (error_text: "The run took too long to complete").
  • Si termina bien, la respuesta final se guarda en result_text. Las ejecuciones interrumpidas por un reinicio del servidor se marcan como error con "The run was interrupted before it could finish" y no se reanudan.

Disparadores. El único tipo de disparador es cron. No hay disparadores por webhook, por evento ni por llamada a la API: una ejecución empieza o bien con un disparador cron o bien con POST /workflow-tasks/:id/manual-run. Tampoco hay webhooks de salida, así que para saber cuándo termina hay que consultar periódicamente.

Estados de ejecución. running (en curso), success (terminada, con result_text) y error (terminada, con error_text). success y error son estados finales. pending existe como valor, pero el código de ejecución actual no lo asigna.

El objeto de la tarea de flujo de trabajo

{
  "ID": 57,
  "CreatedAt": "2026-09-28T09:20:11Z",
  "UpdatedAt": "2026-09-28T09:20:11Z",
  "DeletedAt": null,
  "user_id": 88,
  "name": "Monday pipeline digest",
  "slug": "Tq9mZr4b",
  "description": null,
  "ai_model_id": 31,
  "ai_model": { "ID": 31, "...": "..." },
  "instructions": "Summarise last week's new deals in our CRM and email the summary to the Northwind sales team.",
  "enabled": true,
  "triggers": [
    {
      "ID": 90,
      "workflow_task_id": 57,
      "type": "cron",
      "enabled": true,
      "cron_expression": "0 8 * * 1",
      "timezone": "Europe/Budapest",
      "last_triggered_at": null,
      "next_trigger_at": "2026-09-28T08:00:00+02:00"
    }
  ]
}
CampoNotas
instructionsEl prompt que se envía en cada ejecución, después del enmascaramiento de datos sensibles.
enabledLos disparadores cron de una tarea deshabilitada no se activan.
triggersSe omite cuando está vacío. Cada disparador tiene type (cron), enabled, cron_expression, timezone (IANA, UTC de forma predeterminada), last_triggered_at y next_trigger_at (null mientras el disparador está deshabilitado).
total_run_countSolo en GET /workflow-tasks/:id: el total de ejecuciones registradas.
success_rateSolo en GET /workflow-tasks/:id: la proporción de success entre las 30 ejecuciones más recientes, de 0 a 1 (0 si no hay ninguna).

POST /workflow-tasks

POST /api/v1/workflow-tasks

Crea una tarea de flujo de trabajo.

Cuerpo
name string obligatorio
No puede estar en blanco.
ai_model_id uint obligatorio
Debe existir (400 "AI model not found") y cumplir la política de residencia de datos para flujos de trabajo.
instructions string obligatorio
No puede estar en blanco. Pasa por el filtro de datos sensibles.
description string opcional
Texto libre.
enabled bool opcional por defecto true
Si los disparadores de la tarea se activan.
triggers array opcional
Solicitudes de disparador; consulta más abajo.
Solicitud de disparador
type string obligatorio
Debe ser cron. Cualquier otro valor devuelve 400 "unsupported trigger type: <x>".
cron_expression string obligatorio
Cron estándar de 5 campos: minuto, hora, día del mes, mes y día de la semana. Si no es válida, se devuelve 400 "invalid cron_expression: ...".
enabled bool opcional por defecto false
El valor predeterminado es false. Un disparador enviado sin "enabled": true se guarda deshabilitado y nunca se activa.
timezone string opcional por defecto UTC
Zona IANA, como Europe/Budapest. Si no es válida, se devuelve 400 "invalid timezone: ...".
curl -X POST https://api.stickyprompts.com/api/v1/workflow-tasks \
  -H "Authorization: Bearer $STICKY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Monday pipeline digest",
    "ai_model_id": 31,
    "instructions": "Summarise last week'"'"'s new deals in our CRM and email the summary to the Northwind sales team.",
    "triggers": [
      { "type": "cron", "enabled": true, "cron_expression": "0 8 * * 1", "timezone": "Europe/Budapest" }
    ]
  }'
import os, requests

r = requests.post(
    "https://api.stickyprompts.com/api/v1/workflow-tasks",
    headers={"Authorization": f"Bearer {os.environ['STICKY_API_KEY']}"},
    json={
        "name": "Monday pipeline digest",
        "ai_model_id": 31,
        "instructions": "Summarise last week's new deals in our CRM and email "
                        "the summary to the Northwind sales team.",
        "triggers": [{"type": "cron", "enabled": True,
                      "cron_expression": "0 8 * * 1", "timezone": "Europe/Budapest"}],
    },
)
r.raise_for_status()
print(r.json()["triggers"][0]["next_trigger_at"])
const task = await fetch("https://api.stickyprompts.com/api/v1/workflow-tasks", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.STICKY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Monday pipeline digest",
    ai_model_id: 31,
    instructions:
      "Summarise last week's new deals in our CRM and email the summary to the Northwind sales team.",
    triggers: [{ type: "cron", enabled: true, cron_expression: "0 8 * * 1", timezone: "Europe/Budapest" }],
  }),
}).then((r) => r.json());
console.log(task.ID, task.triggers[0].next_trigger_at);

Respuesta. 201 con la tarea de flujo de trabajo (sin estadísticas de ejecución).

Errores. 400 (validación, errores de disparadores, residencia de datos {"error", "code"}, datos sensibles {"error", "code"}), 500.

GET /workflow-tasks

GET /api/v1/workflow-tasks

Lista tus propias tareas de flujo de trabajo (no se pueden compartir), de la más reciente a la más antigua. Cada elemento incluye ai_model y triggers, pero no total_run_count ni success_rate.

Parámetros de consulta
search string en query opcional
Busca la subcadena en name, sin distinguir mayúsculas de minúsculas.
page integer en query opcional por defecto 1
Número de página.
size integer en query opcional por defecto 10
Elementos por página.

Respuesta. 200 con un array de objetos de tarea de flujo de trabajo.

GET /workflow-tasks/:id

GET /api/v1/workflow-tasks/:id

Devuelve una de tus tareas de flujo de trabajo con ai_model, triggers, total_run_count y success_rate.

Parámetros de ruta
id string en path obligatorio
ID o slug de la tarea de flujo de trabajo.

Errores. 404 "Workflow task not found", 403 "You don't have access to this workflow task".

PATCH /workflow-tasks/:id

PATCH /api/v1/workflow-tasks/:id

Actualiza una de tus tareas de flujo de trabajo. Todos los campos son opcionales; si se omiten, no cambian.

Parámetros de ruta
id string en path obligatorio
ID o slug de la tarea de flujo de trabajo.
Cuerpo
name string opcional
No puede estar en blanco.
description string opcional
Texto libre.
ai_model_id uint opcional
Modelo nuevo.
instructions string opcional
No puede estar en blanco.
enabled bool opcional
Al cambiar de false a true, se recalcula a partir de ese momento el next_trigger_at de todos los disparadores habilitados.
triggers array opcional
Si está presente, sustituye todo el conjunto de disparadores: los antiguos se eliminan y se desprograman. [] quita todos los disparadores.
curl -X PATCH https://api.stickyprompts.com/api/v1/workflow-tasks/57 \
  -H "Authorization: Bearer $STICKY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": false }'

Respuesta. 200 con la tarea de flujo de trabajo (con ai_model y triggers, sin estadísticas de ejecución).

Errores. 400, 403 "You are not authorized to update this workflow task", 404, 500.

DELETE /workflow-tasks/:id

DELETE /api/v1/workflow-tasks/:id

Desprograma y elimina los disparadores, y elimina de forma lógica (soft delete) la tarea y sus ejecuciones. Solo el propietario.

Parámetros de ruta
id string en path obligatorio
ID o slug de la tarea de flujo de trabajo.

Respuesta. 204 No Content.

POST /workflow-tasks/:id/manual-run

POST /api/v1/workflow-tasks/:id/manual-run

Inicia una ejecución al momento, estén o no habilitados la tarea o sus disparadores. Solo el propietario. Sin cuerpo. Devuelve 202 Accepted con la nueva ejecución mientras esta continúa en segundo plano. No hay callback: consulta GET /workflow-tasks/:id/executions hasta que el status de la ejecución sea success o error.

Parámetros de ruta
id string en path obligatorio
ID o slug de la tarea de flujo de trabajo.
curl -X POST https://api.stickyprompts.com/api/v1/workflow-tasks/57/manual-run \
  -H "Authorization: Bearer $STICKY_API_KEY"

# Then poll the run history until the execution is success or error
curl "https://api.stickyprompts.com/api/v1/workflow-tasks/57/executions?page=1&size=5" \
  -H "Authorization: Bearer $STICKY_API_KEY"
import os, time, requests

BASE = "https://api.stickyprompts.com/api/v1"
H = {"Authorization": f"Bearer {os.environ['STICKY_API_KEY']}"}

run = requests.post(f"{BASE}/workflow-tasks/57/manual-run", headers=H).json()
while True:
    time.sleep(10)
    executions = requests.get(f"{BASE}/workflow-tasks/57/executions",
                              headers=H, params={"page": 1, "size": 10}).json()
    ex = next((e for e in executions if e["ID"] == run["ID"]), None)
    if ex and ex["status"] in ("success", "error"):
        print(ex["status"], ex["result_text"] or ex["error_text"])
        break
const BASE = "https://api.stickyprompts.com/api/v1";
const headers = { Authorization: `Bearer ${process.env.STICKY_API_KEY}` };

const run = await fetch(`${BASE}/workflow-tasks/57/manual-run`, { method: "POST", headers }).then((r) => r.json());
for (;;) {
  await new Promise((r) => setTimeout(r, 10_000));
  const executions = await fetch(`${BASE}/workflow-tasks/57/executions?page=1&size=10`, { headers }).then((r) => r.json());
  const ex = executions.find((e) => e.ID === run.ID);
  if (ex && (ex.status === "success" || ex.status === "error")) {
    console.log(ex.status, ex.result_text ?? ex.error_text);
    break;
  }
}

Respuesta. 202 Accepted:

{
  "ID": 1203,
  "CreatedAt": "2026-09-28T09:31:00Z",
  "UpdatedAt": "2026-09-28T09:31:00Z",
  "DeletedAt": null,
  "workflow_task_id": 57,
  "trigger_type": null,
  "conversation_context_id": null,
  "status": "running",
  "started_at": "2026-09-28T09:31:00Z",
  "finished_at": null,
  "result_text": null,
  "error_text": null
}

Aquí conversation_context_id es null porque la conversación oculta se vincula un momento después.

Errores. 404, 403 "You are not authorized to run this workflow task", 500 "Failed to start workflow run". Los fallos de cuota y de modelo no hacen fallar la llamada HTTP; aparecen más tarde como status: "error" en la ejecución.

GET /workflow-tasks/:id/executions

GET /api/v1/workflow-tasks/:id/executions

Devuelve el historial de ejecuciones de una tarea, de la más reciente a la más antigua. Solo el propietario.

Parámetros de ruta
id string en path obligatorio
ID o slug de la tarea de flujo de trabajo.
Parámetros de consulta
page integer en query opcional por defecto 1
Número de página.
size integer en query opcional por defecto 10
Elementos por página.

Respuesta. 200 con un array de ejecuciones. trigger_type es null en una ejecución manual y "cron" en una programada. result_text se devuelve como HTML renderizado.

[
  {
    "ID": 1203,
    "workflow_task_id": 57,
    "trigger_type": null,
    "conversation_context_id": 88123,
    "status": "success",
    "started_at": "2026-09-28T09:31:00Z",
    "finished_at": "2026-09-28T09:32:14Z",
    "result_text": "<p>Last week 4 new deals were created...</p>",
    "error_text": null
  }
]