Questa è una traduzione automatica del documento originale in inglese. In caso di discrepanze tra la presente traduzione e la versione originale in inglese, prevarrà la versione inglese. Leggi la versione originale in inglese
API Pubblica
Caiioo include un'API REST che ti permette di controllare tutto programmaticamente: eseguire agenti, gestire strumenti, pianificare task e altro ancora. L'API risiede sullo stesso server locale che alimenta l'app desktop e il bridge del browser.
URL di base: http://localhost:3847/v1
Autenticazione: Due modi per autenticarsi, entrambi regolati dall'interruttore API nelle impostazioni:
Per consumatori esterni (script, integrazioni, curl): Imposta un token di accesso API in Impostazioni > Accesso API, quindi usalo come Bearer token:
curl -H \"Authorization: Bearer IL_TUO_TOKEN_API\" http://localhost:3847/v1/providers
Per l'app locale (automatico):
L'app desktop Caiioo, le estensioni del browser e le app mobili si autenticano automaticamente tramite l'intestazione di autenticazione relay esistente (x-relay-auth; le intestazioni HTTP non fanno distinzione tra maiuscole e minuscole). Nessuna configurazione manuale necessaria — l'app gestisce tutto dietro le quinte. Le richieste relay-auth saltano l'interruttore Abilita API Pubblica poiché sono già attendibili; solo le richieste con bearer-token sono regolate dall'interruttore.
Configurazione:
- Apri Impostazioni Caiioo > Accesso API
- Attiva Abilita API Pubblica
- Imposta un token di accesso API (qualsiasi stringa a tua scelta — trattala come una password)
- Usa quel token in tutte le richieste API
L'API è disponibile su localhost e tramite il relay privato. Controlla GET /v1/auth/info (nessuna autenticazione richiesta) per lo stato attuale e le istruzioni di configurazione.
Limiti di frequenza: ogni richiesta /v1/* è limitata per IP client — 100 richieste GET al minuto per la lettura e 30 richieste di scrittura al minuto (POST / PATCH / DELETE) combinate. Le richieste oltre il limite ricevono 429. Le consegne dei webhook (POST /v1/webhooks/:id) non sono autenticate tramite bearer e non sono soggette a questi limiti.
Profili
Un singolo dispositivo può ospitare più profili utente (ad es. personale + lavoro). L'API consente agli script esterni di ispezionare i profili disponibili e cambiare quello attivo prima di eseguire altre operazioni. La creazione, l'aggiornamento e l'eliminazione dei profili non sono deliberatamente esposti tramite l'API pubblica — questi flussi appartengono all'interfaccia utente di onboarding dell'app.
Elenco profili:
GET /v1/profiles
Restituisce { profiles: [...] } con una voce per ogni profilo non eliminato. Ogni voce include id, name, email, avatarUrl, tier, accessibleModes, license, organization, preferences, onboardingComplete, createdAt, lastAccessedAt. I campi contenenti token (serviceCredentials, oauthConnections) e i dati interni di sincronizzazione (vectorClock, lastModifiedBy) vengono rimossi. Usa /v1/connectors per ispezionare le connessioni OAuth.
Ottieni il profilo attivo:
GET /v1/profiles/active
Restituisce { profile } per il profilo attualmente in uso da questo server. Tutte le risorse /v1/* relative a un profilo (thread, allegati, impostazioni, skill) operano su questo.
Cambia il profilo attivo:
PUT /v1/profiles/active
Content-Type: application/json
{ "profileId": "user-uuid-dalla-lista" }
Restituisce { profile } per il nuovo profilo attivo. Restituisce 404 se l'ID non corrisponde a un profilo noto.
Providers & Models
Scopri quali provider LLM sono configurati e quali modelli sono disponibili.
Elenco dei provider:
GET /v1/providers
Restituisce ogni tipo di provider supportato. Attualmente: anthropic, openai, google, openrouter, ollama, poe, mlx, perplexity, baseten, cloudflare. Ogni voce include type, displayName, icon, requiresApiKey, hasApiKey e un oggetto capabilities con i flag indicati di seguito.
| Flag di capacità | Significato |
|---|---|
supportsVision |
Il provider può accettare input di immagini |
supportsPdfFile |
Il provider può accettare nativamente blocchi di contenuto di file PDF grezzi |
supportsToolCalling |
Il provider supporta la chiamata di funzioni/strumenti |
supportsStreaming |
Il provider trasmette i token in modo incrementale |
supportsExtendedThinking |
Il provider espone un budget di ragionamento/pensiero |
supportsPromptCaching |
Il provider supporta le direttive di prompt-cache |
nativeReasoningBlocks |
Il provider emette il pensiero come blocchi di messaggi nativi (rispetto al testo) |
requiresThoughtSignature |
Il provider richiede che i token di pensiero firmati vengano restituiti in eco |
I flag di capacità rispecchiano il campo readonly capabilities di ogni classe provider (vedere src/shared/providers/*-provider.ts) e sono validati da un test sentinella di deriva — chiama questo endpoint a runtime invece di codificare la matrice in modo fisso.
Note per i provider BYOK:
perplexityespone un elenco curato di modelli Sonar (Perplexity non ha un endpoint/modelspubblico).cloudflare(AI Gateway) è BYOK + multi-vendor; l'elenco dei modelli è determinato dalla configurazione del tuo gateway e viene restituito come un array vuoto da/v1/providers/cloudflare/models. Utilizza il catalogo del tuo gateway.
Elenco dei modelli per un provider:
GET /v1/providers/openrouter/models
Restituisce il catalogo dei modelli per quel provider. Ogni modello include id, displayName e contextLength dove disponibile. Restituisce 503 quando il provider manca di una API key o il suo catalogo a monte non è raggiungibile.
Catalogo unico per tutti i provider:
GET /v1/models
Unisce i modelli di ogni provider configurato in un unico elenco. I provider senza API key vengono saltati e inclusi nei warnings.
Agenti
Gli agenti sono il cuore di caiioo. Ogni agente è una Modalità — una personalità configurata con il proprio prompt di sistema, strumenti, variabili e skill.
Elenca tutti gli agenti:
GET /v1/agents
Restituisce gli agenti integrati (Shopping, Workplace, Generale) e tutti gli agenti personalizzati creati. Ognuno è contrassegnato con source: \"builtin\" o source: \"custom\".
Crea un agente personalizzato:
POST /v1/agents
Content-Type: application/json
{
\"id\": \"mio-agente-ricerca\",
\"branding\": {
\"name\": \"Agente di Ricerca\",
\"description\": \"Cerca nel web e riassume i risultati\"
},
\"defaultSettings\": {
\"systemPrompt\": \"Sei un assistente di ricerca. Cita sempre le fonti.\",
\"enabledTools\": { \"web_browsing\": true, \"search_tools\": true }
},
\"settingLevels\": {}
}
Restituisce 201 con l'agente creato. Un vector clock viene allegato automaticamente per la sincronizzazione.
Aggiorna un agente:
PATCH /v1/agents/mio-agente-ricerca
Content-Type: application/json
{ \"branding\": { \"name\": \"Agente di Ricerca\", \"description\": \"Descrizione aggiornata\" } }
Unisce la patch all'agente esistente e incrementa il vector clock. Gli agenti integrati restituiscono 403 — sono in sola lettura.
Elimina un agente:
DELETE /v1/agents/mio-agente-ricerca
Eliminazione logica tramite tombstone (si sincronizza tra i dispositivi). Restituisce 204.
Esecuzione degli Agenti
Questo è l'evento principale — invocare un agente per elaborare un messaggio.
Corpo della richiesta — campi supportati
| Campo | Obbligatorio | Descrizione |
|---|---|---|
agentId |
sì | ID della modalità integrata (es. general) o ID di un agente personalizzato |
input.message |
sì | Testo del messaggio dell'utente |
input.attachments |
no | Array di ID degli allegati (già caricati tramite /v1/attachments) da allegare a questo turno |
input.variables |
no | Sovrascritture delle variabili per singola esecuzione unite nel risolutore di variabili dell'agente |
input.tabContext |
no | Stringa a formato libero iniettata come contesto della pagina (utilizzata dal bridge del browser) |
input.messageId |
no | ID messaggio fornito dal client — utile per la deduplicazione in caso di riprovo |
threadId |
no | Thread esistente da continuare. Se omesso, viene creato e restituito un nuovo thread |
mode |
no | "sync" o "async". Il valore predefinito è "async" |
Modalità Sincrona
Attendi la risposta completa:
POST /v1/runs
Content-Type: application/json
{
"agentId": "general",
"input": { "message": "Che tempo fa a Parigi oggi?" },
"mode": "sync"
}
Restituisce 200 con { content, usage, status: "completed" } dopo che l'agente ha terminato. Se l'agente riscontra un errore, restituisce 500 con { error, status: "error" }. Le esecuzioni sincrone vanno in timeout dopo 5 minuti con status: "error" se non viene ricevuto alcun evento terminale — usa la modalità async + SSE per qualsiasi operazione che potrebbe richiedere più tempo.
Modalità Asincrona
Invia e dimentica — utile per attività a lunga durata:
POST /v1/runs
Content-Type: application/json
{
"agentId": "my-research-agent",
"input": { "message": "Scrivi un'analisi di 2000 parole sulle tendenze delle energie rinnovabili" },
"mode": "async"
}
Restituisce immediatamente 202 con { runId, threadId, status: "running" }.
Polling per lo stato:
GET /v1/runs/{runId}
Restituisce { run: { runId, threadId, agentId, status, createdAt, content?, usage?, error? } }. Lo stato è uno tra running, completed, error, o cancelled.
Streaming degli eventi in tempo reale (SSE):
GET /v1/runs/{runId}/events
Restituisce un text/event-stream con ogni evento dell'agente man mano che accade: GENERATION_STARTED, STREAMING_CONTENT, chiamate a strumenti (tool calls), attività dei sub-agenti e l'evento terminale (GENERATION_COMPLETE, GENERATION_ERROR, o GENERATION_CANCELLED).
Dopo l'evento terminale, il server emette un frame SSE finale con event: terminal e un payload di dati vuoto come sentinella esplicita di fine flusso, quindi chiude la connessione. I client dovrebbero considerare la ricezione di quel frame (o la chiusura della connessione) come il segnale per interrompere la lettura.
Se ti iscrivi dopo che l'esecuzione è già terminata, il server riproduce un frame di tipo RUN_SNAPSHOT contenente il record finale completo, seguito dalla sentinella event: terminal, quindi chiude.
Annullare un'esecuzione:
POST /v1/runs/{runId}/cancel
Restituisce { run: { ..., status: "cancelled" } }.
Threads
I Threads sono conversazioni. Ogni esecuzione di un agente avviene all'interno di un thread e i thread persistono tra le sessioni. L'API consente di elencare, leggere, creare e gestire i thread a livello di programmazione.
Elenca tutti i thread (solo metadati):
GET /v1/threads
Restituisce { threads: [...] } per il profilo corrente con i messages rimossi (utilizza l'endpoint di dettaglio quando ne hai bisogno). Ogni altro campo viene preservato — id, title, createdAt, updatedAt, modeId, archived, statistiche di utilizzo, oltre a subAgentHistories, anonymizerSnapshot, threadToolApprovals, threadVariables, threadToolOverrides, messagingBinding, scheduledTaskId quando impostati. (Il payload più ricco è un'esclusiva dell'API — il broadcast della barra laterale via WebSocket utilizza una rimozione più stringente per rimanere entro i limiti di trasporto.)
Ottieni un thread con i messaggi completi:
GET /v1/threads/{id}
Restituisce il thread completo includendo il suo array messages — ogni messaggio dell'utente, risposta dell'assistente, chiamata a strumenti (tool call) e risultato degli strumenti (tool result).
Ottieni solo i messaggi:
GET /v1/threads/{id}/messages
Restituisce solo l'array messages — più leggero rispetto all'oggetto thread completo quando hai bisogno solo della conversazione.
Crea un thread:
POST /v1/threads
Content-Type: application/json
{ "title": "Research project", "modeId": "general" }
Restituisce 201 con { thread }. Il nuovo thread appare immediatamente nella barra laterale (tramite broadcast WebSocket). L'API non cambia mai il thread attivo dell'app al momento della creazione — chiama separatamente PUT /v1/threads/active se desideri farlo.
Aggiorna un thread:
PATCH /v1/threads/{id}
Content-Type: application/json
{ "title": "Renamed project", "archived": true }
Campi aggiornabili: title, modeId, archived, lastUsedModel. Le modifiche vengono trasmesse alla barra laterale in tempo reale.
Elimina un thread:
DELETE /v1/threads/{id}
Esegue una cancellazione logica (soft-delete) del thread (tombstone per la sincronizzazione). Restituisce 204. I thread eliminati vengono spostati nel cestino e possono essere recuperati finché il cestino non viene svuotato.
Thread attivo:
GET /v1/threads/active # Restituisce { threadId }
PUT /v1/threads/active # Body: { "threadId": "..." }
Gestione del cestino:
GET /v1/threads/trash/count # Restituisce { count }
POST /v1/threads/trash/empty # Restituisce { deletedCount, protectedCount }
I thread protetti (conservati tramite l'opzione di conservazione dei dati) sono esclusi dallo svuotamento del cestino.
Continuare una conversazione tramite l'API:
Per inviare un messaggio di follow-up a un thread esistente, usa POST /v1/runs con l'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"
}
L'agente visualizza l'intera cronologia della conversazione dal thread.
Allegati
Gli allegati sono file collegati ai thread — screenshot, PDF, documenti, immagini caricate, artefatti generati. L'API ti consente di elencarli, caricarli, scaricarli e gestirli.
Elenca tutti gli allegati (solo metadati):
GET /v1/attachments
Restituisce i metadati degli allegati per il profilo corrente. I campi pesanti (dataUrl, extractedContent, extractedImages) vengono rimossi — usa gli endpoint di dettaglio o contenuto per quelli.
Elenca allegati per un thread specifico:
GET /v1/threads/{threadId}/attachments
Ottieni metadati dell'allegato:
GET /v1/attachments/{id}
Restituisce i metadati completi inclusi extractedContent (testo OCR, markdown analizzato), contentType, fileName, size e un flag hasContent. Il binario grezzo NON è incluso — usa l'endpoint /content per quello.
Scarica il binario dell'allegato:
GET /v1/attachments/{id}/content
Restituisce il file grezzo con le intestazioni Content-Type e Content-Disposition corrette. Indirizzalo su un file:
curl -o output.pdf \
-H "Authorization: Bearer $API_TOKEN" \
http://localhost:3847/v1/attachments/{id}/content
Carica un allegato:
POST /v1/attachments
Content-Type: application/json
{
"threadId": "id-thread",
"type": "user_upload",
"contentType": "application/pdf",
"fileName": "report.pdf",
"description": "Report trimestrale",
"dataUrl": "data:application/pdf;base64,JVBERi0xLjQ..."
}
Il dataUrl è un URL di dati codificato in base64. Restituisce 201 con l'ID del nuovo allegato. L'allegato è collegato al thread specificato.
Aggiorna i metadati dell'allegato:
PATCH /v1/attachments/{id}
Content-Type: application/json
{ "description": "Descrizione aggiornata", "fileName": "nuovo-nome.pdf" }
Elimina un allegato:
DELETE /v1/attachments/{id}
Eliminazione logica tramite tombstone. Restituisce 204.
Server MCP
Gestisci le tue connessioni ai server MCP (Model Context Protocol) — i server che forniscono agli agenti l'accesso a strumenti esterni e fonti di dati.
Elenca i server configurati:
GET /v1/mcp-servers
Restituisce tutte le configurazioni dei server MCP per il profilo corrente. I campi sensibili (authToken, env, credentialId) vengono rimossi dalla risposta.
Ottieni la configurazione di un server:
GET /v1/mcp-servers/{id}
Aggiungi un nuovo server 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"
}
Per i server HTTP remoti, usa "url" invece di "command":
{
"id": "remote-server",
"name": "Remote API",
"url": "https://my-mcp-server.example.com/sse",
"serverType": "remote"
}
Campi opzionali accettati in POST: command, args, env, url, description, transportType, authType, authToken, authHeader, headers, specType, specPath, timeoutMs, credentialId, oauthConnectionId, approval. I campi gestiti dal server (customOAuth, hubPackageId, profileId, connectorId, teamPublished, teamOrgId, vectorClock, ...) non possono essere impostati tramite API.
Aggiorna un server:
PATCH /v1/mcp-servers/{id}
Content-Type: application/json
{ "name": "Renamed Server", "args": ["-y", "@mcp/server-v2"] }
I campi modificabili tramite patch rispecchiano la allowlist del metodo POST (inclusi credentialId e oauthConnectionId — utile per ruotare una connessione OAuth senza dover eliminare e ricreare). I campi gestiti dal server rimangono in sola lettura.
Abilita/disabilita un server:
POST /v1/mcp-servers/{id}/toggle
Content-Type: application/json
{ "enabled": false }
Elimina un server:
DELETE /v1/mcp-servers/{id}
Gestione dei Processi
Per i server MCP locali (stdio), è possibile gestire direttamente il processo del server.
Elenca i processi in esecuzione:
GET /v1/mcp-servers/processes
Restituisce i processi del server in esecuzione con pid, startedAt e lo stato running.
Avvia un server:
POST /v1/mcp-servers/{id}/start
Legge command/args/env dalla configurazione del server e avvia il processo. Restituisce lo stato del processo.
Ferma un server:
POST /v1/mcp-servers/{id}/stop
Arresta correttamente il processo del server (SIGTERM con fallback a SIGKILL).
Chiama direttamente un metodo JSON-RPC:
POST /v1/mcp-servers/{id}/call
Content-Type: application/json
{ "method": "tools/list", "params": {} }
Invia una richiesta JSON-RPC 2.0 grezza al server e restituisce il risultato. Utile per il debugging o per chiamare metodi non esposti tramite l'API degli strumenti.
Strumenti e Toolkit
Sfoglia e invoca gli strumenti utilizzati dagli agenti: navigazione web, ricerca, calendario, Gmail, Slate e altro ancora.
Elenca i toolkit (raggruppati):
GET /v1/toolkits
Restituisce gli strumenti integrati raggruppati per categoria (Produttività, Ricerca, Utility, ecc.) e tutti i server MCP connessi come toolkit separati, ciascuno con l'elenco delle proprie azioni.
Elenca tutti gli strumenti (elenco piatto):
GET /v1/tools
GET /v1/tools?source=embedded # Solo strumenti integrati
GET /v1/tools?source=mcp # Solo strumenti del server MCP
Ottieni i dettagli dello strumento con lo schema di input:
GET /v1/tools/calculator
Restituisce { tool: { name, displayName, description, source, category, inputSchema, actions?, requiredTier?, requiredRuntimes?, riskTier?, riskExplanation?, requiresApproval? } }.
| Campo | Significato |
|---|---|
inputSchema |
Schema JSON per l'input dello strumento — da validare prima dell'invocazione |
actions |
Sotto-azioni opzionali (es. Slate read/write); ognuna ha id, displayName, description, requiredTier opzionale |
requiredTier |
Livello utente minimo (free se omesso). L'invocazione tramite API pubblica rifiuta qualsiasi livello superiore a free |
requiredRuntimes |
Piattaforme in cui questo strumento è disponibile (macos, ios, ecc.); omettere ⇒ ovunque |
riskTier |
Rischio di consenso: low (predefinito), medium, high |
riskExplanation |
Motivo leggibile dall'utente per cui il riskTier è elevato |
requiresApproval |
true quando lo strumento richiede l'approvazione dell'utente per ogni chiamata — l'invocazione tramite API pubblica li rifiuta |
Invoca uno strumento direttamente:
POST /v1/tools/calculator/invoke
Content-Type: application/json
{ "input": { "expression": "sqrt(144) + 3^2" }, "threadId": "optional-thread-id" }
Restituisce { result }. L'input viene validato rispetto allo schema dello strumento — un input non valido restituisce 422 con i dettagli. Passa un threadId opzionale se lo strumento necessita di un contesto limitato al thread (es. ricerca di allegati).
Gating — cosa rifiuta l'API pubblica:
- Strumenti limitati per livello (
metadata.requiredTier !== 'free') →403. Il ciclo dell'agente controlla il livello rispetto alla sessione dell'utente; l'API pubblica non ha un contesto di livello trasportato, quindi la politica conservativa è il rifiuto. Utilizza invecePOST /v1/runscon un agente che abbia il livello corretto. - Strumenti che richiedono approvazione (
metadata.approval.requiresApproval === true) →403. Non c'è un essere umano nel ciclo a cui chiedere. Invoca tramitePOST /v1/runs(che mostra la richiesta all'utente) o imposta la modalità di approvazione dello strumento suapprove_allnell'app per bypassare. - Strumenti MCP remoti →
501con indicazione di utilizzare/v1/runs(richiedono il trasporto del sottoprocesso dell'agente).
Strumenti di visione e che utilizzano immagini: carica prima tramite POST /v1/attachments, quindi passa l'ID dell'allegato restituito all'interno di input (es. { "input": { "attachment_id": "att_abc", "prompt": "Cosa c'è in questa immagine?" } }). Lo strumento legge il binario dallo storage tramite threadId; non passare i byte inline.
Connettori
Gestisci le integrazioni OAuth — Google, Microsoft, GitHub, Notion, Slack e altro.
Sfoglia le integrazioni disponibili:
GET /v1/connectors/catalog
Restituisce tutti i provider OAuth registrati con il loro nome, categoria e scope predefiniti.
Elenca i tuoi account connessi:
GET /v1/connectors
Restituisce le connessioni attive per il profilo corrente. I token non vengono mai esposti — solo i metadati (provider, email, stato, scope, timestamp).
Ottieni una singola connessione:
GET /v1/connectors/{id}
Restituisce i metadati per una connessione. I token non vengono mai esposti.
Verifica lo stato della connessione:
POST /v1/connectors/{id}/test
Restituisce { health: { status, isTokenExpired, canRefresh } }.
Rimuovi una connessione:
DELETE /v1/connectors/{id}
La creazione di nuove connessioni richiede il flusso OAuth interattivo tramite l'interfaccia dell'app o le rotte /auth/*.
Trigger
Pianifica l'esecuzione automatica degli agenti — briefing quotidiani, report settimanali, monitoraggio a intervalli.
Ogni trigger ha un discriminatore kind: schedule (predefinito — si attiva in base all'orario), webhook (si attiva quando un servizio esterno invia un POST al percorso del webhook) o messaging (si attiva da un adattatore di messaggistica connesso — es. messaggi Slack/Discord in entrata che corrispondono a un filtro di canale).
Elenca i trigger:
GET /v1/triggers
Restituisce { triggers: [...] }.
Ottieni un singolo trigger:
GET /v1/triggers/{id}
Crea un trigger pianificato:
POST /v1/triggers
Content-Type: application/json
{
\"name\": \"Briefing Mattutino\",
\"prompt\": \"Riassumi le mie email non lette e il calendario di oggi\",
\"modeId\": \"general\",
\"schedule\": { \"type\": \"daily\", \"time\": \"08:00\" }
}
Tipi di pianificazione supportati:
{ \"type\": \"interval\", \"minutes\": 60 }— ogni N minuti (min 15, max 1440){ \"type\": \"daily\", \"time\": \"09:00\" }— giornaliero a un orario specifico{ \"type\": \"weekly\", \"day\": \"mon\", \"time\": \"09:00\" }— settimanale{ \"type\": \"weekdays\", \"time\": \"08:30\" }— dal lunedì al venerdì{ \"type\": \"daysOfWeek\", \"days\": [\"mon\", \"wed\", \"fri\"], \"time\": \"10:00\" }— giorni specifici{ \"type\": \"monthly\", \"dayOfMonth\": 1, \"time\": \"09:00\" }— mensile{ \"type\": \"manual\" }— solo se attivato tramite API
Attiva un trigger manualmente:
POST /v1/triggers/{id}/fire
Restituisce 202 con un threadId per l'esecuzione risultante.
Aggiorna o elimina:
PATCH /v1/triggers/{id}
DELETE /v1/triggers/{id}
Webhook
I trigger webhook consentono a servizi esterni (CI/CD, monitoraggio, form builder) di attivare l'esecuzione di un agente tramite HTTP.
Crea un trigger webhook:
POST /v1/triggers
Content-Type: application/json
{
\"name\": \"Deploy hook\",
\"prompt\": \"È avvenuto un deploy: {{webhook.body}}\",
\"modeId\": \"general\",
\"kind\": \"webhook\"
}
Restituisce 201 con un webhookSecret e webhookPath. Conserva il segreto — ti servirà per firmare i payload.
Invia un webhook:
# Calcola HMAC-SHA256 del corpo della richiesta raw
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\"}
L'endpoint del webhook NON richiede l'autenticazione bearer — utilizza invece la verifica HMAC. Restituisce 202 con il threadId dell'esecuzione avviata. Il segnaposto {{webhook.body}} nel prompt del trigger viene sostituito con il corpo della richiesta raw.
Trigger di messaggistica
I trigger di messaggistica si attivano quando un adattatore di messaggistica connesso (es. un'integrazione Slack o Discord installata tramite l'Hub della Community) riceve un messaggio in entrata che corrisponde al filtro del trigger. Crea con kind: \"messaging\":
POST /v1/triggers
Content-Type: application/json
{
\"name\": \"Risponditore menzioni\",
\"prompt\": \"Rispondi in modo utile a: {{message.text}}\",
\"modeId\": \"general\",
\"kind\": \"messaging\",
\"messagingAdapterId\": \"slack-team-acme\",
\"messagingChannelFilter\": \"#support\"
}
L'adattatore è responsabile dell'invio degli eventi corrispondenti al trigger; messagingChannelFilter è specifico per l'adattatore.
Funzioni Personalizzate
Crea i tuoi strumenti che gli agenti possono chiamare. Le funzioni sono scritte in JavaScript o Python ed eseguite in una sandbox.
Elenca funzioni:
GET /v1/functions
Crea una funzione:
POST /v1/functions
Content-Type: application/json
{
"name": "calcola_bmi",
"description": "Calcola l'Indice di Massa Corporea da altezza e peso",
"language": "javascript",
"source": "return { bmi: (input.weightKg / (input.heightM * input.heightM)).toFixed(1) };",
"inputSchema": {
"type": "object",
"properties": {
"weightKg": { "type": "number" },
"heightM": { "type": "number" }
},
"required": ["weightKg", "heightM"]
}
}
Le funzioni JavaScript ricevono input e devono restituire un risultato. Le funzioni Python impostano una variabile result:
# Esempio Python
result = {"bmi": round(input["weightKg"] / (input["heightM"] ** 2), 1)}
Esegui una funzione direttamente:
POST /v1/functions/{id}/execute
Content-Type: application/json
{ "input": { "weightKg": 75, "heightM": 1.80 } }
Sicurezza: JavaScript viene eseguito nella sandbox vm di Node (nessun accesso al filesystem o alla rete, timeout di 10s). Python viene eseguito come sottoprocesso con un timeout di 30s. Entrambi validano l'input prima dell'esecuzione.
Aggiorna o elimina:
PATCH /v1/functions/{id}
DELETE /v1/functions/{id}
Skill
Le Skill sono prompt salvati a cui gli agenti possono fare riferimento e che possono avviare rapidamente dalla visualizzazione di conversazione vuota. Le skill installate tramite Hub (gestite tramite installazione di pacchetti) NON sono incluse qui — solo le skill create dall'utente sono elencate e modificabili.
Elenco skill:
GET /v1/skills
Restituisce { skills: [...] } delle skill create dall'utente per il profilo attivo. Le skill eliminate (tombstoned), quelle sovrapposte dall'hub e le skill ombra di sincronizzazione vengono filtrate.
Ottieni una skill:
GET /v1/skills/{id}
Crea una skill:
POST /v1/skills
Content-Type: application/json
{
"prompt": "Riassumi la pagina in 3 punti elenco.",
"tags": ["utility", "summarize"],
"isFavorite": true,
"modes": ["general"],
"displayName": "Riassunto Rapido",
"description": "TL;DR in tre punti della pagina attiva"
}
Solo prompt è richiesto. modes (opzionale) limita la skill a specifici ID agente; omettere per tutte le modalità. Restituisce 201 con la nuova skill (inclusi id, createdAt, updatedAt assegnati dal server).
Aggiorna una skill:
PATCH /v1/skills/{id}
Content-Type: application/json
{ "prompt": "Prompt aggiornato", "isFavorite": false }
Campi modificabili: prompt, tags, modes, displayName, description, isFavorite. I tentativi di modificare una skill sovrapposta dall'hub restituiscono 404.
Elimina una skill:
DELETE /v1/skills/{id}
Eliminazione logica tramite tombstone. Restituisce 204. Le skill sovrapposte dall'hub restituiscono 404 — disinstalla invece il pacchetto sorgente.
Workflow
Orchestra più agenti in un DAG (grafo aciclico diretto): esegui i passaggi in parallelo quando possibile e inserisci gli output dei passaggi precedenti in quelli successivi.
Validare il grafo di un workflow:
POST /v1/workflows/validate
Content-Type: application/json
{
"graph": {
"nodes": [
{ "id": "research", "agentId": "general", "prompt": "Ricerca le tendenze delle energie rinnovabili" },
{ "id": "analyze", "agentId": "general", "prompt": "Ricerca i prezzi della concorrenza" },
{ "id": "report", "agentId": "general", "prompt": "Scrivi un report combinando: {{outputs.research}} e {{outputs.analyze}}", "dependsOn": ["research", "analyze"] }
]
}
}
Restituisce { valid: true/false, errors: [...] }. Controlla la presenza di cicli, ID duplicati e riferimenti a dipendenze mancanti.
Eseguire un workflow:
POST /v1/workflows/execute
Content-Type: application/json
{
"graph": {
"nodes": [
{ "id": "research", "agentId": "general", "prompt": "Ricerca le tendenze delle energie rinnovabili" },
{ "id": "summarize", "agentId": "general", "prompt": "Riassumi: {{outputs.research}}", "dependsOn": ["research"] }
]
}
}
Restituisce { status: "completed", outputs: { research: "...", summarize: "..." }, nodeResults: {...} }.
I nodi indipendenti (senza dipendenze condivise) vengono eseguiti in parallelo. Il segnaposto {{outputs.nodeId}} nel prompt di un nodo viene sostituito con l'output del contenuto del nodo a monte specificato. Ogni nodo è un'esecuzione completa dell'agente, quindi può utilizzare strumenti, navigare sul web e accedere a tutte le funzionalità dell'agente di destinazione.
Basi di Conoscenza
Organizza i documenti in raccolte ricercabili a cui gli agenti possono fare riferimento.
Elenca basi di conoscenza:
GET /v1/knowledge/bases
Crea una base di conoscenza:
POST /v1/knowledge/bases
Content-Type: application/json
{ "name": "Documenti di Ricerca" }
Restituisce 201 con l'ID della nuova base.
Carica un documento in una base di conoscenza:
POST /v1/knowledge/bases/{id}/documents
Content-Type: application/json
{
"fileName": "ricerca.pdf",
"contentType": "application/pdf",
"dataUrl": "data:application/pdf;base64,JVBERi0xLjQ...",
"description": "Tendenze energie rinnovabili 2026"
}
Il campo dataUrl è un URL di dati codificato in base64. Restituisce 201 con i metadati del documento.
Elenca documenti in una base di conoscenza:
GET /v1/knowledge/bases/{id}/documents
Cerca all'interno di una base di conoscenza:
POST /v1/knowledge/bases/{id}/search
Content-Type: application/json
{ "query": "energia rinnovabile" }
Restituisce i documenti corrispondenti in base al nome del file e alla descrizione. La ricerca semantica (vettoriale) sarà disponibile in una versione futura.
Elimina un documento o una base di conoscenza:
DELETE /v1/knowledge/bases/{id}/documents/{docId}
DELETE /v1/knowledge/bases/{id}
Esportazione e Importazione Agenti
Condividi gli agenti come pacchetti portatili — tra dispositivi, team o il Community Hub.
Esporta un agente:
POST /v1/agents/{id}/export
Restituisce un pacchetto JSON contenente la definizione dell'agente, i requisiti degli strumenti (derivati dagli strumenti abilitati), i requisiti dei connettori (quali fornitori OAuth sono necessari) e i template dei trigger. I metadati di sincronizzazione vengono rimossi — il pacchetto è un progetto pulito e autonomo.
Importa un agente:
POST /v1/agents/import
Content-Type: application/json
{
\"package\": {
\"$schema\": \"caiioo.agent.package/v1\",
\"agent\": {
\"id\": \"agente-ricerca-condiviso\",
\"branding\": { \"name\": \"Agente di Ricerca\", \"description\": \"Dal team\" },
\"defaultSettings\": { \"systemPrompt\": \"Fai ricerche su vari argomenti.\" },
\"settingLevels\": {}
},
\"toolRequirements\": [
{ \"toolId\": \"web_browsing\", \"enabled\": true },
{ \"toolId\": \"search_tools\", \"enabled\": true }
]
}
}
Restituisce 201 con l'agente installato. Le collisioni di ID con agenti integrati o esistenti restituiscono 409.
Gestione degli Errori
L'API utilizza codici di stato HTTP standard:
| Codice | Significato |
|---|---|
200 |
Successo |
201 |
Creato |
202 |
Accettato (operazione asincrona avviata) |
204 |
Eliminato (nessun contenuto) |
400 |
Richiesta errata — controlla il campo error per i dettagli |
401 |
Non autorizzato — segreto di sessione mancante o non valido |
403 |
Proibito — ad es. tentativo di modificare un agente predefinito |
404 |
Non trovato |
409 |
Conflitto — ad es. l'ID dell'agente esiste già |
422 |
Errore di validazione — l'input non corrisponde allo schema dello strumento |
429 |
Limite di frequenza superato — vedi i budget di rate-limit nella sezione Autenticazione |
500 |
Errore del server — controlla il campo error |
501 |
Non implementato — la funzionalità esiste ma non è disponibile in questo modo |
503 |
Servizio non disponibile — archiviazione o provider non pronti |
Tutte le risposte di errore includono { "error": "messaggio leggibile dall'utente" }.
Esempio di Avvio Rapido
Ecco un workflow completo: crea un agente, eseguilo e trasmetti i risultati in streaming.
# 1. Crea un agente personalizzato
curl -X POST http://localhost:3847/v1/agents \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"id": "riassuntore-rapido",
"branding": { "name": "Riassuntore Rapido" },
"defaultSettings": {
"systemPrompt": "Riassumi qualsiasi input in modo conciso in 3 punti elenco.",
"enabledTools": { "web_browsing": true }
},
"settingLevels": {}
}'
# 2. Eseguilo in modo asincrono
RUN=$(curl -s -X POST http://localhost:3847/v1/runs \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "agentId": "riassuntore-rapido", "input": { "message": "Riassumi https://it.wikipedia.org/wiki/Intelligenza_artificiale" }, "mode": "async" }')
RUN_ID=$(echo $RUN | jq -r '.runId')
# 3. Streaming degli eventi
curl -N http://localhost:3847/v1/runs/$RUN_ID/events \
-H "Authorization: Bearer $API_TOKEN"
# 4. Esporta l'agente per la condivisione
curl -X POST http://localhost:3847/v1/agents/riassuntore-rapido/export \
-H "Authorization: Bearer $API_TOKEN"
This guide is maintained by the Caiioo team using Slate, our built-in editor.