Ceci est une traduction automatique du document original en anglais. En cas de divergence entre cette traduction et la version originale anglaise, la version anglaise fera foi. Consulter la version originale en anglais


API Publique

Caiioo inclut une API REST qui vous permet de tout contrôler par programmation : exécuter des agents, gérer des outils, planifier des tâches, et plus encore. L'API réside sur le même serveur local qui alimente l'application de bureau et le bridge du navigateur.

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

Authentification : Deux façons de s'authentifier, toutes deux conditionnées par l'activation de l'API dans les réglages :

Pour les consommateurs externes (scripts, intégrations, curl) : Définissez un jeton d'accès API dans Réglages > Accès API, puis utilisez-le comme jeton Bearer :

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

Pour l'application locale (automatique) : L'application de bureau Caiioo, les extensions de navigateur et les applications mobiles s'authentifient automatiquement via l'en-tête d'authentification relay existant (x-relay-auth). Aucune configuration manuelle n'est nécessaire. Les requêtes relay-auth contournent l'activation de l'API publique car elles sont déjà approuvées.

Configuration :

  1. Ouvrez Réglages Caiioo > Accès API
  2. Activez Activer l'API Publique
  3. Définissez un jeton d'accès API (toute chaîne de votre choix — traitez-la comme un mot de passe)
  4. Utilisez ce jeton dans toutes les requêtes API

L'API est disponible sur localhost et via le relais privé. Consultez GET /v1/auth/info (sans authentification) pour le statut actuel et les instructions.

Limites de débit : chaque requête /v1/* est limitée par IP client — 100 requêtes GET par minute pour la lecture et 30 requêtes d'écriture par minute (POST / PATCH / DELETE) combinées. Les requêtes dépassant la limite reçoivent un code 429.

Profils

Un seul appareil peut contenir plusieurs profils d'utilisateurs (ex: personnel + travail). L'API permet aux scripts d'inspecter les profils disponibles et de changer le profil actif.

Lister les profils :

GET /v1/profiles

Renvoie { profiles: [...] }. Les champs contenant des jetons et les mécanismes internes de synchronisation sont supprimés. Utilisez /v1/connectors pour inspecter les connexions OAuth.

Obtenir le profil actif :

GET /v1/profiles/active

Renvoie le profil actuellement utilisé par ce serveur. Toutes les ressources /v1/* liées à un profil (fils, pièces jointes, réglages) s'appliquent à celui-ci.

Changer le profil actif :

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

{ \"profileId\": \"uuid-utilisateur-de-la-liste\" }

Fournisseurs & Modèles

Découvrez quels fournisseurs de LLM sont configurés et quels modèles sont disponibles.

Lister les fournisseurs :

GET /v1/providers

Renvoie tous les types de fournisseurs pris en charge. Actuellement : anthropic, openai, google, openrouter, ollama, poe, mlx, perplexity, baseten, cloudflare. Chaque entrée inclut type, displayName, icon, requiresApiKey, hasApiKey, ainsi qu'un objet capabilities avec les indicateurs ci-dessous.

Indicateur de capacité Signification
supportsVision Le fournisseur peut accepter des entrées d'images
supportsPdfFile Le fournisseur peut accepter nativement des blocs de contenu de fichiers PDF bruts
supportsToolCalling Le fournisseur prend en charge l'appel de fonctions/outils
supportsStreaming Le fournisseur diffuse les tokens de manière incrémentielle
supportsExtendedThinking Le fournisseur expose un budget de raisonnement/réflexion
supportsPromptCaching Le fournisseur prend en charge les directives de mise en cache des prompts
nativeReasoningBlocks Le fournisseur émet la réflexion sous forme de blocs de messages natifs (vs texte)
requiresThoughtSignature Le fournisseur exige que les tokens de réflexion signés soient renvoyés en écho

Les indicateurs de capacité reflètent le champ readonly capabilities de chaque classe de fournisseur (voir src/shared/providers/*-provider.ts) et sont validés par un test sentinelle de dérive — appelez ce point de terminaison au moment de l'exécution plutôt que de coder la matrice en dur.

Notes pour les fournisseurs BYOK :

  • perplexity expose une liste organisée de modèles Sonar (Perplexity n'a pas de point de terminaison /models public).
  • cloudflare (AI Gateway) est BYOK + multi-vendeurs ; la liste des modèles est déterminée par la configuration de votre passerelle et est renvoyée sous forme de tableau vide par /v1/providers/cloudflare/models. Utilisez votre propre catalogue de passerelle.

Lister les modèles pour un fournisseur :

GET /v1/providers/openrouter/models

Renvoie le catalogue de modèles pour ce fournisseur. Chaque modèle inclut id, displayName, et contextLength lorsqu'ils sont disponibles. Renvoie une erreur 503 lorsque le fournisseur n'a pas de clé API ou que son catalogue en amont est inaccessible.

Catalogue global pour tous les fournisseurs :

GET /v1/models

Fusionne les modèles de chaque fournisseur configuré en une seule liste. Les fournisseurs sans clé API sont ignorés et listés dans warnings.

Agents

Les agents sont le cœur de caiioo. Chaque agent est un Mode — une personnalité configurée avec ses propres instructions système, outils, variables et skills.

Lister tous les agents :

GET /v1/agents

Renvoie les agents intégrés (Shopping, Workplace, General) et tous les agents personnalisés que vous avez créés. Chacun est marqué avec source: \"builtin\" ou source: \"custom\".

Créer un agent personnalisé :

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

{
  \"id\": \"mon-agent-de-recherche\",
  \"branding\": {
    \"name\": \"Agent de recherche\",
    \"description\": \"Recherche sur le web et résume les résultats\"
  },
  \"defaultSettings\": {
    \"systemPrompt\": \"Vous êtes un assistant de recherche. Citez toujours vos sources.\",
    \"enabledTools\": { \"web_browsing\": true, \"search_tools\": true }
  },
  \"settingLevels\": {}
}

Renvoie 201 avec l'agent créé. Une horloge vectorielle est jointe automatiquement pour la synchronisation.

Mettre à jour un agent :

PATCH /v1/agents/mon-agent-de-recherche
Content-Type: application/json

{ \"branding\": { \"name\": \"Agent de recherche\", \"description\": \"Description mise à jour\" } }

Fusionne le correctif dans l'agent existant et incrémente l'horloge vectorielle. Les agents intégrés renvoient 403 — ils sont en lecture seule.

Supprimer un agent :

DELETE /v1/agents/mon-agent-de-recherche

Suppression logicielle via « tombstone » (se synchronise sur les appareils). Renvoie 204.

Exécution d'Agents

C'est l'événement principal — invoquer un agent pour traiter un message.

Corps de la requête — champs pris en charge

Champ Requis Description
agentId oui ID du mode intégré (ex: general) ou ID d'un agent personnalisé
input.message oui Texte du message de l'utilisateur
input.attachments non Tableau d'IDs de pièces jointes (déjà téléchargées via /v1/attachments) à joindre à ce tour
input.variables non Surcharges de variables par exécution fusionnées dans le résolveur de variables de l'agent
input.tabContext non Chaîne de caractères libre injectée comme contexte de page (utilisée par le pont du navigateur)
input.messageId non ID de message fourni par le client — utile pour la déduplication en cas de tentative de réessai
threadId non Fil de discussion existant à continuer. Si omis, un nouveau fil est créé et renvoyé
mode non "sync" ou "async". Par défaut "async"

Mode Synchrone

Attendre la réponse complète :

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

{
  "agentId": "general",
  "input": { "message": "Quel temps fait-il à Paris aujourd'hui ?" },
  "mode": "sync"
}

Renvoie 200 avec { content, usage, status: "completed" } une fois que l'agent a terminé. Si l'agent rencontre une erreur, renvoie 500 avec { error, status: "error" }. Les exécutions synchrones expirent après 5 minutes avec status: "error" si aucun événement terminal n'est reçu — utilisez le mode async + SSE pour tout ce qui pourrait durer plus longtemps.

Mode Asynchrone

Lancer et oublier — utile pour les tâches de longue durée :

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

{
  "agentId": "my-research-agent",
  "input": { "message": "Rédige une analyse de 2000 mots sur les tendances des énergies renouvelables" },
  "mode": "async"
}

Renvoie 202 immédiatement avec { runId, threadId, status: "running" }.

Sonder le statut :

GET /v1/runs/{runId}

Renvoie { run: { runId, threadId, agentId, status, createdAt, content?, usage?, error? } }. Le statut est l'un des suivants : running, completed, error, ou cancelled.

Flux d'événements en temps réel (SSE) :

GET /v1/runs/{runId}/events

Renvoie un text/event-stream avec chaque événement de l'agent au fur et à mesure qu'il se produit : GENERATION_STARTED, STREAMING_CONTENT, appels d'outils, activité des sous-agents, et l'événement terminal (GENERATION_COMPLETE, GENERATION_ERROR, ou GENERATION_CANCELLED).

Après l'événement terminal, le serveur émet une dernière trame SSE avec event: terminal et une charge utile de données vide comme sentinelle explicite de fin de flux, puis ferme la connexion. Les clients doivent considérer la réception de cette trame (ou une fermeture de connexion) comme le signal d'arrêt de la lecture.

Si vous vous abonnez après que l'exécution est déjà terminée, le serveur rejoue une trame de type RUN_SNAPSHOT contenant l'enregistrement final complet (record), suivie de la sentinelle event: terminal, puis ferme la connexion.

Annuler une exécution :

POST /v1/runs/{runId}/cancel

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

Threads

Les Threads sont des conversations. Chaque exécution d'agent se déroule au sein d'un thread, et les threads persistent d'une session à l'autre. L'API vous permet de lister, lire, créer et gérer les threads par programmation.

Lister tous les threads (métadonnées uniquement) :

GET /v1/threads

Renvoie { threads: [...] } pour le profil actuel avec les messages supprimés (utilisez le point de terminaison détaillé lorsque vous en avez besoin). Tous les autres champs sont conservés — id, title, createdAt, updatedAt, modeId, archived, les statistiques d'utilisation, ainsi que subAgentHistories, anonymizerSnapshot, threadToolApprovals, threadVariables, threadToolOverrides, messagingBinding, scheduledTaskId lorsqu'ils sont définis. (La charge utile plus riche est exclusive à l'API — la diffusion de la barre latérale via WebSocket utilise une version plus restreinte pour rester sous les limites de transport.)

Obtenir un thread avec tous les messages :

GET /v1/threads/{id}

Renvoie le thread complet incluant son tableau messages — chaque message utilisateur, réponse de l'assistant, appel d'outil et résultat d'outil.

Obtenir uniquement les messages :

GET /v1/threads/{id}/messages

Renvoie uniquement le tableau messages — plus léger que l'objet thread complet lorsque vous n'avez besoin que de la conversation.

Créer un thread :

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

{ "title": "Projet de recherche", "modeId": "general" }

Renvoie 201 avec { thread }. Le nouveau thread apparaît immédiatement dans la barre latérale (via diffusion WebSocket). L'API ne change jamais le thread actif de l'application lors de la création — appelez PUT /v1/threads/active séparément si vous souhaitez ce comportement.

Mettre à jour un thread :

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

{ "title": "Projet renommé", "archived": true }

Champs modifiables : title, modeId, archived, lastUsedModel. Les modifications sont diffusées dans la barre latérale en temps réel.

Supprimer un thread :

DELETE /v1/threads/{id}

Effectue une suppression logicielle (soft-delete) du thread (marqueur pour la synchronisation). Renvoie 204. Les threads supprimés sont déplacés vers la corbeille et peuvent être récupérés jusqu'à ce que la corbeille soit vidée.

Thread actif :

GET /v1/threads/active            # Renvoie { threadId }
PUT /v1/threads/active            # Corps : { "threadId": "..." }

Gestion de la corbeille :

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

Les threads protégés (conservés via le bouton de rétention des données) sont exclus du vidage de la corbeille.

Poursuivre une conversation via l'API : Pour envoyer un message de suivi à un thread existant, utilisez POST /v1/runs avec l'ID du thread :

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

{
  "agentId": "general",
  "threadId": "existing-thread-id",
  "input": { "message": "Suivi sur ce dernier point" },
  "mode": "sync"
}

L'agent voit l'historique complet de la conversation à partir du thread.

Pièces jointes

Les pièces jointes sont des fichiers liés aux fils de discussion — captures d'écran, PDF, documents, images téléchargées, artefacts générés. L'API vous permet de les lister, télécharger, téléverser et gérer.

Lister toutes les pièces jointes (métadonnées uniquement) :

GET /v1/attachments

Renvoie les métadonnées des pièces jointes pour le profil actuel. Les champs lourds (dataUrl, extractedContent, extractedImages) sont supprimés — utilisez les points de terminaison de détail ou de contenu pour ceux-là.

Lister les pièces jointes pour un fil spécifique :

GET /v1/threads/{threadId}/attachments

Obtenir les métadonnées d'une pièce jointe :

GET /v1/attachments/{id}

Renvoie les métadonnées complètes incluant extractedContent (texte OCR, markdown analysé), contentType, fileName, size, et un drapeau hasContent. Le binaire brut n'est PAS inclus — utilisez le point de terminaison /content pour cela.

Télécharger le binaire d'une pièce jointe :

GET /v1/attachments/{id}/content

Renvoie le fichier brut avec les en-têtes Content-Type et Content-Disposition corrects. Redirigez ceci vers un fichier :

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

Téléverser une pièce jointe :

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

{
  "threadId": "id-du-fil",
  "type": "user_upload",
  "contentType": "application/pdf",
  "fileName": "rapport.pdf",
  "description": "Rapport trimestriel",
  "dataUrl": "data:application/pdf;base64,JVBERi0xLjQ..."
}

Le dataUrl est une URL de données encodée en base64. Renvoie 201 avec le nouvel ID de pièce jointe. La pièce jointe est liée au fil spécifié.

Mettre à jour les métadonnées d'une pièce jointe :

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

{ "description": "Description mise à jour", "fileName": "nouveau-nom.pdf" }

Supprimer une pièce jointe :

DELETE /v1/attachments/{id}

Suppression douce via un marqueur d'effacement. Renvoie 204.

Serveurs MCP

Gérez vos connexions aux serveurs MCP (Model Context Protocol) — les serveurs qui permettent aux agents d'accéder à des outils externes et à des sources de données.

Lister les serveurs configurés :

GET /v1/mcp-servers

Renvoie toutes les configurations de serveurs MCP pour le profil actuel. Les champs sensibles (authToken, env, credentialId) sont retirés de la réponse.

Obtenir la configuration d'un serveur :

GET /v1/mcp-servers/{id}

Ajouter un nouveau serveur 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"
}

Pour les serveurs HTTP distants, utilisez "url" au lieu de "command" :

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

Champs optionnels acceptés lors du POST : command, args, env, url, description, transportType, authType, authToken, authHeader, headers, specType, specPath, timeoutMs, credentialId, oauthConnectionId, approval. Les champs gérés par le serveur (customOAuth, hubPackageId, profileId, connectorId, teamPublished, teamOrgId, vectorClock, ...) ne peuvent pas être définis via l'API.

Mettre à jour un serveur :

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

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

Les champs modifiables via PATCH correspondent à la liste d'autorisation du POST (incluant credentialId et oauthConnectionId — pratique pour faire pivoter une connexion OAuth sans supprimer et recréer). Les champs gérés par le serveur restent en lecture seule.

Activer/désactiver un serveur :

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

{ "enabled": false }

Supprimer un serveur :

DELETE /v1/mcp-servers/{id}

Gestion des processus

Pour les serveurs MCP locaux (stdio), vous pouvez gérer le processus du serveur directement.

Lister les processus en cours d'exécution :

GET /v1/mcp-servers/processes

Renvoie les processus serveur en cours avec le pid, le startedAt, et le statut running.

Démarrer un serveur :

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

Lit la commande/args/env depuis la configuration du serveur et lance le processus. Renvoie le statut du processus.

Arrêter un serveur :

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

Arrête proprement le processus du serveur (SIGTERM avec repli sur SIGKILL).

Appeler directement une méthode JSON-RPC :

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

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

Envoie une requête JSON-RPC 2.0 brute au serveur et renvoie le résultat. Utile pour le débogage ou pour appeler des méthodes non exposées via l'API des outils.

Outils et Toolkits

Parcourez et invoquez les outils utilisés par les agents — navigation web, recherche, calendrier, Gmail, Slate, et plus encore.

Lister les toolkits (groupés) :

GET /v1/toolkits

Renvoie les outils intégrés groupés par catégorie (Productivité, Recherche, Utilitaires, etc.) et tous les serveurs MCP connectés en tant que toolkits distincts, chacun avec la liste de ses actions.

Lister tous les outils (liste plate) :

GET /v1/tools
GET /v1/tools?source=embedded   # Uniquement les outils intégrés
GET /v1/tools?source=mcp        # Uniquement les outils des serveurs MCP

Obtenir les détails d'un outil avec son schéma d'entrée :

GET /v1/tools/calculator

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

Champ Signification
inputSchema Schéma JSON pour l'entrée de l'outil — à valider avant l'invocation
actions Sous-actions optionnelles (ex: Slate read/write) ; chacune possède un id, displayName, description, et un requiredTier optionnel
requiredTier Niveau d'abonnement utilisateur minimum (free si omis). L'invocation via l'API publique refuse tout ce qui est supérieur à free
requiredRuntimes Plateformes où cet outil est disponible (macos, ios, etc.) ; omission ⇒ partout
riskTier Risque lié au consentement : low (par défaut), medium, high
riskExplanation Raison lisible par l'homme expliquant pourquoi le riskTier est élevé
requiresApproval true quand l'outil nécessite une approbation utilisateur par appel — l'invocation via l'API publique refuse ces outils

Invoquer un outil directement :

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

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

Renvoie { result }. L'entrée est validée par rapport au schéma de l'outil — une entrée invalide renvoie une erreur 422 avec les détails. Passez un threadId optionnel si l'outil a besoin d'un contexte lié au fil de discussion (ex: recherche de pièces jointes).

Restrictions — ce que l'API publique refuse :

  • Outils restreints par abonnement (metadata.requiredTier !== 'free') → 403. La boucle de l'agent vérifie le niveau d'abonnement par rapport à la session de l'utilisateur ; l'API publique n'ayant pas de contexte d'abonnement transporté, la politique conservatrice est de refuser. Utilisez plutôt POST /v1/runs avec un agent disposant du bon niveau d'abonnement.
  • Outils nécessitant une approbation (metadata.approval.requiresApproval === true) → 403. Il n'y a pas d'humain dans la boucle pour donner son accord. Invoquez via POST /v1/runs (qui affiche la demande à l'utilisateur) ou réglez le mode d'approbation de l'outil sur approve_all dans l'application pour contourner cette restriction.
  • Outils MCP distants501 avec l'instruction d'utiliser /v1/runs (ils nécessitent le transport par sous-processus de l'agent).

Outils de vision et utilisant des images : téléchargez d'abord via POST /v1/attachments, puis passez l'ID de la pièce jointe renvoyé à l'intérieur de input (ex: { "input": { "attachment_id": "att_abc", "prompt": "Que contient cette image ?" } }). L'outil lit le binaire depuis le stockage via le threadId ; vous ne passez pas les octets directement dans la requête.

Connecteurs

Gérez les intégrations OAuth — Google, Microsoft, GitHub, Notion, Slack, et plus encore.

Parcourir les intégrations disponibles :

GET /v1/connectors/catalog

Renvoie tous les fournisseurs OAuth enregistrés avec leur nom, catégorie et portées par défaut.

Lister vos comptes connectés :

GET /v1/connectors

Renvoie les connexions actives pour le profil actuel. Les jetons ne sont jamais exposés — seulement les métadonnées.

Obtenir une seule connexion :

GET /v1/connectors/{id}

Vérifier la santé d'une connexion :

POST /v1/connectors/{id}/test

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

Supprimer une connexion :

DELETE /v1/connectors/{id}

La création de nouvelles connexions nécessite le flux OAuth interactif via l'interface de l'application ou les routes /auth/*.

Déclencheurs

Planifiez l'exécution automatique d'agents — briefings quotidiens, rapports hebdomadaires, surveillance par intervalles.

Chaque déclencheur a un discriminateur kind : schedule (par défaut — s'exécute selon une horloge), webhook (s'exécute lorsqu'un service externe envoie un POST) ou messaging (s'exécute depuis un adaptateur de messagerie connecté).

Lister les déclencheurs :

GET /v1/triggers

Obtenir un seul déclencheur :

GET /v1/triggers/{id}

Créer un déclencheur planifié :

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

{
  \"name\": \"Briefing Matinal\",
  \"prompt\": \"Résume mes e-mails non lus et mon calendrier d'aujourd'hui\",
  \"modeId\": \"general\",
  \"schedule\": { \"type\": \"daily\", \"time\": \"08:00\" }
}

Types de planification pris en charge :

  • { \"type\": \"interval\", \"minutes\": 60 } — toutes les N minutes (min 15, max 1440)
  • { \"type\": \"daily\", \"time\": \"09:00\" } — quotidiennement à une heure précise
  • { \"type\": \"weekly\", \"day\": \"mon\", \"time\": \"09:00\" } — hebdomadaire
  • { \"type\": \"weekdays\", \"time\": \"08:30\" } — du lundi au vendredi
  • { \"type\": \"daysOfWeek\", \"days\": [\"mon\", \"wed\", \"fri\"], \"time\": \"10:00\" } — jours spécifiques
  • { \"type\": \"monthly\", \"dayOfMonth\": 1, \"time\": \"09:00\" } — mensuel
  • { \"type\": \"manual\" } — seulement via l'API

Lancer un déclencheur manuellement :

POST /v1/triggers/{id}/fire

Renvoie 202 avec un threadId pour l'exécution résultante.

Webhooks

Les déclencheurs Webhook permettent à des services externes (CI/CD, surveillance, constructeurs de formulaires) de déclencher l'exécution d'un agent via HTTP.

Créer un déclencheur webhook :

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

{
  "name": "Deploy hook",
  "prompt": "Un déploiement a eu lieu : {{webhook.body}}",
  "modeId": "general",
  "kind": "webhook"
}

Retourne 201 avec un webhookSecret et un webhookPath. Conservez le secret — vous en aurez besoin pour signer les charges utiles.

Envoyer un webhook :

# Calculer le HMAC-SHA256 du corps brut de la requête
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"}

Le point de terminaison du webhook ne nécessite PAS d'authentification bearer — il utilise la vérification HMAC à la place. Retourne 202 avec le threadId de l'exécution répartie. L'espace réservé {{webhook.body}} dans l'invite du déclencheur est remplacé par le corps brut de la requête.

Déclencheurs de messagerie

Les déclencheurs de messagerie s'activent lorsqu'un adaptateur de messagerie connecté (par exemple, une intégration Slack ou Discord installée via le Community Hub) reçoit un message entrant correspondant au filtre du déclencheur. Créez avec kind: "messaging" :

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

{
  "name": "Mention responder",
  "prompt": "Réponds utilement à : {{message.text}}",
  "modeId": "general",
  "kind": "messaging",
  "messagingAdapterId": "slack-team-acme",
  "messagingChannelFilter": "#support"
}

L'adaptateur est responsable de la répartition des événements correspondants dans le déclencheur ; messagingChannelFilter est spécifique à l'adaptateur.

Fonctions personnalisées

Créez vos propres outils que les agents peuvent appeler. Les fonctions sont écrites en JavaScript ou Python et s'exécutent dans un bac à sable (sandbox).

Lister les fonctions :

GET /v1/functions

Créer une fonction :

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

{
  "name": "calculer_imc",
  "description": "Calculer l'Indice de Masse Corporelle à partir de la taille et du poids",
  "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"]
  }
}

Les fonctions JavaScript reçoivent input et doivent retourner un résultat. Les fonctions Python définissent une variable result :

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

Exécuter une fonction directement :

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

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

Sécurité : JavaScript s'exécute dans le bac à sable vm de Node (pas d'accès au système de fichiers ou au réseau, délai d'expiration de 10s). Python s'exécute comme un sous-processus avec un délai d'expiration de 30s. Les deux valident l'entrée avant l'exécution.

Mettre à jour ou supprimer :

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

Skills

Les Skills sont des invites enregistrées auxquelles les agents peuvent se référer et qu'ils peuvent lancer rapidement depuis la vue de conversation vide. Les skills installés via le Hub (gérés via l'installation de paquets) ne sont PAS inclus ici — seuls les skills créés par l'utilisateur sont listés et modifiables.

Lister les skills :

GET /v1/skills

Retourne { skills: [...] } des skills créés par l'utilisateur pour le profil actif. Les skills supprimés (tombstoned), les superpositions du hub et les copies de synchronisation sont filtrés.

Obtenir un skill :

GET /v1/skills/{id}

Créer un skill :

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

{
  "prompt": "Résume la page en 3 points clés.",
  "tags": ["utilitaire", "résumer"],
  "isFavorite": true,
  "modes": ["general"],
  "displayName": "Résumé Rapide",
  "description": "TL;DR en trois points de la page active"
}

Seul le champ prompt est requis. modes (optionnel) limite le skill à des ID d'agents spécifiques ; omettez pour tous les modes. Retourne 201 avec le nouveau skill (incluant l' id attribué par le serveur, createdAt, updatedAt).

Mettre à jour un skill :

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

{ "prompt": "Invite mise à jour", "isFavorite": false }

Champs modifiables : prompt, tags, modes, displayName, description, isFavorite. Les tentatives de modification d'un skill provenant du hub retournent 404.

Supprimer un skill :

DELETE /v1/skills/{id}

Suppression réversible via marquage (tombstone). Retourne 204. Les skills du hub retournent 404 — désinstallez le paquet source à la place.

Workflows

Orchestrez plusieurs agents dans un DAG (graphe orienté acyclique) — exécutez les étapes en parallèle lorsque c'est possible, et injectez les résultats des étapes précédentes dans les suivantes.

Valider un graphe de workflow :

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

{
  "graph": {
    "nodes": [
      { "id": "research", "agentId": "general", "prompt": "Rechercher les tendances des énergies renouvelables" },
      { "id": "analyze", "agentId": "general", "prompt": "Rechercher les prix des concurrents" },
      { "id": "report", "agentId": "general", "prompt": "Rédiger un rapport combinant : {{outputs.research}} et {{outputs.analyze}}", "dependsOn": ["research", "analyze"] }
    ]
  }
}

Retourne { valid: true/false, errors: [...] }. Vérifie les cycles, les identifiants en double et les références de dépendance manquantes.

Exécuter un workflow :

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

{
  "graph": {
    "nodes": [
      { "id": "research", "agentId": "general", "prompt": "Rechercher les tendances des énergies renouvelables" },
      { "id": "summarize", "agentId": "general", "prompt": "Résumer : {{outputs.research}}", "dependsOn": ["research"] }
    ]
  }
}

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

Les nœuds indépendants (sans dépendances communes) s'exécutent en parallèle. L'espace réservé {{outputs.nodeId}} dans le prompt d'un nœud est remplacé par le contenu de sortie du nœud amont nommé. Chaque nœud est une exécution complète d'agent, il peut donc utiliser des outils, naviguer sur le web et accéder à toutes les capacités de l'agent cible.

Bases de connaissances

Organisez des documents en collections consultables que les agents peuvent référencer.

Lister les bases de connaissances :

GET /v1/knowledge/bases

Créer une base de connaissances :

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

{ "name": "Articles de recherche" }

Renvoie 201 avec l'ID de la nouvelle base.

Télécharger un document vers une base de connaissances :

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

{
  "fileName": "article-recherche.pdf",
  "contentType": "application/pdf",
  "dataUrl": "data:application/pdf;base64,JVBERi0xLjQ...",
  "description": "Tendances des énergies renouvelables 2026"
}

Le champ dataUrl est une URL de données encodée en base64. Renvoie 201 avec les métadonnées du document.

Lister les documents d'une base de connaissances :

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

Rechercher dans une base de connaissances :

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

{ "query": "énergie renouvelable" }

Renvoie les documents correspondants basés sur le nom du fichier et la description. La recherche sémantique (vectorielle) arrivera dans une future version.

Supprimer un document ou une base de connaissances :

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

Exporter et importer des agents

Partagez des agents sous forme de packages portables — entre appareils, équipes ou via le Community Hub.

Exporter un agent :

POST /v1/agents/{id}/export

Renvoie un package JSON contenant la définition de l'agent, les exigences d'outils (dérivées des outils activés), les exigences de connecteurs (quels fournisseurs OAuth sont nécessaires) et les modèles de déclencheurs. Les métadonnées de synchronisation sont supprimées — le package est un plan propre et autonome.

Importer un agent :

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

{
  \"package\": {
    \"$schema\": \"caiioo.agent.package/v1\",
    \"agent\": {
      \"id\": \"agent-de-recherche-partage\",
      \"branding\": { \"name\": \"Agent de recherche\", \"description\": \"De l'équipe\" },
      \"defaultSettings\": { \"systemPrompt\": \"Vous recherchez des choses.\" },
      \"settingLevels\": {}
    },
    \"toolRequirements\": [
      { \"toolId\": \"web_browsing\", \"enabled\": true },
      { \"toolId\": \"search_tools\", \"enabled\": true }
    ]
  }
}

Renvoie 201 avec l'agent installé. Les collisions d'ID avec des agents intégrés ou existants renvoient 409.

Gestion des erreurs

L'API utilise les codes de statut HTTP standard :

Code Signification
200 Succès
201 Créé
202 Accepté (opération asynchrone démarrée)
204 Supprimé (pas de contenu)
400 Requête incorrecte — vérifiez le champ error
401 Non autorisé — secret de session manquant ou invalide
403 Interdit — ex: tentative de modifier un agent intégré
404 Non trouvé
409 Conflit — ex: l'ID de l'agent existe déjà
422 Erreur de validation — l'entrée ne correspond pas au schéma
429 Limite de débit atteinte
500 Erreur serveur
501 Non implémenté
503 Service indisponible

Toutes les réponses d'erreur incluent { \"error\": \"message lisible par l'homme\" }.

Exemple de démarrage rapide

Voici un flux de travail complet : créer un agent, l'exécuter et diffuser les résultats.

# 1. Créer un agent personnalisé
curl -X POST http://localhost:3847/v1/agents \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "quick-summarizer",
    "branding": { "name": "Quick Summarizer" },
    "defaultSettings": {
      "systemPrompt": "Résumez toute entrée de manière concise en 3 points.",
      "enabledTools": { "web_browsing": true }
    },
    "settingLevels": {}
  }'

# 2. L'exécuter de manière asynchrone
RUN=$(curl -s -X POST http://localhost:3847/v1/runs \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "agentId": "quick-summarizer", "input": { "message": "Résumer https://fr.wikipedia.org/wiki/Intelligence_artificielle" }, "mode": "async" }')

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

# 3. Diffuser les événements
curl -N http://localhost:3847/v1/runs/$RUN_ID/events \
  -H "Authorization: Bearer $API_TOKEN"

# 4. Exporter l'agent pour le partager
curl -X POST http://localhost:3847/v1/agents/quick-summarizer/export \
  -H "Authorization: Bearer $API_TOKEN"

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