Esta es una traducción automática del documento original en inglés. En caso de cualquier discrepancia entre esta traducción y la versión original en inglés, prevalecerá la versión en inglés. Leer la versión original en inglés


API pública

Caiioo incluye una API REST que te permite controlar todo mediante programación: ejecutar agentes, gestionar herramientas, programar tareas y más. La API reside en el mismo servidor local que alimenta la aplicación de escritorio y el puente del navegador.

URL base: http://localhost:3847/v1

Autenticación: Dos formas de autenticarse, ambas reguladas por el interruptor de API en los ajustes:

Para consumidores externos (scripts, integraciones, curl): Establece un token de acceso a la API en Ajustes > Acceso API, luego úsalo como un token Bearer:

curl -H \"Authorization: Bearer TU_TOKEN_API\" http://localhost:3847/v1/providers

Para la aplicación local (automático): La aplicación de escritorio de Caiioo, las extensiones de navegador y las aplicaciones móviles se autentican automáticamente a través de la cabecera de autenticación de relay existente (x-relay-auth). No requiere configuración manual; la aplicación maneja esto entre bastidores. Las solicitudes de relay-auth omiten el interruptor de "Habilitar API pública" ya que se consideran de confianza; solo las solicitudes con token bearer están reguladas por el interruptor.

Configuración:

  1. Abre Ajustes de Caiioo > Acceso API
  2. Activa Habilitar API pública
  3. Establece un token de acceso a la API (cualquier cadena que elijas; trátala como una contraseña)
  4. Usa ese token en todas las solicitudes a la API

La API está disponible en localhost y a través del relay privado. Consulta GET /v1/auth/info (no requiere autenticación) para ver el estado actual e instrucciones de configuración.

Límites de velocidad: cada solicitud a /v1/* está limitada por IP de cliente: 100 solicitudes GET por minuto para lecturas y 30 solicitudes de escritura por minuto (POST / PATCH / DELETE) combinadas. Las solicitudes que superen el límite recibirán un 429. Las entregas de webhooks (POST /v1/webhooks/:id) no requieren autenticación bearer y no están sujetas a estos límites.

Perfiles

Un solo dispositivo puede albergar múltiples perfiles de usuario (p. ej., personal + trabajo). La API permite que scripts externos inspeccionen los perfiles disponibles y cambien el perfil activo antes de realizar otras tareas. La creación, actualización y eliminación de perfiles no se exponen deliberadamente a través de la API pública; esos flujos pertenecen a la interfaz de usuario de incorporación de la aplicación.

Listar perfiles:

GET /v1/profiles

Devuelve { profiles: [...] } con una entrada por cada perfil no eliminado. Cada entrada incluye id, name, email, avatarUrl, tier, accessibleModes, license, organization, preferences, onboardingComplete, createdAt, lastAccessedAt. Los campos que contienen tokens (serviceCredentials, oauthConnections) y los internos de sincronización (vectorClock, lastModifiedBy) se eliminan. Use /v1/connectors para inspeccionar las conexiones OAuth.

Obtener el perfil activo:

GET /v1/profiles/active

Devuelve { profile } para el perfil que está utilizando actualmente este servidor. Todos los recursos /v1/* vinculados a un perfil (hilos, archivos adjuntos, ajustes, habilidades) operan contra este.

Cambiar el perfil activo:

PUT /v1/profiles/active
Content-Type: application/json

{ "profileId": "user-uuid-from-list" }

Devuelve { profile } para el nuevo perfil activo. Devuelve 404 si el ID no es un perfil conocido.

Providers & Models

Descubra qué proveedores de LLM están configurados y qué modelos están disponibles.

Listar proveedores:

GET /v1/providers

Devuelve todos los tipos de proveedores compatibles. Actualmente: anthropic, openai, google, openrouter, ollama, poe, mlx, perplexity, baseten, cloudflare. Cada entrada incluye type, displayName, icon, requiresApiKey, hasApiKey y un objeto capabilities con los indicadores (flags) que se detallan a continuación.

Indicador de capacidad Significado
supportsVision El proveedor puede aceptar entradas de imágenes
supportsPdfFile El proveedor puede aceptar bloques de contenido de archivos PDF nativos
supportsToolCalling El proveedor admite llamadas a funciones/herramientas
supportsStreaming El proveedor transmite tokens de forma incremental
supportsExtendedThinking El proveedor expone un presupuesto de razonamiento/pensamiento
supportsPromptCaching El proveedor admite directivas de almacenamiento en caché de prompts
nativeReasoningBlocks El proveedor emite el pensamiento como bloques de mensajes nativos (en lugar de texto)
requiresThoughtSignature El proveedor requiere que los tokens de pensamiento firmados se devuelvan como eco

Los indicadores de capacidad reflejan el campo readonly capabilities de cada clase de proveedor (consulte src/shared/providers/*-provider.ts) y son validados por una prueba de centinela de desviación; llame a este endpoint en tiempo de ejecución en lugar de codificar la matriz de forma fija.

Notas para los proveedores BYOK:

  • perplexity expone una lista curada de modelos Sonar (Perplexity no tiene un endpoint /models público).
  • cloudflare (AI Gateway) es BYOK + multi-proveedor; la lista de modelos se determina mediante la configuración de su gateway y el endpoint /v1/providers/cloudflare/models la devuelve como un array vacío. Utilice su propio catálogo de gateway.

Listar modelos de un proveedor:

GET /v1/providers/openrouter/models

Devuelve el catálogo de modelos para ese proveedor. Cada modelo incluye id, displayName y contextLength cuando están disponibles. Devuelve 503 cuando el proveedor carece de una API key o su catálogo ascendente (upstream) es inalcanzable.

Catálogo plano de todos los proveedores:

GET /v1/models

Combina los modelos de cada proveedor configurado en una sola lista. Los proveedores sin API keys se omiten y se enumeran en warnings.

Agentes

Los agentes son el núcleo de caiioo. Cada agente es un Modo: una personalidad configurada con su propia instrucción de sistema, herramientas, variables y skills.

Listar todos los agentes:

GET /v1/agents

Devuelve agentes integrados (Compras, Trabajo, General) y cualquier agente personalizado que hayas creado. Cada uno está etiquetado con source: \"builtin\" o source: \"custom\".

Crear un agente personalizado:

POST /v1/agents
Content-Type: application/json

{
  \"id\": \"mi-agente-de-investigacion\",
  \"branding\": {
    \"name\": \"Agente de Investigación\",
    \"description\": \"Busca en la web y resume hallazgos\"
  },
  \"defaultSettings\": {
    \"systemPrompt\": \"Eres un asistente de investigación. Cita siempre las fuentes.\",
    \"enabledTools\": { \"web_browsing\": true, \"search_tools\": true }
  },
  \"settingLevels\": {}
}

Devuelve 201 con el agente creado. Se adjunta automáticamente un vector clock para la sincronización.

Actualizar un agente:

PATCH /v1/agents/mi-agente-de-investigacion
Content-Type: application/json

{ \"branding\": { \"name\": \"Agente de Investigación\", \"description\": \"Descripción actualizada\" } }

Fusiona el parche en el agente existente y actualiza el vector clock. Los agentes integrados devuelven 403: son de solo lectura.

Eliminar un agente:

DELETE /v1/agents/mi-agente-de-investigacion

Eliminación lógica mediante tombstone (se sincroniza entre dispositivos). Devuelve 204.

Ejecución de Agentes

Este es el evento principal: invocar a un agente para procesar un mensaje.

Cuerpo de la solicitud — campos compatibles

Campo Requerido Descripción
agentId ID de modo integrado (ej. general) o un ID de agente personalizado
input.message Texto del mensaje del usuario
input.attachments no Array de IDs de adjuntos (ya subidos a través de /v1/attachments) para adjuntar a este turno
input.variables no Sobrescritura de variables por ejecución fusionadas en el resolutor de variables del agente
input.tabContext no Cadena de texto de formato libre inyectada como contexto de página (utilizada por el puente del navegador)
input.messageId no ID de mensaje proporcionado por el cliente; útil para la deduplicación si se reintenta
threadId no Hilo existente para continuar. Si se omite, se crea y devuelve un nuevo hilo
mode no "sync" o "async". Por defecto es "async"

Modo Síncrono

Espere la respuesta completa:

POST /v1/runs
Content-Type: application/json

{
  "agentId": "general",
  "input": { "message": "What's the weather in Paris today?" },
  "mode": "sync"
}

Devuelve 200 con { content, usage, status: "completed" } después de que el agente termina. Si el agente presenta un error, devuelve 500 con { error, status: "error" }. Las ejecuciones síncronas agotan el tiempo de espera (timeout) después de 5 minutos con status: "error" si no se recibe un evento terminal; use async + SSE para cualquier tarea que pueda tardar más.

Modo Asíncrono

Ejecutar y olvidar: útil para tareas de larga duración:

POST /v1/runs
Content-Type: application/json

{
  "agentId": "my-research-agent",
  "input": { "message": "Write a 2000-word analysis of renewable energy trends" },
  "mode": "async"
}

Devuelve 202 inmediatamente con { runId, threadId, status: "running" }.

Consultar estado (Polling):

GET /v1/runs/{runId}

Devuelve { run: { runId, threadId, agentId, status, createdAt, content?, usage?, error? } }. El estado es uno de los siguientes: running, completed, error, o cancelled.

Transmitir eventos en tiempo real (SSE):

GET /v1/runs/{runId}/events

Devuelve un text/event-stream con cada evento del agente a medida que ocurre: GENERATION_STARTED, STREAMING_CONTENT, llamadas a herramientas, actividad de subagentes y el evento terminal (GENERATION_COMPLETE, GENERATION_ERROR, o GENERATION_CANCELLED).

Después del evento terminal, el servidor emite un último frame SSE con event: terminal y una carga de datos vacía como centinela explícito de fin de flujo, y luego cierra la conexión. Los clientes deben tratar la recepción de ese frame (o el cierre de la conexión) como la señal para dejar de leer.

Si se suscribe después de que la ejecución ya haya finalizado, el servidor reproduce un frame de tipo RUN_SNAPSHOT que contiene el record final completo, seguido del centinela event: terminal, y luego cierra la conexión.

Cancelar una ejecución:

POST /v1/runs/{runId}/cancel

Devuelve { run: { ..., status: "cancelled" } }.

Threads

Los Threads son conversaciones. Cada ejecución de un agente ocurre dentro de un thread, y los threads persisten a través de las sesiones. La API le permite listar, leer, crear y gestionar threads de forma programática.

Listar todos los threads (solo metadatos):

GET /v1/threads

Devuelve { threads: [...] } para el perfil actual con los messages eliminados (use el endpoint de detalle cuando los necesite). Todos los demás campos se conservan: id, title, createdAt, updatedAt, modeId, archived, estadísticas de uso, además de subAgentHistories, anonymizerSnapshot, threadToolApprovals, threadVariables, threadToolOverrides, messagingBinding, scheduledTaskId cuando estén configurados. (El payload más completo es exclusivo de la API; la transmisión de la barra lateral por WebSocket utiliza un recorte más estricto para mantenerse bajo los límites de transporte).

Obtener un thread con los mensajes completos:

GET /v1/threads/{id}

Devuelve el thread completo incluyendo su array de messages: cada mensaje del usuario, respuesta del asistente, llamada a herramientas (tool call) y resultado de herramientas (tool result).

Obtener solo los mensajes:

GET /v1/threads/{id}/messages

Devuelve solo el array de messages; es más ligero que el objeto de thread completo cuando solo necesita la conversación.

Crear un thread:

POST /v1/threads
Content-Type: application/json

{ "title": "Research project", "modeId": "general" }

Devuelve 201 con { thread }. El nuevo thread aparece en la barra lateral inmediatamente (vía transmisión por WebSocket). La API nunca cambia el thread activo de la aplicación al crear uno; llame a PUT /v1/threads/active por separado si desea eso.

Actualizar un thread:

PATCH /v1/threads/{id}
Content-Type: application/json

{ "title": "Renamed project", "archived": true }

Campos actualizables: title, modeId, archived, lastUsedModel. Los cambios se transmiten a la barra lateral en tiempo real.

Eliminar un thread:

DELETE /v1/threads/{id}

Realiza un borrado lógico (soft-delete) del thread (tombstone para sincronización). Devuelve 204. Los threads eliminados se mueven a la papelera y pueden recuperarse hasta que la papelera se vacíe.

Thread activo:

GET /v1/threads/active            # Devuelve { threadId }
PUT /v1/threads/active            # Cuerpo: { "threadId": "..." }

Gestión de la papelera:

GET /v1/threads/trash/count       # Devuelve { count }
POST /v1/threads/trash/empty      # Devuelve { deletedCount, protectedCount }

Los threads protegidos (retenidos mediante el interruptor de retención de datos) se excluyen del vaciado de la papelera.

Continuar una conversación a través de la API: Para enviar un mensaje de seguimiento a un thread existente, use POST /v1/runs con el ID del thread:

POST /v1/runs
Content-Type: application/json

{
  "agentId": "general",
  "threadId": "existing-thread-id",
  "input": { "message": "Follow up on that last point" },
  "mode": "sync"
}

El agente ve el historial completo de la conversación del thread.

Adjuntos

Los adjuntos son archivos vinculados a hilos: capturas de pantalla, PDFs, documentos, imágenes subidas, artefactos generados. La API le permite listarlos, subirlos, descargarlos y gestionarlos.

Listar todos los adjuntos (solo metadatos):

GET /v1/attachments

Devuelve metadatos de adjuntos para el perfil actual. Los campos pesados (dataUrl, extractedContent, extractedImages) se eliminan; use los puntos de conexión de detalle o contenido para ellos.

Listar adjuntos para un hilo específico:

GET /v1/threads/{threadId}/attachments

Obtener metadatos de un adjunto:

GET /v1/attachments/{id}

Devuelve los metadatos completos, incluyendo extractedContent (texto OCR, markdown analizado), contentType, fileName, size y un indicador hasContent. El binario original NO se incluye; use el punto de conexión /content para eso.

Descargar binario de adjunto:

GET /v1/attachments/{id}/content

Devuelve el archivo original con las cabeceras Content-Type y Content-Disposition correctas. Redirija esto a un archivo:

curl -o salida.pdf \
  -H "Authorization: Bearer $API_TOKEN" \
  http://localhost:3847/v1/attachments/{id}/content

Subir un adjunto:

POST /v1/attachments
Content-Type: application/json

{
  "threadId": "id-del-hilo",
  "type": "user_upload",
  "contentType": "application/pdf",
  "fileName": "informe.pdf",
  "description": "Informe trimestral",
  "dataUrl": "data:application/pdf;base64,JVBERi0xLjQ..."
}

El dataUrl es una URL de datos codificada en base64. Devuelve 201 con el nuevo ID del adjunto. El adjunto queda vinculado al hilo especificado.

Actualizar metadatos de adjunto:

PATCH /v1/attachments/{id}
Content-Type: application/json

{ "description": "Descripción actualizada", "fileName": "nuevo-nombre.pdf" }

Eliminar un adjunto:

DELETE /v1/attachments/{id}

Eliminación lógica mediante lápida. Devuelve 204.

Servidores MCP

Administre sus conexiones de servidor MCP (Model Context Protocol) — los servidores que brindan a los agentes acceso a herramientas externas y fuentes de datos.

Listar servidores configurados:

GET /v1/mcp-servers

Devuelve todas las configuraciones de servidores MCP para el perfil actual. Los campos sensibles (authToken, env, credentialId) se eliminan de la respuesta.

Obtener la configuración de un servidor:

GET /v1/mcp-servers/{id}

Agregar un nuevo servidor MCP:

POST /v1/mcp-servers
Content-Type: application/json

{
  "id": "my-server",
  "name": "My MCP Server",
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/files"],
  "serverType": "local"
}

Para servidores HTTP remotos, use "url" en lugar de "command":

{
  "id": "remote-server",
  "name": "Remote API",
  "url": "https://my-mcp-server.example.com/sse",
  "serverType": "remote"
}

Campos opcionales aceptados en POST: command, args, env, url, description, transportType, authType, authToken, authHeader, headers, specType, specPath, timeoutMs, credentialId, oauthConnectionId, approval. Los campos gestionados por el servidor (customOAuth, hubPackageId, profileId, connectorId, teamPublished, teamOrgId, vectorClock, ...) no pueden establecerse a través de la API.

Actualizar un servidor:

PATCH /v1/mcp-servers/{id}
Content-Type: application/json

{ "name": "Renamed Server", "args": ["-y", "@mcp/server-v2"] }

Los campos modificables mediante Patch coinciden con la lista permitida de POST (incluyendo credentialId y oauthConnectionId — útil para rotar una conexión OAuth sin tener que eliminar y volver a crear). Los campos gestionados por el servidor permanecen como solo lectura.

Activar/desactivar un servidor:

POST /v1/mcp-servers/{id}/toggle
Content-Type: application/json

{ "enabled": false }

Eliminar un servidor:

DELETE /v1/mcp-servers/{id}

Gestión de Procesos

Para servidores MCP locales (stdio), puede gestionar el proceso del servidor directamente.

Listar procesos en ejecución:

GET /v1/mcp-servers/processes

Devuelve los procesos del servidor en ejecución con pid, startedAt y el estado running.

Iniciar un servidor:

POST /v1/mcp-servers/{id}/start

Lee el comando/args/env de la configuración del servidor y genera el proceso. Devuelve el estado del proceso.

Detener un servidor:

POST /v1/mcp-servers/{id}/stop

Cierra de forma controlada el proceso del servidor (SIGTERM con recurso de reserva a SIGKILL).

Llamar a un método JSON-RPC directamente:

POST /v1/mcp-servers/{id}/call
Content-Type: application/json

{ "method": "tools/list", "params": {} }

Envía una solicitud JSON-RPC 2.0 sin procesar al servidor y devuelve el resultado. Útil para depuración o para llamar a métodos que no están expuestos a través de la API de herramientas.

Tools & Toolkits

Explore e invoque las herramientas que utilizan los agentes: navegación web, búsqueda, calendario, Gmail, Slate y más.

Listar toolkits (agrupados):

GET /v1/toolkits

Devuelve las herramientas integradas agrupadas por categoría (Productivity, Search, Utilities, etc.) y cualquier servidor MCP conectado como toolkits independientes, cada uno con sus acciones listadas.

Listar todas las herramientas (lista plana):

GET /v1/tools
GET /v1/tools?source=embedded   # Solo herramientas integradas
GET /v1/tools?source=mcp        # Solo herramientas de servidores MCP

Obtener detalles de la herramienta con esquema de entrada:

GET /v1/tools/calculator

Devuelve { tool: { name, displayName, description, source, category, inputSchema, actions?, requiredTier?, requiredRuntimes?, riskTier?, riskExplanation?, requiresApproval? } }.

Campo Significado
inputSchema JSON Schema para la entrada de la herramienta — validar antes de invocar
actions Sub-acciones opcionales (ej. Slate read/write); cada una tiene id, displayName, description, requiredTier opcional
requiredTier Nivel mínimo de usuario (free si se omite). La invocación vía API pública rechaza cualquier nivel superior a free
requiredRuntimes Plataformas donde esta herramienta está disponible (macos, ios, etc.); omitir ⇒ en todas partes
riskTier Riesgo de consentimiento: low (predeterminado), medium, high
riskExplanation Razón legible por humanos por la cual el riskTier es elevado
requiresApproval true cuando la herramienta necesita aprobación del usuario por cada llamada — la invocación vía API pública las rechaza

Invocar una herramienta directamente:

POST /v1/tools/calculator/invoke
Content-Type: application/json

{ "input": { "expression": "sqrt(144) + 3^2" }, "threadId": "optional-thread-id" }

Devuelve { result }. La entrada se valida contra el esquema de la herramienta — una entrada inválida devuelve 422 con detalles. Pase un threadId opcional si la herramienta necesita contexto con alcance de hilo (ej. búsquedas de archivos adjuntos).

Restricciones — lo que la API pública rechaza:

  • Herramientas restringidas por nivel (metadata.requiredTier !== 'free') → 403. El bucle del agente verifica el nivel contra la sesión del usuario; la API pública no tiene un contexto de nivel transferido, por lo que la política conservadora es rechazar. En su lugar, use POST /v1/runs con un agente que tenga el nivel adecuado.
  • Herramientas que requieren aprobación (metadata.approval.requiresApproval === true) → 403. No hay un humano en el bucle a quien preguntar. Invoque a través de POST /v1/runs (que presenta la solicitud al usuario) o configure el modo de aprobación de herramientas en approve_all en la aplicación para omitirlo.
  • Herramientas MCP remotas501 con instrucciones para usar /v1/runs (requieren el transporte del subproceso del agente).

Herramientas de visión y uso de imágenes: cargue primero a través de POST /v1/attachments, luego pase el ID del adjunto devuelto dentro de input (ej. { "input": { "attachment_id": "att_abc", "prompt": "¿Qué hay en esta imagen?" } }). La herramienta lee el binario del almacenamiento a través de threadId; no se pasan los bytes en línea.

Conectores

Gestiona integraciones OAuth: Google, Microsoft, GitHub, Notion, Slack y más.

Explorar integraciones disponibles:

GET /v1/connectors/catalog

Devuelve todos los proveedores OAuth registrados con su nombre, categoría y alcances predeterminados.

Listar tus cuentas conectadas:

GET /v1/connectors

Devuelve las conexiones activas para el perfil actual. Los tokens nunca se exponen, solo los metadatos (proveedor, correo, estado, alcances, marcas de tiempo).

Obtener una sola conexión:

GET /v1/connectors/{id}

Devuelve metadatos de una conexión. Los tokens nunca se exponen.

Comprobar la salud de la conexión:

POST /v1/connectors/{id}/test

Devuelve { health: { status, isTokenExpired, canRefresh } }.

Eliminar una conexión:

DELETE /v1/connectors/{id}

Crear nuevas conexiones requiere el flujo interactivo de OAuth a través de la interfaz de la aplicación o las rutas /auth/*.

Disparadores

Programa agentes para que se ejecuten automáticamente: resúmenes diarios, informes semanales, monitoreo basado en intervalos.

Cada disparador tiene un discriminador kind: schedule (predeterminado: se activa por reloj), webhook (se activa cuando un servicio externo envía un POST a la ruta del webhook) o messaging (se activa desde un adaptador de mensajería conectado, por ejemplo, mensajes entrantes de Slack/Discord que coinciden con un filtro de canal).

Listar disparadores:

GET /v1/triggers

Devuelve { triggers: [...] }. Cada entrada incluye su kind, horario y campos específicos del tipo.

Obtener un solo disparador:

GET /v1/triggers/{id}

Crear un disparador programado:

POST /v1/triggers
Content-Type: application/json

{
  \"name\": \"Resumen matutino\",
  \"prompt\": \"Resume mis correos no leídos y el calendario de hoy\",
  \"modeId\": \"general\",
  \"schedule\": { \"type\": \"daily\", \"time\": \"08:00\" }
}

Tipos de horario compatibles:

  • { \"type\": \"interval\", \"minutes\": 60 } — cada N minutos (mín 15, máx 1440)
  • { \"type\": \"daily\", \"time\": \"09:00\" } — diario a una hora específica
  • { \"type\": \"weekly\", \"day\": \"mon\", \"time\": \"09:00\" } — semanal
  • { \"type\": \"weekdays\", \"time\": \"08:30\" } — de lunes a viernes
  • { \"type\": \"daysOfWeek\", \"days\": [\"mon\", \"wed\", \"fri\"], \"time\": \"10:00\" } — días específicos
  • { \"type\": \"monthly\", \"dayOfMonth\": 1, \"time\": \"09:00\" } — mensual
  • { \"type\": \"manual\" } — solo cuando se activa vía API

Activar un disparador manualmente:

POST /v1/triggers/{id}/fire

Devuelve 202 con un threadId para la ejecución resultante.

Actualizar o eliminar:

PATCH /v1/triggers/{id}
DELETE /v1/triggers/{id}

Webhooks

Los disparadores de webhook permiten que servicios externos (CI/CD, monitoreo, constructores de formularios) activen la ejecución de un agente a través de HTTP.

Crear un disparador de webhook:

POST /v1/triggers
Content-Type: application/json

{
  \"name\": \"Hook de despliegue\",
  \"prompt\": \"Ha ocurrido un despliegue: {{webhook.body}}\",
  \"modeId\": \"general\",
  \"kind\": \"webhook\"
}

Devuelve 201 con un webhookSecret y webhookPath. Guarda el secreto; lo necesitarás para firmar las cargas útiles.

Enviar un webhook:

# Calcular HMAC-SHA256 del cuerpo de la solicitud
SIGNATURE=$(echo -n '{\"repo\":\"my-app\",\"branch\":\"main\"}' | openssl dgst -sha256 -hmac \"$WEBHOOK_SECRET\" | awk '{print $2}')

POST /v1/webhooks/{triggerId}
Content-Type: application/json
X-Webhook-Signature: $SIGNATURE

{\"repo\": \"my-app\", \"branch\": \"main\"}

El punto final del webhook NO requiere autenticación bearer; utiliza verificación HMAC en su lugar. Devuelve 202 con el threadId de la ejecución enviada. El marcador {{webhook.body}} en el prompt del disparador se reemplaza con el cuerpo bruto de la solicitud.

Disparadores de mensajería

Los disparadores de mensajería se activan cuando un adaptador de mensajería conectado (por ejemplo, una integración de Slack o Discord instalada vía Community Hub) recibe un mensaje entrante que coincide con el filtro del disparador. Crear con kind: \"messaging\":

POST /v1/triggers
Content-Type: application/json

{
  \"name\": \"Respondedor de menciones\",
  \"prompt\": \"Responde amablemente a: {{message.text}}\",
  \"modeId\": \"general\",
  \"kind\": \"messaging\",
  \"messagingAdapterId\": \"slack-team-acme\",
  \"messagingChannelFilter\": \"#support\"
}

El adaptador es responsable de enviar los eventos coincidentes al disparador; messagingChannelFilter es específico del adaptador.

Funciones Personalizadas

Cree sus propias herramientas que los agentes puedan llamar. Las funciones se escriben en JavaScript o Python y se ejecutan en un entorno seguro (sandbox).

Listar funciones:

GET /v1/functions

Crear una función:

POST /v1/functions
Content-Type: application/json

{
  "name": "calcular_imc",
  "description": "Calcular el Índice de Masa Corporal a partir de la altura y el peso",
  "language": "javascript",
  "source": "return { imc: (input.weightKg / (input.heightM * input.heightM)).toFixed(1) };",
  "inputSchema": {
    "type": "object",
    "properties": {
      "weightKg": { "type": "number" },
      "heightM": { "type": "number" }
    },
    "required": ["weightKg", "heightM"]
  }
}

Las funciones de JavaScript reciben input y deben devolver un resultado. Las funciones de Python establecen una variable result:

# Ejemplo en Python
result = {"imc": round(input["weightKg"] / (input["heightM"] ** 2), 1)}

Ejecutar una función directamente:

POST /v1/functions/{id}/execute
Content-Type: application/json

{ "input": { "weightKg": 75, "heightM": 1.80 } }

Seguridad: JavaScript se ejecuta en el sandbox vm de Node (sin acceso al sistema de archivos ni a la red, tiempo de espera de 10s). Python se ejecuta como un subproceso con un tiempo de espera de 30s. Ambos validan la entrada antes de la ejecución.

Actualizar o eliminar:

PATCH /v1/functions/{id}
DELETE /v1/functions/{id}

Habilidades

Habilidades son prompts guardados que los agentes pueden referenciar y lanzar rápidamente desde la vista de conversación vacía. Las habilidades instaladas desde el Hub (gestionadas mediante instalación de paquetes) NO se incluyen aquí; solo se enumeran y pueden editarse las habilidades creadas por el usuario.

Listar habilidades:

GET /v1/skills

Devuelve { skills: [...] } de las habilidades creadas por el usuario para el perfil activo. Se filtran las habilidades eliminadas (tombstoned), las superpuestas del hub y las de sincronización (sync-shadow).

Obtener una habilidad:

GET /v1/skills/{id}

Crear una habilidad:

POST /v1/skills
Content-Type: application/json

{
  "prompt": "Resume la página en 3 puntos clave.",
  "tags": ["utilidad", "resumir"],
  "isFavorite": true,
  "modes": ["general"],
  "displayName": "Resumen rápido",
  "description": "TL;DR de tres puntos de la página activa"
}

Solo se requiere prompt. modes (opcional) limita la habilidad a IDs de agentes específicos; omítalo para todos los modos. Devuelve 201 con la nueva habilidad (incluyendo id, createdAt, updatedAt asignados por el servidor).

Actualizar una habilidad:

PATCH /v1/skills/{id}
Content-Type: application/json

{ "prompt": "Prompt actualizado", "isFavorite": false }

Campos editables: prompt, tags, modes, displayName, description, isFavorite. Los intentos de editar una habilidad superpuesta del hub devuelven 404.

Eliminar una habilidad:

DELETE /v1/skills/{id}

Eliminación lógica mediante marca de borrado. Devuelve 204. Las habilidades del hub devuelven 404; desinstale el paquete de origen en su lugar.

Flujos de trabajo

Orqueste múltiples agentes en un DAG (grafo acíclico dirigido): ejecute pasos en paralelo cuando sea posible y use los resultados de pasos anteriores en los posteriores.

Validar un grafo de flujo de trabajo:

POST /v1/workflows/validate
Content-Type: application/json

{
  "graph": {
    "nodes": [
      { "id": "research", "agentId": "general", "prompt": "Investigar tendencias de energía renovable" },
      { "id": "analyze", "agentId": "general", "prompt": "Investigar precios de la competencia" },
      { "id": "report", "agentId": "general", "prompt": "Escribir un informe combinando: {{outputs.research}} y {{outputs.analyze}}", "dependsOn": ["research", "analyze"] }
    ]
  }
}

Devuelve { valid: true/false, errors: [...] }. Comprueba ciclos, IDs duplicados y referencias de dependencia faltantes.

Ejecutar un flujo de trabajo:

POST /v1/workflows/execute
Content-Type: application/json

{
  "graph": {
    "nodes": [
      { "id": "research", "agentId": "general", "prompt": "Investigar tendencias de energía renovable" },
      { "id": "summarize", "agentId": "general", "prompt": "Resumir: {{outputs.research}}", "dependsOn": ["research"] }
    ]
  }
}

Devuelve { status: "completed", outputs: { research: "...", summarize: "..." }, nodeResults: {...} }.

Los nodos independientes (sin dependencias compartidas) se ejecutan en paralelo. El marcador de posición {{outputs.nodeId}} en el prompt de un nodo se reemplaza con el contenido de salida del nodo ascendente correspondiente. Cada nodo es una ejecución completa del agente, por lo que puede usar herramientas, navegar por la web y acceder a todas las capacidades del agente de destino.

Bases de Conocimiento

Organice documentos en colecciones buscables a las que los agentes puedan hacer referencia.

Listar bases de conocimiento:

GET /v1/knowledge/bases

Crear una base de conocimiento:

POST /v1/knowledge/bases
Content-Type: application/json

{ "name": "Artículos de Investigación" }

Devuelve 201 con el nuevo ID de la base.

Subir un documento a una base de conocimiento:

POST /v1/knowledge/bases/{id}/documents
Content-Type: application/json

{
  "fileName": "articulo-investigacion.pdf",
  "contentType": "application/pdf",
  "dataUrl": "data:application/pdf;base64,JVBERi0xLjQ...",
  "description": "Tendencias de energía renovable 2026"
}

El campo dataUrl es una URL de datos codificada en base64. Devuelve 201 con los metadatos del documento.

Listar documentos en una base de conocimiento:

GET /v1/knowledge/bases/{id}/documents

Buscar dentro de una base de conocimiento:

POST /v1/knowledge/bases/{id}/search
Content-Type: application/json

{ "query": "energía renovable" }

Devuelve documentos coincidentes basados en el nombre del archivo y la descripción. La búsqueda semántica (vectorial) llegará en una versión futura.

Eliminar un documento o base de conocimiento:

DELETE /v1/knowledge/bases/{id}/documents/{docId}
DELETE /v1/knowledge/bases/{id}

Exportar e Importar Agentes

Comparte agentes como paquetes portátiles: entre dispositivos, equipos o el Community Hub.

Exportar un agente:

POST /v1/agents/{id}/export

Devuelve un paquete JSON que contiene la definición del agente, los requisitos de herramientas (derivados de las herramientas habilitadas), los requisitos de conectores (qué proveedores de OAuth son necesarios) y las plantillas de activadores. Los metadatos de sincronización se eliminan: el paquete es un diseño limpio e independiente.

Importar un agente:

POST /v1/agents/import
Content-Type: application/json

{
  \"package\": {
    \"$schema\": \"caiioo.agent.package/v1\",
    \"agent\": {
      \"id\": \"agente-de-investigacion-compartido\",
      \"branding\": { \"name\": \"Agente de Investigación\", \"description\": \"Del equipo\" },
      \"defaultSettings\": { \"systemPrompt\": \"Investigas cosas.\" },
      \"settingLevels\": {}
    },
    \"toolRequirements\": [
      { \"toolId\": \"web_browsing\", \"enabled\": true },
      { \"toolId\": \"search_tools\", \"enabled\": true }
    ]
  }
}

Devuelve 201 con el agente instalado. Las colisiones de ID con agentes integrados o existentes devuelven 409.

Manejo de errores

La API utiliza códigos de estado HTTP estándar:

Código Significado
200 Éxito
201 Creado
202 Aceptado (operación asíncrona iniciada)
204 Eliminado (sin contenido)
400 Solicitud incorrecta: consulta el campo error para más detalles
401 No autorizado: falta el secreto de sesión o es inválido
403 Prohibido: por ejemplo, intentar modificar un agente integrado
404 No encontrado
409 Conflicto: por ejemplo, el ID del agente ya existe
422 Error de validación: la entrada no coincide con el esquema de la herramienta
429 Límite de velocidad excedido: consulta los presupuestos en la sección de Autenticación
500 Error del servidor: consulta el campo error
501 No implementado: la función existe pero no está disponible de esta forma
503 Servicio no disponible: el almacenamiento o proveedor no están listos

Todas las respuestas de error incluyen { \"error\": \"mensaje legible por humanos\" }.

Ejemplo de Inicio Rápido

Aquí tiene un flujo de trabajo completo: crear un agente, ejecutarlo y transmitir los resultados.

# 1. Crear un agente personalizado
curl -X POST http://localhost:3847/v1/agents \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "resumidor-rapido",
    "branding": { "name": "Resumidor Rápido" },
    "defaultSettings": {
      "systemPrompt": "Resume cualquier entrada de forma concisa en 3 puntos clave.",
      "enabledTools": { "web_browsing": true }
    },
    "settingLevels": {}
  }'

# 2. Ejecutarlo asíncronamente
RUN=$(curl -s -X POST http://localhost:3847/v1/runs \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "agentId": "resumidor-rapido", "input": { "message": "Resumir https://es.wikipedia.org/wiki/Inteligencia_artificial" }, "mode": "async" }')

RUN_ID=$(echo $RUN | jq -r '.runId')

# 3. Transmitir los eventos
curl -N http://localhost:3847/v1/runs/$RUN_ID/events \
  -H "Authorization: Bearer $API_TOKEN"

# 4. Exportar el agente para compartir
curl -X POST http://localhost:3847/v1/agents/resumidor-rapido/export \
  -H "Authorization: Bearer $API_TOKEN"

This guide is maintained by the Caiioo team using Slate, our built-in editor.