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:
- Abre Ajustes de Caiioo > Acceso API
- Activa Habilitar API pública
- Establece un token de acceso a la API (cualquier cadena que elijas; trátala como una contraseña)
- 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:
perplexityexpone una lista curada de modelos Sonar (Perplexity no tiene un endpoint/modelspú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/modelsla 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 |
sí | ID de modo integrado (ej. general) o un ID de agente personalizado |
input.message |
sí | 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, usePOST /v1/runscon 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 dePOST /v1/runs(que presenta la solicitud al usuario) o configure el modo de aprobación de herramientas enapprove_allen la aplicación para omitirlo. - Herramientas MCP remotas →
501con 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.