Agentes y flujos de trabajo
Crea y gestiona agentes, y programa, ejecuta y supervisa tareas de flujo de trabajo con la API REST.
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
:idacepta tanto elIDnumérico como elslug. 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 esnullen las filas activas); todos los demás campos están en snake_case. - Las listas paginadas aceptan
page(1de forma predeterminada) ysize(10de forma predeterminada), devuelven un array JSON sin envoltorio e indican los totales en los headers de respuestaX-Total-Count,X-PageyX-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, "...": "..." }]
}
| Campo | Tipo | Notas |
|---|---|---|
user_id | uint | El propietario. |
name | string | Hasta 500 caracteres. |
slug | string | Lo genera el servidor; se puede usar como :id. |
tag | string | El @handle: ^[a-z0-9][a-z0-9-_]*$, de 1 a 50 caracteres. |
icon | string | Por ejemplo cpu, rocket, folder, database, headset. El predeterminado es cpu. |
color | string | Color hexadecimal de la paleta, por ejemplo #F59E0B (el predeterminado). |
description | string o null | Se muestra en la tarjeta del agente. |
system_prompt | string | Puede estar enmascarado por los guardrails de tu espacio de trabajo. |
ai_model_id, ai_model | uint, objeto | El modelo. En GET /agents, el objeto ai_model no se carga y se devuelve con valores cero: en esa ruta, lee ai_model_id. |
tools | array o null | {"name", "use"}. Nombres: web_search, image_generation, video_generation, speech_generation, music_generation, remote_mcp. |
knowledge_base_limit_node_ids | uint[] o null | Limita la recuperación a estos nodos de la base de conocimiento. |
world_knowledge | bool | Si el agente puede ir más allá de sus bases de conocimiento. |
mcp_servers, knowledge_bases, files | array | Se omiten cuando están vacíos; no se cargan en el endpoint de listado. |
is_shared | bool | Solo en GET /agents y GET /agents/:id: true cuando el agente pertenece a otra persona y lo ha compartido contigo. |
POST /agents
/api/v1/agents Crea un agente.
-
namestring obligatorio - No puede estar en blanco.
-
ai_model_iduint 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.
-
tagstring opcional - El
@handle. Si se omite, se deriva dename(en minúsculas, con los demás caracteres sustituidos por-, un máximo de 50 yagentcomo valor de reserva). -
iconstring opcional por defectocpu - Nombre del icono.
-
colorstring opcional por defecto#F59E0B - Color hexadecimal.
-
descriptionstring opcional - Descripción de una línea.
-
system_promptstring opcional - La descripción del puesto del agente. Pasa por el filtro de datos sensibles de tu espacio de trabajo.
-
toolsarray opcional [{"name", "use"}].-
mcp_server_idsuint[] 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_idsuint[] 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_idsuint[] 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_idsuint[] opcional - Limita la recuperación a estos nodos.
-
world_knowledgebool opcional por defectofalse - 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
/api/v1/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.
-
searchstring en query opcional - Busca la subcadena en
name, sin distinguir mayúsculas de minúsculas. -
sharedstring 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_sortstring 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. -
pageinteger en query opcional por defecto1 - Número de página.
-
sizeinteger en query opcional por defecto10 - 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
/api/v1/agents/:id 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.
-
idstring 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
/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.
-
idstring en path obligatorio - ID o slug del agente.
-
namestring opcional - Nombre nuevo. No puede estar en blanco.
-
system_promptstring opcional - Prompt de sistema nuevo.
-
ai_model_iduint opcional - Modelo nuevo.
-
mcp_server_idsuint[] opcional - Si se omite, se deja como está. Cualquier array, incluido
[], sustituye el conjunto completo. -
knowledge_base_idsuint[] opcional - Si se omite, se deja como está. Cualquier array, incluido
[], sustituye el conjunto completo. -
file_idsuint[] opcional - Si se omite, se deja como está. Cualquier array, incluido
[], sustituye el conjunto completo. -
tagstring opcional - Igual que al crear.
-
iconstring opcional - Igual que al crear.
-
colorstring opcional - Igual que al crear.
-
descriptionstring opcional - Igual que al crear.
-
toolsarray opcional - Igual que al crear.
-
knowledge_base_limit_node_idsuint[] opcional - Igual que al crear.
-
world_knowledgebool 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
/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.
-
idstring 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 lasinstructionscomo 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 comoerrorcon"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"
}
]
}
| Campo | Notas |
|---|---|
instructions | El prompt que se envía en cada ejecución, después del enmascaramiento de datos sensibles. |
enabled | Los disparadores cron de una tarea deshabilitada no se activan. |
triggers | Se 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_count | Solo en GET /workflow-tasks/:id: el total de ejecuciones registradas. |
success_rate | Solo 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
/api/v1/workflow-tasks Crea una tarea de flujo de trabajo.
-
namestring obligatorio - No puede estar en blanco.
-
ai_model_iduint obligatorio - Debe existir (
400 "AI model not found") y cumplir la política de residencia de datos para flujos de trabajo. -
instructionsstring obligatorio - No puede estar en blanco. Pasa por el filtro de datos sensibles.
-
descriptionstring opcional - Texto libre.
-
enabledbool opcional por defectotrue - Si los disparadores de la tarea se activan.
-
triggersarray opcional - Solicitudes de disparador; consulta más abajo.
-
typestring obligatorio - Debe ser
cron. Cualquier otro valor devuelve400 "unsupported trigger type: <x>". -
cron_expressionstring 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: ...". -
enabledbool opcional por defectofalse - El valor predeterminado es false. Un disparador enviado sin
"enabled": truese guarda deshabilitado y nunca se activa. -
timezonestring opcional por defectoUTC - Zona IANA, como
Europe/Budapest. Si no es válida, se devuelve400 "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
/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.
-
searchstring en query opcional - Busca la subcadena en
name, sin distinguir mayúsculas de minúsculas. -
pageinteger en query opcional por defecto1 - Número de página.
-
sizeinteger en query opcional por defecto10 - Elementos por página.
Respuesta. 200 con un array de objetos de tarea de flujo de trabajo.
GET /workflow-tasks/:id
/api/v1/workflow-tasks/:id Devuelve una de tus tareas de flujo de trabajo con ai_model, triggers, total_run_count y success_rate.
-
idstring 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
/api/v1/workflow-tasks/:id Actualiza una de tus tareas de flujo de trabajo. Todos los campos son opcionales; si se omiten, no cambian.
-
idstring en path obligatorio - ID o slug de la tarea de flujo de trabajo.
-
namestring opcional - No puede estar en blanco.
-
descriptionstring opcional - Texto libre.
-
ai_model_iduint opcional - Modelo nuevo.
-
instructionsstring opcional - No puede estar en blanco.
-
enabledbool opcional - Al cambiar de
falseatrue, se recalcula a partir de ese momento elnext_trigger_atde todos los disparadores habilitados. -
triggersarray 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
/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.
-
idstring en path obligatorio - ID o slug de la tarea de flujo de trabajo.
Respuesta. 204 No Content.
POST /workflow-tasks/:id/manual-run
/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.
-
idstring 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"])
breakconst 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
/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.
-
idstring en path obligatorio - ID o slug de la tarea de flujo de trabajo.
-
pageinteger en query opcional por defecto1 - Número de página.
-
sizeinteger en query opcional por defecto10 - 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
}
]
Contenido relacionado
- Conversaciones y mensajes - chatea con un agente mediante
agent_ido una@tag. - Integraciones - las conexiones de CRM, correo electrónico y bases de datos que puede usar un flujo de trabajo.
- Referencia de herramientas de MCP -
list_agents,get_agent,list_workflow_tasks,get_workflow_task,run_workflow_task.