Zum Inhalt springen

API-Referenz

Selu bietet zwei Gruppen von HTTP-Endpunkten: die v1 Conversation API (genutzt von der Web-App und nativen mobilen Clients) sowie Admin-Endpunkte für die Verwaltung von Agenten, Richtlinien und System-Updates. Alle Endpunkte erfordern Authentifizierung über Session-Cookie.

Die v1 API ist der gemeinsame Vertrag zwischen der Selu-Web-App und iOS. Sie umfasst Unterhaltungsverwaltung, Nachrichtenversand, einen wiederholbaren Event-Feed und Tool-Genehmigungsentscheidungen.

Gibt grundlegende Informationen über den angemeldeten Benutzer zurück. Die Web-App nutzt dies, um eine rollengerechte Navigation anzuzeigen, ohne Zugangsdaten im Browser zu speichern.

Antwort:

{
"display_name": "Ada Lovelace",
"is_admin": false,
"language": "de",
"supports_photo_uploads": true
}
FeldTypBeschreibung
display_namestringAnzeigename des Benutzers
is_adminbooleanOb der Benutzer Admin-Rechte hat
languagestringBevorzugter Sprachcode (z. B. "en", "de")
supports_photo_uploadsbooleanOb dieser Server Foto-Anhänge in Nachrichten akzeptiert

Listet Unterhaltungen des angemeldeten Benutzers, sortiert nach zuletzt aktiv.

Query-Parameter:

ParameterTypPflichtBeschreibung
limitintegerneinAnzahl zurückzugebender Unterhaltungen (1–100, Standard 50)
beforestringneinOpaker Cursor aus next_cursor einer vorherigen Antwort

Antwort:

{
"conversations": [
{
"id": "01J...",
"channel_id": "pipe-abc",
"channel_name": "Mein Web-Chat",
"title": "Ideen für das Wochenende",
"status": "active",
"kind": "regular",
"created_at": "2026-09-03T10:00:00.000Z",
"last_activity_at": "2026-09-03T10:15:00.000Z",
"active_run_id": null
}
],
"next_cursor": "2026-09-03T10:00:00.000Z|01J..."
}

Antwort-Felder:

FeldTypBeschreibung
conversationsarraySeite mit Unterhaltungszusammenfassungen
next_cursorstring | nicht vorhandenAls ?before= übergeben, um die nächste (ältere) Seite abzurufen. Fehlt, wenn keine ältere Seite existiert.

ConversationSummary-Felder:

FeldTypBeschreibung
idstringEindeutige Unterhaltungs-ID
channel_idstringID der Pipe, zu der diese Unterhaltung gehört
channel_namestringLesbarer Pipe-Name
titlestring | nullBenutzer-sichtbarer Titel, null wenn noch nicht gesetzt
statusstring"active" oder "archived"
kindstring"regular" für vom Benutzer gestartete Unterhaltungen, "schedule" für durch Zeitpläne erzeugte Threads
created_atstringISO 8601 Zeitstempel
last_activity_atstringISO 8601 Zeitstempel der letzten Nachricht
active_run_idstring | nullID eines laufenden Runs, oder null

Erstellt eine neue Unterhaltung.

Antwort: Ein ConversationSummary-Objekt (siehe oben).


Gibt einen vollständigen Snapshot der Unterhaltung zurück: Metadaten, Nachrichten und aktuelle Runs. Der Snapshot enthält außerdem einen event_cursor, den du an GET /api/v1/events übergeben solltest, um nur Events zu empfangen, die nach diesem Snapshot eingetreten sind.

Antwort:

{
"conversation": { "...ConversationSummary-Felder..." },
"messages": [
{
"id": "msg-001",
"role": "user",
"content": "Wie ist das Wetter?",
"created_at": "2026-09-03T10:00:00.000Z",
"tool_calls": null,
"tool_call_id": null,
"attachments": null,
"compacted": false
}
],
"runs": [
{
"id": "run-001",
"client_message_id": "client-uuid",
"status": "completed",
"error_code": null,
"created_at": "2026-09-03T10:00:00.000Z",
"started_at": "2026-09-03T10:00:01.000Z",
"completed_at": "2026-09-03T10:00:05.000Z"
}
],
"event_cursor": 42
}

ConversationMessage-Felder:

FeldTypBeschreibung
idstringNachrichten-ID
rolestring"user", "assistant", "tool" oder "status"
contentstringTextinhalt der Nachricht
created_atstringISO 8601 Zeitstempel
tool_callsobject | nullTool-Aufruf-Details, wenn die Rolle "assistant" ist und Tools aufgerufen wurden
tool_call_idstring | nullVorhanden bei Nachrichten mit Rolle "tool"
attachmentsobject | nullAngehängte Dateien oder Bilder
compactedbooleanOb diese Nachricht beim Context-Window-Management komprimiert wurde

ConversationRun-Felder:

FeldTypBeschreibung
idstringRun-ID
client_message_idstringIdempotency-Schlüssel vom Client
statusstringSiehe Run-Status unten
error_codestring | nullMaschinenlesbarer Fehlercode bei fehlgeschlagenem Run
created_atstringISO 8601 Zeitstempel
started_atstring | nullWann die Verarbeitung begann
completed_atstring | nullWann der Run abgeschlossen wurde

Run-Status:

StatusBedeutung
queuedRun wartet auf Start
runningAgent verarbeitet aktiv
waiting_for_approvalPausiert – wartet auf Tool-Genehmigung
cancellingAbbruch angefordert, läuft noch aus
completedErfolgreich abgeschlossen
failedMit Fehler beendet
cancelledVor Abschluss abgebrochen
interruptedUnerwartet gestoppt

Benennt eine Unterhaltung um. Der neue Titel ist nur für den Benutzer sichtbar – der Agent liest ihn nicht.

Anfrage-Body:

{
"title": "Ideen für das Wochenende"
}
FeldTypPflichtEinschränkungen
titlestringjaNicht leer, max. 120 Zeichen

Antwort: Das aktualisierte ConversationSummary.

Fehler-Antworten:

StatusCodeBedeutung
400conversation.invalid_titleTitel war leer oder fehlend
404—Unterhaltung nicht gefunden oder nicht dein Besitz

Löscht eine Unterhaltung zusammen mit allen Nachrichten, Runs, Events und gespeicherten Artefakten.

Fehler-Antworten:

StatusCodeBedeutung
404—Unterhaltung nicht gefunden oder nicht dein Besitz
409conversation.run_in_progressEin Run ist gerade aktiv – warte auf dessen Abschluss vor dem Löschen

Antwort: HTTP 204 bei Erfolg.


POST /api/v1/conversations/{conversation_id}/messages

Abschnitt betitelt „POST /api/v1/conversations/{conversation_id}/messages“

Sendet Text, Fotos oder beides und startet einen Agenten-Run. Der Endpunkt ist idempotent: Wiederhole dieselbe logische Nachricht mit derselben client_message_id, um den bestehenden Run zu erhalten, statt ein Duplikat zu erstellen. Das Limit für den Request-Body beträgt 18 MiB.

Anfrage-Body:

{
"text": "Wie ist das Wetter?",
"client_message_id": "550e8400-e29b-41d4-a716-446655440000",
"attachments": [
{
"filename": "foto.jpg",
"mime_type": "image/jpeg",
"data_base64": "<base64-kodierte Bilddaten>"
}
]
}
FeldTypPflichtBeschreibung
textstringaußer bei FotosNachrichtentext; darf bei einer reinen Foto-Nachricht leer sein
client_message_idstringjaStabile, clientseitig erzeugte UUID; bei unverändertem Inhalt für Wiederholungen erneut verwenden
attachmentsarrayneinBis zu 10 Foto-Anhänge

Anhang-Felder:

FeldTypBeschreibung
filenamestringOriginaldateiname
mime_typestringimage/jpeg, image/png, image/gif oder image/webp
data_base64stringBase64-kodierte Bildbytes

Limits:

LimitWert
Fotos pro Nachricht10
Dekodierte Größe pro Foto2 MiB
Dekodierte Gesamtgröße12 MiB
JSON-Request-Body18 MiB

Der Server prüft die Dateisignatur, statt nur mime_type zu vertrauen.

FehlercodeBedeutung
conversation.invalid_photoDie Signatur gehört zu keinem unterstützten Bildformat
conversation.photo_too_largeEin Foto überschreitet 2 MiB
conversation.too_many_photosMehr als 10 Fotos wurden angehängt
conversation.photo_commandFotos wurden mit einem Slash-Befehl kombiniert

Antwort: Der erstellte ConversationRun.


POST /api/v1/conversations/{conversation_id}/feedback

Abschnitt betitelt „POST /api/v1/conversations/{conversation_id}/feedback“

Bewertet die letzte abgeschlossene Antwort in einer Unterhaltung.

Anfrage-Body:

{ "rating": 1 }
WertBedeutung
1Hilfreich
-1Nicht hilfreich

Die Bewertung wird im letzten Turn-Signal gespeichert und fließt in die Verhaltenslektionen des Agenten ein.

Antworten:

StatusCodeBedeutung
204—Bewertung gespeichert
400conversation.invalid_feedbackrating war weder 1 noch -1
404conversation.feedback_unavailableEs ist noch keine abgeschlossene Antwort zum Bewerten vorhanden
409conversation.run_in_progressEin Run ist noch aktiv; warte auf seinen Abschluss

Der Unterhaltungs-Snapshot stellt den gespeicherten Wert als latest_turn_rating (1, -1 oder null) bereit, damit Clients die Auswahl nach einem Neuladen wiederherstellen können.


Gibt den lokalisierten Slash-Befehls-Katalog zurück. Clients können damit eine Befehlsauswahl darstellen, ohne bei neuen oder geänderten Befehlen veröffentlicht werden zu müssen.

Query-Parameter:

ParameterTypPflichtBeschreibung
langstringneinen oder de; standardmäßig die Sprache des angemeldeten Benutzers

Antwort:

{
"commands": [
{
"command": "/remind ",
"label": "/remind",
"description": "Eine einmalige Erinnerung setzen",
"argument_hint": "was zu tun ist + wann"
},
{
"command": "/help",
"label": "/help",
"description": "Verfügbare Befehle anzeigen",
"argument_hint": null
}
]
}
FeldTypBeschreibung
commandstringText für das Eingabefeld, einschließlich Leerzeichen am Ende, wenn ein Argument erforderlich ist
labelstringKurzform in der Befehlsauswahl
descriptionstringLokalisierte einzeilige Beschreibung
argument_hintstring | nullLokalisierter Platzhalter für das Argument, falls erforderlich

Ein authentifizierter Server-Sent Events-Stream, der Live-Updates an den Client liefert.

Query-Parameter:

ParameterTypPflichtBeschreibung
cursorintegerjaLetzte Event-ID, die der Client gesehen hat. Verwende event_cursor aus dem Unterhaltungs-Snapshot.

Der Server spielt beim Verbindungsaufbau sofort alle Events mit einer ID größer als cursor nach, dann werden neue Events live gestreamt. Das macht den Feed reconnect-sicher: bricht die Verbindung ab, verbinde dich mit der zuletzt empfangenen Event-ID neu und du verpasst nichts.

Event-Envelope:

{
"id": 43,
"conversation_id": "01J...",
"run_id": "run-001",
"type": "message.delta",
"entity_id": "msg-002",
"payload": { "delta": "sonnig" },
"created_at": "2026-09-03T10:00:03.000Z"
}
FeldTypBeschreibung
idintegerMonoton steigend Event-ID. Verwende sie als nächsten Cursor.
conversation_idstringZu welcher Unterhaltung dieses Event gehört
run_idstring | nullDer Run, der dieses Event erzeugt hat, falls zutreffend
typestringEvent-Typ (siehe Tabelle unten)
entity_idstring | nullID der betroffenen Entität (Nachrichten-ID, Run-ID usw.)
payloadobjectEvent-spezifische Daten
created_atstringISO 8601 Zeitstempel

Event-Typen:

TypPayloadBeschreibung
message.created{ id, role, content, ... }Eine neue Nachricht wurde zur Unterhaltung hinzugefügt
message.delta{ delta: string }Streaming-Textchunk einer laufenden Agenten-Antwort
run.started{ run_id }Ein Agenten-Run hat begonnen
run.tool_call{ name, arguments, ... }Der Agent hat ein Tool aufgerufen
run.tool_result{ tool_call_id, content }Ein Tool hat ein Ergebnis zurückgegeben
run.approval_required{ approval_id, tool_name, ... }Der Run wartet auf deine Genehmigung
run.output_finished{ run_id }Die Agenten-Antwort ist vollständig
run.completed{ run_id, status }Der Run hat einen Endzustand erreicht
conversation.changed{ title }Unterhaltungsmetadaten wurden aktualisiert (z. B. umbenannt)
conversation.deleted{}Die Unterhaltung wurde gelöscht (transient – nicht persistiert)

Lädt ein Artefakt mit der aktiven Sitzung herunter. Der Zugriff ist auf den Eigentümer beschränkt: Die Anfrage für ein fremdes Artefakt aus dem Arbeitsspeicher oder von der Festplatte gibt 404 zurück.

Die Antwort enthält die Rohdatei mit passenden Content-Type- und Content-Disposition-Headern. Bilder werden inline ausgeliefert, andere Dateien als attachment.


Genehmigt oder verweigert einen ausstehenden Tool-Aufruf, der auf deine Bestätigung wartet.

Genehmigungs-IDs sind auf ihren Besitzer beschränkt. Ein Versuch, eine Genehmigung eines anderen Benutzers zu entscheiden, gibt 404 zurück, ohne die ausstehende Genehmigung zu verbrauchen.

Anfrage-Body:

{
"approved": true
}
FeldTypPflichtBeschreibung
approvedbooleanjatrue um den Tool-Aufruf zu erlauben, false um ihn zu blockieren

Antwort: HTTP 200 bei Erfolg.


Die folgenden Endpunkte erfordern is_admin = true beim angemeldeten Benutzer. Anfragen ohne Admin-Rechte geben HTTP 403 zurück.

Startet ein Agenten-Update im Hintergrund.

Anfrage:

POST /agents/update/start
Content-Type: application/x-www-form-urlencoded
entry_json={"id":"weather","name":"Weather Assistant",...}
ParameterTypBeschreibung
entry_jsonstringJSON-kodierter Marketplace-Eintrag des zu aktualisierenden Agenten

Antwort:

{ "job_id": "550e8400-e29b-41d4-a716-446655440000" }

Fragt den Status eines Hintergrund-Update-Jobs ab.

Antwort:

{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"agent_id": "weather",
"agent_name": "Weather Assistant",
"target_version": "1.2.0",
"progress": 75,
"message_key": "agents.update.phase.downloading",
"done": false,
"success": false,
"redirect_to": null,
"error_key": null
}
FeldTypBeschreibung
progressnumberFertigstellungsgrad in Prozent (0–100)
message_keystringi18n-Schlüssel für die aktuelle Statusmeldung
donebooleanOb der Job abgeschlossen ist
successbooleanOb er erfolgreich abgeschlossen wurde (nur relevant wenn done true ist)
redirect_tostring | nullURL zum Weiterleiten nach Abschluss
error_keystring | nulli18n-Schlüssel für die Fehlermeldung bei Fehler

Status-Schlüssel:

SchlüsselBedeutung
agents.update.phase.preparingJob startet
agents.update.phase.downloadingDocker-Images werden heruntergeladen
agents.update.success.updatedUpdate abgeschlossen
agents.update.success.setup_requiredUpdate abgeschlossen, Setup erforderlich
agents.update.error.dockerDocker-Verbindung fehlgeschlagen
agents.update.error.startUpdate konnte nicht gestartet werden
agents.update.error.failedUpdate-Prozess fehlgeschlagen

Synchroner Update-Endpunkt. Noch verfügbar für formularbasierte Flows, kann aber mehrere Minuten blockieren.

Antwort: HTTP 302 Weiterleitung zur Agenten-Seite oder zum Setup-Assistenten.

Aktualisiert eine Tool-Richtlinie für einen bestimmten Agenten.

ParameterOrtBeschreibung
agent_idPfadAgenten-Bezeichner
capability_idFormularCapability-ID; __builtin__ für eingebaute Tools verwenden
tool_nameFormularTool-Name
policyFormularallow, ask oder block
scopeFormularglobal (nur Admin) oder user

Antwort: HTTP 200 (leerer Body) bei Erfolg.

Setzt eine persönliche Richtlinien-Überschreibung auf den globalen Standard zurück.

ParameterOrtBeschreibung
agent_idPfadAgenten-Bezeichner
capability_idFormularCapability-ID
tool_nameFormularTool-Name
return_toFormularOptionale Weiterleitungs-URL nach dem Reset

Antwort: HTTP 200 mit HX-Redirect-Header zur Agenten-Berechtigungsseite.

Zeigt die System-Update-Verwaltungsseite an.

Ändert den Release-Kanal.

ParameterTypWerte
release_channelstringstable, dev oder nightly

Antwort: HTTP 302 Weiterleitung.

Prüft manuell auf verfügbare Updates.

Wendet ein verfügbares Update an.

Kehrt zur vorherigen Version zurück.

Gibt den aktuellen System-Update-Status für Live-Polling zurück.

Antwort:

{
"active_job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "updating",
"progress_key": "updates.progress.downloading",
"installed_version": "v1.5.0",
"installed_display": "v1.5.0 (build 123)",
"available_version": "v1.5.1",
"available_display": "v1.5.1 (build 124)",
"available_changelog_url": "https://selu.bot/changelog/v1.5.1",
"update_available": true,
"rollback_available": true
}

Fortschritts-Schlüssel:

SchlüsselBedeutung
updates.progress.checkingRelease-Metadaten werden abgerufen
updates.progress.downloadingNeues Docker-Image wird heruntergeladen
updates.progress.restartingNeustart mit neuer Version
updates.progress.health_checkPost-Update-Validierung läuft
updates.progress.apply_doneUpdate erfolgreich abgeschlossen

Schaltet automatische Updates ein oder aus.

ParameterTypWerte
auto_updatestring1 zum Aktivieren, 0 zum Deaktivieren

  1. POST /api/v1/conversations — Unterhaltung erstellen, id notieren
  2. GET /api/v1/conversations/{id} — Snapshot abrufen, event_cursor notieren
  3. GET /api/v1/events?cursor={event_cursor} — SSE-Stream öffnen
  4. POST /api/v1/conversations/{id}/messages — Nachricht mit frischer client_message_id senden
  5. Im SSE-Stream auf message.delta-Chunks, run.output_finished und run.completed hören
  1. Du erhältst ein run.approval_required-Event im SSE-Stream
  2. Zeige dem Benutzer die Genehmigungskarte mit Tool-Name und Argumenten
  3. POST /api/v1/approvals/{approval_id}/decision mit { "approved": true/false }
  4. Der Run wird fortgesetzt und der SSE-Stream läuft weiter

Merke dir die letzte empfangene Event-id aus dem SSE-Stream. Beim Neuverbinden:

  1. GET /api/v1/conversations/{id} — Snapshot aktualisieren (holt verpasste Nachrichten nach)
  2. GET /api/v1/events?cursor={zuletzt_gesehene_id} — Stream dort fortsetzen, wo du aufgehört hast
  1. GET /api/v1/conversations — erste Seite (aktuellste 50 Unterhaltungen)
  2. Wenn die Antwort next_cursor enthält, als ?before={next_cursor} übergeben
  3. Wiederholen bis next_cursor fehlt
  1. POST /agents/update/start — gibt job_id zurück
  2. GET /agents/update/status/{job_id} — alle 1–2 Sekunden abfragen bis done: true
  3. success prüfen und redirect_to folgen, falls vorhanden

Alle Endpunkte erfordern ein gültiges Session-Cookie, das beim Anmelden unter /login gesetzt wird.

Admin-Endpunkte erfordern zusätzlich is_admin = true auf dem Benutzerkonto. Nicht-Admin-Anfragen an Admin-Endpunkte geben HTTP 403 zurück.