Dies ist eine maschinelle Übersetzung des englischen Originaldokuments. Im Falle von Widersprüchen zwischen dieser Übersetzung und der englischen Originalversion ist die englische Version maßgeblich. Englische Originalversion lesen


Öffentliche API

Caiioo enthält eine REST-API, mit der Sie alles programmatisch steuern können: Agenten ausführen, Tools verwalten, Aufgaben planen und mehr. Die API läuft auf demselben lokalen Server, der auch die Desktop-App und die Browser-Bridge antreibt.

Basis-URL: http://localhost:3847/v1

Authentifizierung: Zwei Wege zur Authentifizierung, beide über den API-Schalter in den Einstellungen gesteuert:

Für externe Konsumenten (Skripte, Integrationen, curl): Legen Sie ein API-Zugriffstoken in Einstellungen > API-Zugriff fest und verwenden Sie es als Bearer-Token:

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

Für die lokale App (automatisch): Die Caiioo Desktop-App, Browser-Erweiterungen und mobilen Apps authentifizieren sich automatisch über den vorhandenen Relay-Auth-Header (x-relay-auth; HTTP-Header sind Case-Insensitive). Keine manuelle Einrichtung erforderlich – die App erledigt dies im Hintergrund. Relay-Auth-Anfragen umgehen den Schalter „Öffentliche API aktivieren“, da sie bereits vertrauenswürdig sind; nur Bearer-Token-Anfragen werden durch den Schalter gesteuert.

Einrichtung:

  1. Öffnen Sie Caiioo Einstellungen > API-Zugriff
  2. Schalten Sie Öffentliche API aktivieren ein
  3. Legen Sie ein API-Zugriffstoken fest (eine beliebige Zeichenfolge – behandeln Sie sie wie ein Passwort)
  4. Verwenden Sie dieses Token in allen API-Anfragen

Die API ist auf localhost und über das private Relay verfügbar. Überprüfen Sie GET /v1/auth/info (keine Authentifizierung erforderlich) für den aktuellen Status und Einrichtungsanweisungen.

Ratelimits: Jede /v1/* Anfrage ist pro Client-IP limitiert – 100 GET-Anfragen pro Minute für Lesezugriffe und insgesamt 30 Schreib-Anfragen pro Minute (POST / PATCH / DELETE). Anfragen über dem Limit erhalten einen 429-Fehler. Webhook-Zustellungen (POST /v1/webhooks/:id) sind nicht Bearer-authentifiziert und unterliegen nicht diesen Limits.

Profile

Ein einzelnes Gerät kann mehrere Benutzerprofile enthalten (z. B. Privat + Arbeit). Die API ermöglicht es externen Skripten, die verfügbaren Profile zu prüfen und das aktive Profil zu wechseln, bevor andere Aufgaben ausgeführt werden. Das Erstellen, Aktualisieren und Löschen von Profilen wird bewusst nicht über die öffentliche API angeboten — diese Abläufe gehören in die Onboarding-Benutzeroberfläche der App.

Profile auflisten:

GET /v1/profiles

Gibt { profiles: [...] } mit einem Eintrag pro nicht gelöschtem Profil zurück. Jeder Eintrag enthält id, name, email, avatarUrl, tier, accessibleModes, license, organization, preferences, onboardingComplete, createdAt, lastAccessedAt. Token-haltige Felder (serviceCredentials, oauthConnections) und Synchronisations-Interna (vectorClock, lastModifiedBy) werden entfernt. Verwenden Sie /v1/connectors, um OAuth-Verbindungen zu prüfen.

Aktives Profil abrufen:

GET /v1/profiles/active

Gibt { profile } für das aktuell von diesem Server verwendete Profil zurück. Alle /v1/*-Ressourcen, die auf ein Profil bezogen sind (Threads, Anhänge, Einstellungen, Skills), beziehen sich auf dieses Profil.

Aktives Profil wechseln:

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

{ "profileId": "user-uuid-aus-der-liste" }

Gibt { profile } für das neu aktivierte Profil zurück. Gibt 404 zurück, wenn die ID kein bekanntes Profil ist.

Providers & Models

Entdecken Sie, welche LLM-Provider konfiguriert sind und welche Modelle zur Verfügung stehen.

Provider auflisten:

GET /v1/providers

Gibt jeden unterstützten Provider-Typ zurück. Derzeit: anthropic, openai, google, openrouter, ollama, poe, mlx, perplexity, baseten, cloudflare. Jeder Eintrag enthält type, displayName, icon, requiresApiKey, hasApiKey sowie ein capabilities-Objekt mit den unten aufgeführten Flags.

Capability-Flag Bedeutung
supportsVision Provider kann Bild-Inputs verarbeiten
supportsPdfFile Provider kann native PDF-Datei-Content-Blöcke akzeptieren
supportsToolCalling Provider unterstützt Funktions-/Tool-Aufrufe
supportsStreaming Provider überträgt Tokens inkrementell per Streaming
supportsExtendedThinking Provider bietet ein Budget für Reasoning/Thinking an
supportsPromptCaching Provider unterstützt Prompt-Caching-Direktiven
nativeReasoningBlocks Provider gibt Denkprozesse als native Nachrichtenblöcke aus (statt als Text)
requiresThoughtSignature Provider erfordert, dass signierte Thought-Tokens zurückgesendet werden

Die Capability-Flags spiegeln das Feld readonly capabilities der jeweiligen Provider-Klasse wider (siehe src/shared/providers/*-provider.ts) und werden durch einen Drift-Sentinel-Test validiert — rufen Sie diesen Endpunkt zur Laufzeit auf, anstatt die Matrix fest im Code zu hinterlegen.

Hinweise für BYOK-Provider:

  • perplexity stellt eine kuratierte Liste von Sonar-Modellen bereit (Perplexity verfügt über keinen öffentlichen /models-Endpunkt).
  • cloudflare (AI Gateway) ist BYOK + Multi-Vendor; die Modellliste wird durch Ihre Gateway-Konfiguration bestimmt und von /v1/providers/cloudflare/models als leeres Array zurückgegeben. Verwenden Sie Ihren eigenen Gateway-Katalog.

Modelle eines Providers auflisten:

GET /v1/providers/openrouter/models

Gibt den Modellkatalog für diesen Provider zurück. Jedes Modell enthält id, displayName und, sofern verfügbar, contextLength. Gibt 503 zurück, wenn dem Provider ein API-Key fehlt oder sein Upstream-Katalog nicht erreichbar ist.

Gesamtkatalog über alle Provider hinweg:

GET /v1/models

Führt die Modelle aller konfigurierten Provider in einer Liste zusammen. Provider ohne API-Keys werden übersprungen und unter warnings aufgeführt.

Agenten

Agenten sind das Herzstück von caiioo. Jeder Agent ist ein Modus — eine konfigurierte Persönlichkeit mit eigenem System-Prompt, Tools, Variablen und Skills.

Alle Agenten auflisten:

GET /v1/agents

Gibt integrierte Agenten (Shopping, Arbeitsplatz, Allgemein) und alle von Ihnen erstellten benutzerdefinierten Agenten zurück. Jeder ist mit source: \"builtin\" oder source: \"custom\" markiert.

Einen benutzerdefinierten Agenten erstellen:

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

{
  \"id\": \"mein-forschungs-agent\",
  \"branding\": {
    \"name\": \"Forschungs-Agent\",
    \"description\": \"Durchsucht das Web und fasst Ergebnisse zusammen\"
  },
  \"defaultSettings\": {
    \"systemPrompt\": \"Du bist ein Forschungsassistent. Zitiere immer Quellen.\",
    \"enabledTools\": { \"web_browsing\": true, \"search_tools\": true }
  },
  \"settingLevels\": {}
}

Gibt 201 mit dem erstellten Agenten zurück. Eine Vector Clock wird für die Synchronisierung automatisch angehängt.

Einen Agenten aktualisieren:

PATCH /v1/agents/mein-forschungs-agent
Content-Type: application/json

{ \"branding\": { \"name\": \"Forschungs-Agent\", \"description\": \"Aktualisierte Beschreibung\" } }

Führt den Patch in den bestehenden Agenten zusammen und erhöht die Vector Clock. Integrierte Agenten geben 403 zurück — sie sind schreibgeschützt.

Einen Agenten löschen:

DELETE /v1/agents/mein-forschungs-agent

Führt einen Soft-Delete via Tombstone durch (synchronisiert über Geräte). Gibt 204 zurück.

Ausführen von Agenten

Dies ist das Hauptereignis — rufen Sie einen Agenten auf, um eine Nachricht zu verarbeiten.

Request body — unterstützte Felder

Feld Erforderlich Beschreibung
agentId ja ID des integrierten Modus (z. B. general) oder eine benutzerdefinierte Agent-ID
input.message ja Text der Benutzernachricht
input.attachments nein Array von Attachment-IDs (bereits über /v1/attachments hochgeladen), die diesem Turn beigefügt werden sollen
input.variables nein Variablen-Overrides pro Durchlauf, die in den Variablen-Resolver des Agenten eingefügt werden
input.tabContext nein Freiform-String, der als Seitenkontext injiziert wird (verwendet von der Browser-Bridge)
input.messageId nein Vom Client bereitgestellte Nachrichten-ID — nützlich für die Deduplizierung bei Wiederholungsversuchen
threadId nein Bestehender Thread, der fortgesetzt werden soll. Falls weggelassen, wird ein neuer Thread erstellt und zurückgegeben
mode nein "sync" oder "async". Standardwert ist "async"

Synchroner Modus

Warten Sie auf die vollständige Antwort:

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

{
  "agentId": "general",
  "input": { "message": "Wie ist das Wetter heute in Paris?" },
  "mode": "sync"
}

Gibt 200 mit { content, usage, status: "completed" } zurück, nachdem der Agent fertig ist. Wenn der Agent einen Fehler verursacht, wird 500 mit { error, status: "error" } zurückgegeben. Synchrone Durchläufe werden nach 5 Minuten mit status: "error" abgebrochen, wenn kein terminales Ereignis empfangen wird — verwenden Sie async + SSE für alles, was länger dauern könnte.

Asynchroner Modus

Fire-and-Forget — nützlich für lang laufende Aufgaben:

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

{
  "agentId": "my-research-agent",
  "input": { "message": "Schreibe eine 2000 Wörter umfassende Analyse der Trends bei erneuerbaren Energien" },
  "mode": "async"
}

Gibt sofort 202 mit { runId, threadId, status: "running" } zurück.

Status abfragen (Polling):

GET /v1/runs/{runId}

Gibt { run: { runId, threadId, agentId, status, createdAt, content?, usage?, error? } } zurück. Der Status ist einer von running, completed, error oder cancelled.

Ereignisse in Echtzeit streamen (SSE):

GET /v1/runs/{runId}/events

Gibt einen text/event-stream mit jedem Agenten-Ereignis zurück, sobald es eintritt: GENERATION_STARTED, STREAMING_CONTENT, Tool-Aufrufe, Subagent-Aktivitäten und das terminale Ereignis (GENERATION_COMPLETE, GENERATION_ERROR oder GENERATION_CANCELLED).

Nach dem terminalen Ereignis sendet der Server einen letzten SSE-Frame mit event: terminal und einem leeren Daten-Payload als explizites Ende-des-Streams-Signal und schließt dann die Verbindung. Clients sollten den Empfang dieses Frames (oder das Schließen der Verbindung) als Signal zum Beenden des Lesevorgangs behandeln.

Wenn Sie sich anmelden, nachdem der Durchlauf bereits beendet ist, spielt der Server einen Frame vom Typ RUN_SNAPSHOT ab, der den vollständigen finalen record enthält, gefolgt vom event: terminal Signal, und schließt dann die Verbindung.

Einen Durchlauf abbrechen:

POST /v1/runs/{runId}/cancel

Gibt { run: { ..., status: "cancelled" } } zurück.

Threads

Threads sind Konversationen. Jeder Agent-Durchlauf findet innerhalb eines Threads statt, und Threads bleiben über Sitzungen hinweg bestehen. Die API ermöglicht es Ihnen, Threads programmatisch aufzulisten, zu lesen, zu erstellen und zu verwalten.

Alle Threads auflisten (nur Metadaten):

GET /v1/threads

Gibt { threads: [...] } für das aktuelle Profil zurück, wobei messages entfernt wurden (verwenden Sie den Detail-Endpunkt, wenn Sie diese benötigen). Jedes andere Feld bleibt erhalten — id, title, createdAt, updatedAt, modeId, archived, Nutzungsstatistiken, plus subAgentHistories, anonymizerSnapshot, threadToolApprovals, threadVariables, threadToolOverrides, messagingBinding, scheduledTaskId, sofern gesetzt. (Die umfangreichere Payload ist exklusiv für die API — der WebSocket-Sidebar-Broadcast verwendet eine stärkere Reduzierung, um unter den Übertragungslimits zu bleiben.)

Einen Thread mit vollständigen Nachrichten abrufen:

GET /v1/threads/{id}

Gibt den vollständigen Thread einschließlich seines messages-Arrays zurück — jede Benutzernachricht, Assistant-Antwort, jeder Tool-Aufruf und jedes Tool-Ergebnis.

Nur die Nachrichten abrufen:

GET /v1/threads/{id}/messages

Gibt nur das messages-Array zurück — schlanker als das vollständige Thread-Objekt, wenn Sie nur die Konversation benötigen.

Einen Thread erstellen:

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

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

Gibt 201 mit { thread } zurück. Der neue Thread erscheint sofort in der Sidebar (via WebSocket-Broadcast). Die API wechselt beim Erstellen niemals den aktiven Thread der App — rufen Sie separat PUT /v1/threads/active auf, falls dies gewünscht ist.

Einen Thread aktualisieren:

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

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

Aktualisierbare Felder: title, modeId, archived, lastUsedModel. Änderungen werden in Echtzeit an die Sidebar übertragen.

Einen Thread löschen:

DELETE /v1/threads/{id}

Führt ein Soft-Delete des Threads aus (Tombstone für die Synchronisation). Gibt 204 zurück. Gelöschte Threads werden in den Papierkorb verschoben und können wiederhergestellt werden, bis der Papierkorb geleert wird.

Aktiver Thread:

GET /v1/threads/active            # Gibt { threadId } zurück
PUT /v1/threads/active            # Body: { "threadId": "..." }

Papierkorb-Verwaltung:

GET /v1/threads/trash/count       # Gibt { count } zurück
POST /v1/threads/trash/empty      # Gibt { deletedCount, protectedCount } zurück

Geschützte Threads (die über die Datenrückhalte-Option beibehalten werden) sind vom Leeren des Papierkorbs ausgeschlossen.

Fortsetzen einer Konversation über die API: Um eine Folgenachricht an einen bestehenden Thread zu senden, verwenden Sie POST /v1/runs mit der ID des Threads:

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

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

Der Agent sieht den vollständigen Konversationsverlauf aus dem Thread.

Anhänge

Anhänge sind Dateien, die mit Threads verknüpft sind – Screenshots, PDFs, Dokumente, hochgeladene Bilder, generierte Artefakte. Die API ermöglicht es Ihnen, diese aufzulisten, hochzuladen, herunterzuladen und zu verwalten.

Alle Anhänge auflisten (nur Metadaten):

GET /v1/attachments

Gibt Anhang-Metadaten für das aktuelle Profil zurück. Umfangreiche Felder (dataUrl, extractedContent, extractedImages) werden entfernt – verwenden Sie dafür die Detail- oder Inhalts-Endpunkte.

Anhänge für einen bestimmten Thread auflisten:

GET /v1/threads/{threadId}/attachments

Anhang-Metadaten abrufen:

GET /v1/attachments/{id}

Gibt vollständige Metadaten zurück, einschließlich extractedContent (OCR-Text, geparstes Markdown), contentType, fileName, size und ein hasContent-Flag. Die rohe Binärdatei ist NICHT enthalten – verwenden Sie dafür den /content-Endpunkt.

Binärdatei eines Anhangs herunterladen:

GET /v1/attachments/{id}/content

Gibt die Rohdatei mit den korrekten Headern für Content-Type und Content-Disposition zurück. Leiten Sie dies in eine Datei um:

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

Einen Anhang hochladen:

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

{
  "threadId": "thread-id",
  "type": "user_upload",
  "contentType": "application/pdf",
  "fileName": "bericht.pdf",
  "description": "Quartalsbericht",
  "dataUrl": "data:application/pdf;base64,JVBERi0xLjQ..."
}

Die dataUrl ist eine base64-kodierte Daten-URL. Gibt 201 mit der neuen Anhang-ID zurück. Der Anhang wird mit dem angegebenen Thread verknüpft.

Anhang-Metadaten aktualisieren:

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

{ "description": "Aktualisierte Beschreibung", "fileName": "neuer-name.pdf" }

Einen Anhang löschen:

DELETE /v1/attachments/{id}

Soft-Delete via Tombstone. Gibt 204 zurück.

MCP-Server

Verwalten Sie Ihre MCP (Model Context Protocol) Server-Verbindungen — die Server, die Agenten Zugriff auf externe Tools und Datenquellen ermöglichen.

Konfigurierte Server auflisten:

GET /v1/mcp-servers

Gibt alle MCP-Server-Konfigurationen für das aktuelle Profil zurück. Sensible Felder (authToken, env, credentialId) werden aus der Antwort entfernt.

Konfiguration eines Servers abrufen:

GET /v1/mcp-servers/{id}

Einen neuen MCP-Server hinzufügen:

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"
}

Verwenden Sie für Remote-HTTP-Server "url" anstelle von "command":

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

Akzeptierte optionale Felder bei POST: command, args, env, url, description, transportType, authType, authToken, authHeader, headers, specType, specPath, timeoutMs, credentialId, oauthConnectionId, approval. Vom Server verwaltete Felder (customOAuth, hubPackageId, profileId, connectorId, teamPublished, teamOrgId, vectorClock, ...) können nicht über die API gesetzt werden.

Einen Server aktualisieren:

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

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

Die über Patch änderbaren Felder entsprechen der POST-Allowlist (einschließlich credentialId und oauthConnectionId — praktisch für die Rotation einer OAuth-Verbindung ohne Löschen und Neuerstellen). Vom Server verwaltete Felder bleiben schreibgeschützt.

Einen Server aktivieren/deaktivieren:

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

{ "enabled": false }
}

Einen Server löschen:

DELETE /v1/mcp-servers/{id}

Prozessverwaltung

Für lokale (stdio) MCP-Server können Sie den Serverprozess direkt verwalten.

Laufende Prozesse auflisten:

GET /v1/mcp-servers/processes

Gibt laufende Serverprozesse mit pid, startedAt und dem Status running zurück.

Einen Server starten:

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

Liest command/args/env aus der Serverkonfiguration und startet den Prozess. Gibt den Prozessstatus zurück.

Einen Server stoppen:

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

Beendet den Serverprozess ordnungsgemäß (SIGTERM mit Fallback auf SIGKILL).

Eine JSON-RPC-Methode direkt aufrufen:

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

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

Sendet eine rohe JSON-RPC 2.0-Anfrage an den Server und gibt das Ergebnis zurück. Nützlich für das Debugging oder den Aufruf von Methoden, die nicht über die Tools-API bereitgestellt werden.

Tools & Toolkits

Durchsuchen und rufen Sie die Tools auf, die Agenten verwenden — Web-Browsing, Suche, Kalender, Gmail, Slate und mehr.

Toolkits auflisten (gruppiert):

GET /v1/toolkits

Gibt eingebettete Tools gruppiert nach Kategorie (Produktivität, Suche, Dienstprogramme usw.) und alle verbundenen MCP-Server als separate Toolkits zurück, jeweils mit ihren aufgelisteten Aktionen.

Alle Tools auflisten (flach):

GET /v1/tools
GET /v1/tools?source=embedded   # Nur integrierte Tools
GET /v1/tools?source=mcp        # Nur MCP-Server-Tools

Tool-Details mit Eingabeschema abrufen:

GET /v1/tools/calculator

Gibt { tool: { name, displayName, description, source, category, inputSchema, actions?, requiredTier?, requiredRuntimes?, riskTier?, riskExplanation?, requiresApproval? } } zurück.

Feld Bedeutung
inputSchema JSON-Schema für die Eingabe des Tools — vor dem Aufruf validieren
actions Optionale Unteraktionen (z. B. Slate read/write); jede hat id, displayName, description, optional requiredTier
requiredTier Mindest-User-Tier (free, falls weggelassen). Public-API-Aufrufe lehnen alles über free ab
requiredRuntimes Plattformen, auf denen dieses Tool verfügbar ist (macos, ios, etc.); weglassen ⇒ überall
riskTier Zustimmungsrisiko: low (Standard), medium, high
riskExplanation Menschlich lesbarer Grund, warum riskTier erhöht ist
requiresApproval true, wenn das Tool pro Aufruf eine Benutzerzustimmung benötigt — Public-API-Aufrufe lehnen diese ab

Ein Tool direkt aufrufen:

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

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

Gibt { result } zurück. Die Eingabe wird gegen das Schema des Tools validiert — ungültige Eingaben geben 422 mit Details zurück. Übergeben Sie eine optionale threadId, wenn das Tool einen Thread-bezogenen Kontext benötigt (z. B. Attachment-Lookups).

Gating — was die öffentliche API ablehnt:

  • Tier-beschränkte Tools (metadata.requiredTier !== 'free') → 403. Der Agent-Loop prüft das Tier gegen die Sitzung des Benutzers; die öffentliche API hat keinen übertragenen Tier-Kontext, daher ist die konservative Richtlinie die Ablehnung. Verwenden Sie stattdessen POST /v1/runs mit einem Agenten, der über das richtige Tier verfügt.
  • Zustimmungspflichtige Tools (metadata.approval.requiresApproval === true) → 403. Es gibt keinen Menschen im Prozess, der gefragt werden könnte. Rufen Sie diese über POST /v1/runs auf (was dem Benutzer die Abfrage anzeigt) oder stellen Sie den Tool-Zustimmungsmodus in der App auf approve_all ein, um dies zu umgehen.
  • Remote MCP-Tools501 mit dem Hinweis, /v1/runs zu verwenden (diese erfordern den Transport über den Agent-Subprozess).

Vision- und bildbasierte Tools: Laden Sie diese zuerst über POST /v1/attachments hoch und übergeben Sie dann die zurückgegebene Attachment-ID innerhalb von input (z. B. { "input": { "attachment_id": "att_abc", "prompt": "Was ist auf diesem Bild zu sehen?" } }). Das Tool liest die Binärdaten über die threadId aus dem Speicher; Sie übergeben die Bytes nicht direkt im Aufruf.

Connectors

Verwalten Sie OAuth-Integrationen – Google, Microsoft, GitHub, Notion, Slack und mehr.

Verfügbare Integrationen durchsuchen:

GET /v1/connectors/catalog

Gibt alle registrierten OAuth-Anbieter mit Namen, Kategorie und Standard-Scopes zurück.

Ihre verbundenen Konten auflisten:

GET /v1/connectors

Gibt aktive Verbindungen für das aktuelle Profil zurück. Token werden niemals offengelegt – nur Metadaten (Anbieter, E-Mail, Status, Scopes, Zeitstempel).

Einzelne Verbindung abrufen:

GET /v1/connectors/{id}

Gibt Metadaten für eine Verbindung zurück. Token werden niemals offengelegt.

Verbindungsstatus prüfen:

POST /v1/connectors/{id}/test

Gibt { health: { status, isTokenExpired, canRefresh } } zurück.

Verbindung entfernen:

DELETE /v1/connectors/{id}

Das Erstellen neuer Verbindungen erfordert den interaktiven OAuth-Flow über die App-UI oder die /auth/* Routen.

Trigger

Planen Sie Agenten für die automatische Ausführung – tägliche Briefings, wöchentliche Berichte, intervallbasierte Überwachung.

Jeder Trigger hat einen kind-Diskriminator: schedule (Standard – zeitgesteuert), webhook (wird ausgelöst, wenn ein externer Dienst an den Webhook-Pfad sendet) oder messaging (wird von einem verbundenen Messaging-Adapter ausgelöst – z. B. eingehende Slack/Discord-Nachrichten, die einem Kanalfilter entsprechen).

Trigger auflisten:

GET /v1/triggers

Gibt { triggers: [...] } zurück. Jeder Eintrag enthält seinen Typ (kind), Zeitplan und typspezifische Felder (z. B. webhookSecret/webhookPath für Webhook-Trigger).

Einzelnen Trigger abrufen:

GET /v1/triggers/{id}

Geplanten Trigger erstellen:

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

{
  \"name\": \"Morgen-Briefing\",
  \"prompt\": \"Fasse meine ungelesenen E-Mails und den heutigen Kalender zusammen\",
  \"modeId\": \"general\",
  \"schedule\": { \"type\": \"daily\", \"time\": \"08:00\" }
}

Unterstützte Zeitplantypen:

  • { \"type\": \"interval\", \"minutes\": 60 } – alle N Minuten (min 15, max 1440)
  • { \"type\": \"daily\", \"time\": \"09:00\" } – täglich zu einer bestimmten Zeit
  • { \"type\": \"weekly\", \"day\": \"mon\", \"time\": \"09:00\" } – wöchentlich
  • { \"type\": \"weekdays\", \"time\": \"08:30\" } – Montag bis Freitag
  • { \"type\": \"daysOfWeek\", \"days\": [\"mon\", \"wed\", \"fri\"], \"time\": \"10:00\" } – spezifische Tage
  • { \"type\": \"monthly\", \"dayOfMonth\": 1, \"time\": \"09:00\" } – monatlich
  • { \"type\": \"manual\" } – nur bei manuellem Aufruf via API

Trigger manuell auslösen:

POST /v1/triggers/{id}/fire

Gibt 202 mit einer threadId für den resultierenden Lauf zurück.

Aktualisieren oder Löschen:

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

Webhooks

Webhook-Trigger ermöglichen es externen Diensten (CI/CD, Monitoring, Formular-Builder), einen Agentenlauf via HTTP auszulösen.

Webhook-Trigger erstellen:

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

{
  \"name\": \"Deploy-Hook\",
  \"prompt\": \"Ein Deployment ist erfolgt: {{webhook.body}}\",
  \"modeId\": \"general\",
  \"kind\": \"webhook\"
}

Gibt 201 mit einem webhookSecret und webhookPath zurück. Speichern Sie das Secret – Sie benötigen es zum Signieren der Payloads.

Webhook senden:

# HMAC-SHA256 des rohen Request-Bodys berechnen
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\"}

Der Webhook-Endpunkt erfordert KEINE Bearer-Authentifizierung – er verwendet stattdessen die HMAC-Verifizierung. Gibt 202 mit der threadId des gestarteten Laufs zurück. Der Platzhalter {{webhook.body}} im Trigger-Prompt wird durch den rohen Request-Body ersetzt.

Messaging-Trigger

Messaging-Trigger werden ausgelöst, wenn ein verbundener Messaging-Adapter (z. B. eine über den Community Hub installierte Slack- oder Discord-Integration) eine eingehende Nachricht empfängt, die dem Filter des Triggers entspricht. Erstellung mit kind: \"messaging\":

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

{
  \"name\": \"Erwähnungs-Beantworter\",
  \"prompt\": \"Antworte hilfreich auf: {{message.text}}\",
  \"modeId\": \"general\",
  \"kind\": \"messaging\",
  \"messagingAdapterId\": \"slack-team-acme\",
  \"messagingChannelFilter\": \"#support\"
}

Der Adapter ist dafür verantwortlich, passende Ereignisse an den Trigger weiterzuleiten; messagingChannelFilter ist adapterspezifisch.

Benutzerdefinierte Funktionen

Erstellen Sie Ihre eigenen Tools, die Agenten aufrufen können. Funktionen werden in JavaScript oder Python geschrieben und in einer Sandbox ausgeführt.

Funktionen auflisten:

GET /v1/functions

Eine Funktion erstellen:

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

{
  "name": "calculate_bmi",
  "description": "Berechne den Body-Mass-Index aus Größe und Gewicht",
  "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"]
  }
}

JavaScript-Funktionen erhalten input und müssen ein Ergebnis zurückgeben. Python-Funktionen setzen eine result-Variable:

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

Eine Funktion direkt ausführen:

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

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

Sicherheit: JavaScript läuft in der vm-Sandbox von Node (kein Dateisystem- oder Netzwerkzugriff, 10s Timeout). Python läuft als Subprozess mit einem 30s Timeout. Beide validieren die Eingabe vor der Ausführung.

Aktualisieren oder löschen:

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

Skills

Skills sind gespeicherte Prompts, auf die Agenten verweisen können und die aus der Ansicht für leere Konversationen schnell gestartet werden können. Über den Hub installierte Skills (verwaltet via Paketinstallation) sind hier NICHT enthalten — nur vom Benutzer erstellte Skills werden aufgelistet und sind bearbeitbar.

Skills auflisten:

GET /v1/skills

Gibt { skills: [...] } der vom Benutzer erstellten Skills für das aktive Profil zurück. Gelöschte (Tombstoned), Hub-Overlay- und Sync-Shadow-Skills werden herausgefiltert.

Einen Skill abrufen:

GET /v1/skills/{id}

Einen Skill erstellen:

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

{
  "prompt": "Fasse die Seite in 3 Stichpunkten zusammen.",
  "tags": ["utility", "summarize"],
  "isFavorite": true,
  "modes": ["general"],
  "displayName": "Schnellzusammenfassung",
  "description": "Drei-Punkte-TL;DR der aktiven Seite"
}

Nur prompt ist erforderlich. modes (optional) beschränkt den Skill auf bestimmte Agenten-IDs; weglassen für alle Modi. Gibt 201 mit dem neuen Skill zurück (einschließlich serverzugewiesener id, createdAt, updatedAt).

Einen Skill aktualisieren:

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

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

Anpassbare Felder: prompt, tags, modes, displayName, description, isFavorite. Versuche, einen Hub-Overlay-Skill zu ändern, geben 404 zurück.

Einen Skill löschen:

DELETE /v1/skills/{id}

Führt eine Soft-Löschung via Tombstone durch. Gibt 204 zurück. Hub-Overlay-Skills geben 404 zurück — deinstallieren Sie stattdessen das Quellpaket.

Workflows

Orchestrieren Sie mehrere Agenten in einem DAG (gerichteter azyklischer Graph) – führen Sie Schritte nach Möglichkeit parallel aus und leiten Sie Ausgaben früherer Schritte in spätere ein.

Einen Workflow-Graphen validieren:

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

{
  "graph": {
    "nodes": [
      { "id": "research", "agentId": "general", "prompt": "Erforsche Trends bei erneuerbaren Energien" },
      { "id": "analyze", "agentId": "general", "prompt": "Recherchiere Wettbewerberpreise" },
      { "id": "report", "agentId": "general", "prompt": "Schreibe einen Bericht, der Folgendes kombiniert: {{outputs.research}} und {{outputs.analyze}}", "dependsOn": ["research", "analyze"] }
    ]
  }
}

Gibt { valid: true/false, errors: [...] } zurück. Prüft auf Zyklen, doppelte IDs und fehlende Abhängigkeitsreferenzen.

Einen Workflow ausführen:

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

{
  "graph": {
    "nodes": [
      { "id": "research", "agentId": "general", "prompt": "Erforsche Trends bei erneuerbaren Energien" },
      { "id": "summarize", "agentId": "general", "prompt": "Fasse zusammen: {{outputs.research}}", "dependsOn": ["research"] }
    ]
  }
}

Gibt { status: "completed", outputs: { research: "...", summarize: "..." }, nodeResults: {...} } zurück.

Unabhängige Knoten (ohne gemeinsame Abhängigkeiten) laufen parallel. Der Platzhalter {{outputs.nodeId}} im Prompt eines Knotens wird durch den Inhalts-Output des genannten Upstream-Knotens ersetzt. Jeder Knoten ist ein vollständiger Agentenlauf, kann also Tools verwenden, im Web surfen und auf alle Funktionen des Zielagenten zugreifen.

Wissensdatenbanken

Organisieren Sie Dokumente in durchsuchbaren Sammlungen, auf die Agenten Bezug nehmen können.

Wissensdatenbanken auflisten:

GET /v1/knowledge/bases

Eine Wissensdatenbank erstellen:

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

{ "name": "Forschungsarbeiten" }

Gibt 201 mit der neuen Basis-ID zurück.

Ein Dokument in eine Wissensdatenbank hochladen:

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

{
  "fileName": "research-paper.pdf",
  "contentType": "application/pdf",
  "dataUrl": "data:application/pdf;base64,JVBERi0xLjQ...",
  "description": "Trends bei erneuerbaren Energien 2026"
}

Das Feld dataUrl ist eine base64-kodierte Daten-URL. Gibt 201 mit den Dokument-Metadaten zurück.

Dokumente in einer Wissensdatenbank auflisten:

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

In einer Wissensdatenbank suchen:

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

{ "query": "erneuerbare energien" }

Gibt passende Dokumente basierend auf Dateiname und Beschreibung zurück. Die semantische (Vektor-)Suche folgt in einer zukünftigen Version.

Ein Dokument oder eine Wissensdatenbank löschen:

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

Agenten exportieren & importieren

Teilen Sie Agenten als portable Pakete — über Geräte, Teams oder den Community Hub hinweg.

Einen Agenten exportieren:

POST /v1/agents/{id}/export

Gibt ein JSON-Paket zurück, das die Agentendefinition, Tool-Anforderungen (abgeleitet von aktivierten Tools), Connector-Anforderungen (welche OAuth-Anbieter benötigt werden) und Trigger-Vorlagen enthält. Synchronisierungs-Metadaten werden entfernt — das Paket ist ein sauberer, eigenständiger Bauplan.

Einen Agenten importieren:

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

{
  \"package\": {
    \"$schema\": \"caiioo.agent.package/v1\",
    \"agent\": {
      \"id\": \"geteilter-forschungs-agent\",
      \"branding\": { \"name\": \"Forschungs-Agent\", \"description\": \"Vom Team\" },
      \"defaultSettings\": { \"systemPrompt\": \"Du erforschst Dinge.\" },
      \"settingLevels\": {}
    },
    \"toolRequirements\": [
      { \"toolId\": \"web_browsing\", \"enabled\": true },
      { \"toolId\": \"search_tools\", \"enabled\": true }
    ]
  }
}

Gibt 201 mit dem installierten Agenten zurück. ID-Kollisionen mit integrierten oder vorhandenen Agenten geben 409 zurück.

Fehlerbehandlung

Die API verwendet Standard-HTTP-Statuscodes:

Code Bedeutung
200 Erfolg
201 Erstellt
202 Akzeptiert (asynchrone Operation gestartet)
204 Gelöscht (kein Inhalt)
400 Ungültige Anfrage — Details finden Sie im Feld error
401 Nicht autorisiert — Sitzungsgeheimnis fehlt oder ist ungültig
403 Verboten — z. B. Versuch, einen integrierten Agenten zu ändern
404 Nicht gefunden
409 Konflikt — z. B. Agenten-ID existiert bereits
422 Validierungsfehler — Eingabe entspricht nicht dem Tool-Schema
429 Ratenbegrenzung — siehe Ratenlimits im Abschnitt Authentifizierung
500 Serverfehler — prüfen Sie das Feld error
501 Nicht implementiert — Funktion existiert, ist aber so nicht verfügbar
503 Dienst nicht verfügbar — Speicher oder Anbieter nicht bereit

Alle Fehlermeldungen enthalten { "error": "lesbare Nachricht" }.

Schnellstart-Beispiel

Hier ist ein vollständiger Workflow: Erstellen Sie einen Agenten, führen Sie ihn aus und streamen Sie die Ergebnisse.

# 1. Einen benutzerdefinierten Agenten erstellen
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": "Fasse jede Eingabe prägnant in 3 Stichpunkten zusammen.",
      "enabledTools": { "web_browsing": true }
    },
    "settingLevels": {}
  }'

# 2. Asynchron ausführen
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": "Fasse https://de.wikipedia.org/wiki/Künstliche_Intelligenz zusammen" }, "mode": "async" }')

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

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

# 4. Agenten zum Teilen exportieren
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.