enhancement
major
minor
major
minor
major
#29965
tl-ai-core: LLM-Anbieter ohne Anwendungskonfiguration über Umgebungsvariablen aktivieren
Kontext
Eine Anwendung bindet die KI-Module (Chat, Living Views, MCP-Server) über die Abhängigkeiten von tl-ai-core ein, künftig über den Feature-Starter tl-starter-ai (#29956). Damit Agenten laufen, braucht LLMProviderService mindestens einen Anbieter mit API-Schlüssel. tl-ai-core lieferte keinen Anbieter mit; jede Anwendung musste <providers> selbst konfigurieren (so tl-ai-demo in WEB-INF/autoconf/com.top_logic.tl.ai.core.provider.LLMProviderService.config.xml). Eine frisch erzeugte Anwendung mit KI-Modulen war deshalb ohne Nacharbeit nicht nutzbar.
Erweiterung
tl-ai-core bringt eine Vorgabe-Konfiguration der unterstützten Anbieter (Anthropic, OpenAI, Mistral, xAI) mit, deren API-Schlüssel (und ggf. Modelle) aus Umgebungsvariablen bzw. dem Geheimnisspeicher der Installation gelesen werden:
- Ein Anbieter ohne Schlüssel ist inaktiv, statt den Start des Dienstes zu verhindern; ohne jeden Schlüssel startet die Anwendung, die KI-Funktionen melden verständlich, dass kein Anbieter verfügbar ist.
- Die Vorgabe-Modelle (default-model der Agenten) passen zu den aktiven Anbietern.
- Eine Anwendung kann die Vorgabe wie bisher überschreiben.
- Die Umgebungsvariablen sind im Entwicklerartikel der KI-Module beschrieben.
Test
Anwendung mit tl-ai-core/`tl-chat` ohne eigene Anbieterkonfiguration starten: ohne Variable startet sie und meldet den fehlenden Anbieter; mit gesetztem Schlüssel (z. B. tl_anthropic_api_key) beantwortet der Chat eine Anfrage.
Lösung
Baut auf den Geheimnisquellen aus #29948 auf: Ein API-Schlüssel wird im Moment der Verwendung gelesen (<api-key name="tl_anthropic_api_key"/>, aufgelöst über den SecretStoreService: Umgebungsvariable bzw. Systemeigenschaft gleichen Namens mit dem Klartext-Schlüssel, in der Entwicklung auch ~/.top-logic/secrets). Ob ein Anbieter aktiv ist, entscheidet sich deshalb ebenfalls bei der Verwendung, nicht beim Start: ein später hinterlegter Schlüssel aktiviert den Anbieter ohne Neustart.
- Verfügbarkeit von Zugangsdaten: CredentialProvider (com.top_logic.basic.credential) hat isAvailable() und reference(). Zugangsdaten aus einer Geheimnisquelle (Header-, Basic-, OAuth-Client-Credentials einschließlich private_key_jwt und Client-Assertion) sind verfügbar, wenn die Quelle das Geheimnis hält (SecretSource#isAvailable()); ein vorhandenes, aber unlesbares Geheimnis zählt als verfügbar und meldet seinen Fehler bei der Verwendung. reference() nennt die Herkunft (z. B. den Namen des Geheimnisses), ohne es preiszugeben.
- Inaktive Anbieter: Ein Anbieter, dessen Zugangsdaten nicht verfügbar sind (LLMProviderConfig#isAvailable()), wird nicht aufgerufen: keine 401-Antwort, keine 24-Stunden-Kontingentmarke des Modells; Failover übergeht ihn. Ein Lauf, der nur ihn hätte, endet mit einer internationalisierten Meldung, die den Anbieter und das fehlende Geheimnis nennt. Die Modellabfrage im Service-Editor sendet ohne Zugangsdaten keine Anfrage und nennt das fehlende Geheimnis. Die Startprüfungen bleiben unverändert: ausdrücklich konfigurierte Modelle starten weiterhin.
- Vorgabe-Modell: Ist default-model von AgentRuntimeService leer (Vorgabe: Umgebungsvariable tl_ai_default_model), läuft ein Agent auf dem ersten Modell des ersten verfügbaren Anbieters in der konfigurierten Reihenfolge, für jeden Lauf neu bestimmt.
- Mitgelieferte Anbieter: tl-ai-core.conf.config.xml konfiguriert anthropic, openai, mistral und xai (in dieser Reihenfolge) mit den Geheimnissen tl_anthropic_api_key, tl_openai_api_key, tl_mistral_api_key, tl_xai_api_key. Die Modelle kommen aus tl_<anbieter>_models (kommagetrennt, das erste ist das Vorgabe-Modell); ohne Variable: claude-sonnet-4-6,claude-opus-4-7,claude-haiku-4-5, gpt-5.5,gpt-5.4-mini, mistral-medium-latest,mistral-small-latest, grok-4.3,grok-4-1-fast. Eine Anwendung ändert einen Anbieter über seinen Namen (Zusammenführung nach Schlüssel) oder ersetzt die Liste mit <providers config:override="true">.
- Meldung ohne Anbieter: „Es ist kein KI-Anbieter verfügbar. Hinterlegen Sie den API-Schlüssel eines Anbieters als eines der Secrets tl_anthropic_api_key, tl_openai_api_key, tl_mistral_api_key, tl_xai_api_key.“ Der Chat zeigt Meldungen eines Laufs, die einen übersetzbaren Text tragen, in der Sprache des Benutzers.
- Chat: Die Modellauswahl bietet nur Modelle an, deren Anbieter seine Zugangsdaten hat (je Anfrage geprüft); ohne Modell zur Wahl entfällt das Modellmenü. Das Kontextfenster des Chats folgt dem tatsächlich verwendeten Vorgabe-Modell.
- tl-ai-demo verwendet die mitgelieferten Anbieter statt einer eigenen Konfiguration; tl-factory-app ersetzt die Liste weiterhin durch seinen eigenen Anthropic-Anbieter. Die Testkonfigurationen von tl-chat und tl-ai-demo sind angepasst; TestConcurrentAgents wird ohne Schlüssel übersprungen.
- Die Entwicklerartikel ai/index und ai/providers beschreiben die Geheimnisse, Variablen, inaktive Anbieter und die Wahl des Vorgabe-Modells.
Der Start von tl-ai-demo ohne Schlüssel für den VectorIndex (#29962) ist bereits mit #29948 behoben.
Migration
- Eine Anwendung, die in ihrer Konfiguration von LLMProviderService eigene <providers> ohne config:override angibt, erhält zusätzlich die mitgelieferten Anbieter anthropic, openai, mistral und xai; ein eigener Anbieter mit einem dieser Namen wird mit dem mitgelieferten zusammengeführt. Soll weiterhin genau die eigene Liste gelten, <providers config:override="true"> schreiben. Exponieren ein eigener und ein mitgelieferter Anbieter dasselbe Modell, verweigert der Dienst den Start, solange eine Referenz auf das Modell keinen Anbieter nennt (default-provider bzw. provider angeben oder die Liste ersetzen).
- Eine Anwendung, die ihre Anbieter allein für die Vorgabe-Konfiguration der Demo nachgebaut hat, kann ihre LLMProviderService-Konfiguration entfernen und die Schlüssel über tl_<anbieter>_api_key hinterlegen.
- Ohne gesetztes default-model läuft ein Agent nicht mehr nur mit Fehler, sondern auf dem ersten Modell des ersten verfügbaren Anbieters.