new
This commit is contained in:
247
01_Modulerweiterungen/Planung/Agenten_API.md
Normal file
247
01_Modulerweiterungen/Planung/Agenten_API.md
Normal file
@@ -0,0 +1,247 @@
|
||||
# Agenten-API – Planung & Architektur
|
||||
|
||||
## Zielsetzung
|
||||
|
||||
Die Agenten-API erweitert die Basis-API aus [`00_Globale_Richtlinien`](../00_Globale_Richtlinien/README.md) um OpenAPI-kompatible Endpunkte, die als Vermittlungsschicht zwischen externen Anfragenden, internen Worker/Agenten und einem LLM mit OpenAI-kompatibler Schnittstelle fungieren. Sie übernimmt folgende Aufgaben:
|
||||
|
||||
1. **Entgegennahme von Nutzeranfragen** (z. B. Anweisungen, Aufgabenbeschreibungen, Kontextdaten).
|
||||
2. **Anreicherung, Validierung und Normalisierung** der Anfragen.
|
||||
3. **Koordination eines Worker/Agenten**, der Vorverarbeitungsschritte ausführt (z. B. Kontextsuche, Prompt-Erweiterung, Werkzeugaufrufe).
|
||||
4. **Weiterleitung** der aufbereiteten Anfrage an ein LLM mit OpenAI-kompatibler REST-API.
|
||||
5. **Postprocessing der LLM-Antwort** (z. B. Extraktion strukturierter Resultate, Fehlerbehandlung, Logging) und Rückgabe an den ursprünglichen Anfragenden.
|
||||
|
||||
Die API bleibt streng modular: Planung unter `/Planung/`, Umsetzung unter `/Entworfener_Code/`.
|
||||
|
||||
---
|
||||
|
||||
## Anwendungsfälle
|
||||
|
||||
| Use-Case | Beschreibung |
|
||||
|----------|---------------|
|
||||
| `submit_task` | Externe Systeme übermitteln komplexe Arbeitsaufträge an den Agenten. |
|
||||
| `status_query` | Abfrage, ob ein Auftrag bereits verarbeitet wurde (Polling). |
|
||||
| `cancel_task` | Steuerung laufender Aufträge (Cancel/Abort). |
|
||||
| `interactive_chat` | Ad-hoc-Konversationen mit dem LLM inkl. Kontextanreicherung. |
|
||||
| `tool_feedback` | Worker meldet Zwischenergebnisse zurück, die an das LLM angehängt werden. |
|
||||
|
||||
---
|
||||
|
||||
## API-Design (OpenAPI)
|
||||
|
||||
### Basisdaten
|
||||
|
||||
- **Base Path**: `/api/agent`
|
||||
- **Version**: `v1`
|
||||
- **Schema**: JSON (application/json)
|
||||
- **Authentifizierung**: zukünftige Erweiterung; initial optionales `api_key`-Header-Feld.
|
||||
- **Fehlerformat**: RFC 7807-kompatibles JSON (`type`, `title`, `detail`, `instance`, optionale `meta`).
|
||||
|
||||
### Endpunkte (first iteration)
|
||||
|
||||
| Methode & Pfad | Zweck | Status |
|
||||
|----------------|-------|--------|
|
||||
| `POST /v1/tasks` | Erstellt neuen Auftrag. | Implementieren |
|
||||
| `GET /v1/tasks/{task_id}` | Status & Ergebnis abrufen. | Implementieren |
|
||||
| `POST /v1/chat` | Direkter Chat (Streaming optional). | Optional (Stretch) |
|
||||
| `POST /v1/tasks/{task_id}/cancel` | Laufenden Auftrag abbrechen. | Optional |
|
||||
| `POST /v1/tasks/{task_id}/feedback` | Worker liefert Zwischenstände/Tool-Ausgaben. | Optional |
|
||||
|
||||
---
|
||||
|
||||
## Komponentenarchitektur
|
||||
|
||||
```plaintext
|
||||
FastAPI Router (agent_api/router.py)
|
||||
└── AgentService (agent_api/service.py)
|
||||
├── WorkerAdapter (agent_api/worker_adapter.py)
|
||||
├── LLMClient (agent_api/llm_client.py)
|
||||
├── Persistence (optional spätere Erweiterung)
|
||||
└── Config Provider (agent_api/config.py)
|
||||
```
|
||||
|
||||
### 1. Router (`router.py`)
|
||||
- Definiert die FastAPI-Routen und Pydantic-Modelle.
|
||||
- Validiert Eingaben (z. B. Pflichtfelder, Limits).
|
||||
- Übersetzt Exceptions in HTTP-Fehler (Problem Details).
|
||||
|
||||
### 2. Service (`service.py`)
|
||||
- Zentrale Koordinationslogik.
|
||||
- Verantwortlich für:
|
||||
- Generierung Task-ID.
|
||||
- Übergabe an WorkerAdapter (Vorverarbeitung).
|
||||
- Aufruf des LLMClient.
|
||||
- Zusammenführung von Ergebnissen, Logging, Telemetrie.
|
||||
- Kapselt Retries, Timeout-Handling, Circuit-Breaker (später).
|
||||
|
||||
### 3. WorkerAdapter (`worker_adapter.py`)
|
||||
- Abstraktionslayer für Worker/Agenten (lokal, remote, Message-Bus).
|
||||
- Erste Version: synchroner Stub, der eingehende Daten durchreicht.
|
||||
- Später: Integration in Task-Queue (Celery, Arq, RQ) oder Event-System.
|
||||
|
||||
### 4. LLMClient (`llm_client.py`)
|
||||
- Kapselt HTTP-Aufrufe gegen OpenAI-kompatible APIs.
|
||||
- Unterstützt:
|
||||
- Text Completion / Chat Completion.
|
||||
- Streaming (später).
|
||||
- Fehlerbehandlung (Rate-Limit, Timeout, Invalid Request).
|
||||
- Konfiguration aus agenten-spezifischem Config-File (API-Key, Endpoint, Model).
|
||||
|
||||
### 5. Config (`config.py`)
|
||||
- Lädt `agent_api.yaml` (siehe unten) und ermöglicht Zugriffe auf Parameter.
|
||||
- Option auf Umgebungsvariablen (Override sensibler Felder, z. B. API-Key).
|
||||
- Links zur globalen Config (`00_Globale_Richtlinien/Entworfener_Code/app/src/config_loader.py`).
|
||||
|
||||
---
|
||||
|
||||
## Konfigurationsschema (`agent_api.yaml`)
|
||||
|
||||
```yaml
|
||||
agent_api:
|
||||
metadata:
|
||||
version: "0.1.0"
|
||||
description: "Agent Gateway für Worker + OpenAI-kompatible LLMs"
|
||||
|
||||
http:
|
||||
base_path: "/api/agent/v1"
|
||||
timeout_seconds: 60
|
||||
rate_limit_per_minute: 120
|
||||
enable_cors: true
|
||||
|
||||
auth:
|
||||
api_key_header: "x-agent-api-key"
|
||||
allowed_keys: [] # Optional: Liste statischer Schlüssel
|
||||
allow_unauthenticated: true
|
||||
|
||||
worker:
|
||||
adapter: "inline" # inline | queue | external
|
||||
endpoint: null # URL falls adapter=external
|
||||
timeout_seconds: 30
|
||||
|
||||
llm:
|
||||
provider: "openai" # openai | azure_openai | anthropic (kompatibel)
|
||||
base_url: "https://api.openai.com/v1"
|
||||
model: "gpt-4o-mini"
|
||||
temperature: 0.2
|
||||
max_tokens: 1200
|
||||
api_key: null # via ENV: AGENT_API_LLM_KEY
|
||||
request_timeout_seconds: 45
|
||||
retry:
|
||||
max_attempts: 3
|
||||
backoff_seconds: 2
|
||||
|
||||
execution:
|
||||
mode: "async" # async | sync
|
||||
response_timeout_seconds: 30
|
||||
queue_ttl_seconds: 300
|
||||
heartbeat_interval_seconds: 10
|
||||
allow_long_polling: true
|
||||
|
||||
logging:
|
||||
enabled: true
|
||||
log_payloads: false
|
||||
redact_fields:
|
||||
- "user_input"
|
||||
- "llm_response"
|
||||
```
|
||||
|
||||
- Sensible Werte (API-Key) werden über Umgebungsvariablen überschrieben.
|
||||
- `adapter` kann später für Worker-Typen erweitert werden.
|
||||
|
||||
---
|
||||
|
||||
## Timeout- und TTL-Strategie
|
||||
|
||||
### Verhalten von OpenAI-kompatiblen APIs
|
||||
- Der Standard-Endpunkt von OpenAI (und kompatiblen Anbietern) ist request/response-basiert. Wenn ein LLM länger braucht, bestimmt der Client, wie lange er wartet, bevor er mit einem Timeout abbricht.
|
||||
- HTTP-Clients sowie Proxys besitzen meist ein Standard-Timeout (z. B. 30–60 Sekunden). Bleibt die Antwort länger aus, wird die Verbindung beendet – unabhängig davon, ob der LLM-Aufruf intern noch läuft.
|
||||
- Streaming-Endpunkte (Server-Sent Events) halten die Verbindung offen. Sobald keine Daten übertragen werden, trennen viele Proxys nach ihrer Idle-Timeout-Regel.
|
||||
|
||||
### Anforderungen für die Agenten-API
|
||||
- Verhindern, dass externe Clients wegen langer LLM-Laufzeiten abbrechen.
|
||||
- Aufträge weiterbearbeiten können, auch wenn der initiale HTTP-Request beendet wurde.
|
||||
- Ergebnisse bereitstellen, sobald sie fertig sind (Polling, später Webhook/Streaming).
|
||||
|
||||
### Konzept und API-Verhalten
|
||||
1. **Async-Standardmodus (`execution.mode = "async"`)**
|
||||
- `POST /v1/tasks` antwortet unmittelbar mit `202 Accepted` + `task_id`.
|
||||
- Verarbeitung geschieht im Hintergrund (WorkerAdapter).
|
||||
- Client ruft periodisch `GET /v1/tasks/{task_id}` auf. Optional ermöglicht `allow_long_polling` längeres Offenhalten der Verbindung mit `Retry-After`-Headern.
|
||||
2. **Synchroner Modus (`execution.mode = "sync"`)**
|
||||
- Die API wartet maximal `response_timeout_seconds`.
|
||||
- Benötigt das LLM länger, wird eine Antwort mit `408 Request Timeout` oder erneut `202 Accepted` plus Hinweis zurückgegeben.
|
||||
- Die Aufgabe bleibt aktiv; Clients können später den Status abrufen.
|
||||
3. **TTL und Heartbeat**
|
||||
- `queue_ttl_seconds` begrenzt die Gesamtlebensdauer eines Tasks (z. B. 5 Minuten).
|
||||
- `heartbeat_interval_seconds` definiert, wie oft Worker/Adapter Aktivität melden. Bleibt der Heartbeat aus, wird der Task als `expired` markiert.
|
||||
|
||||
### Status-Codes und Rückmeldungen
|
||||
- `202 Accepted`: Aufgabe angenommen, Verarbeitung läuft. Response enthält `task_id`, `status = processing`, optional `retry_after`.
|
||||
- `200 OK`: Aufgabe abgeschlossen. Antwort enthält fertige `result`-Payload sowie Metadaten (`duration_ms`, `completed_at`).
|
||||
- `408 Request Timeout`: Synchroner Modus, Ergebnis liegt noch nicht vor. Response enthält `task_id`, `status = processing`, `detail = "still_running"`.
|
||||
- `410 Gone`: Aufgabe abgelaufen (`expired`) oder bewusst entfernt.
|
||||
- `500 Internal Server Error`: Verarbeitung fehlgeschlagen. Response enthält Fehlerdetails und Hinweise zum Retrying.
|
||||
|
||||
### Integration in die Implementierung
|
||||
- `AgentService` verwaltet Task-Status (`processing`, `succeeded`, `failed`, `expired`) und entscheidet anhand der Konfiguration über Sync/Async-Verhalten.
|
||||
- `WorkerAdapter` sendet Heartbeats; bleibt dieser aus, sorgt die TTL für automatisches Aufräumen.
|
||||
- `LLMClient` respektiert `request_timeout_seconds` und `retry`-Parameter; nach ausgeschöpften Retries wird der Task auf `failed` gesetzt.
|
||||
- Persistenzschicht (später Redis/DB) speichert `expires_at` und `last_heartbeat`, sodass Expiration sauber umgesetzt werden kann.
|
||||
|
||||
Damit ist festgelegt, wie der Agent weiterarbeitet, obwohl ein Client den ursprünglichen HTTP-Request beendet oder ein Timeout erreicht. Die Agenten-API übernimmt das Handling von Time-to-Live und Task-Lebenszyklen und stellt sicher, dass LLM-Laufzeiten den Client nicht blockieren.
|
||||
|
||||
---
|
||||
|
||||
## Sequenzfluss (High-Level)
|
||||
|
||||
1. **Client** sendet POST `/v1/tasks` mit Payload (`user_input`, optional `context`, `metadata`).
|
||||
2. **Router** validiert Payload → ruft `AgentService.submit_task`.
|
||||
3. **AgentService**:
|
||||
1. erzeugt Task-ID, speichert Minimalzustand (in-memory, später DB).
|
||||
2. ruft `WorkerAdapter.pre_process` für Kontextanreicherung.
|
||||
3. erstellt Request an `LLMClient.generate`.
|
||||
4. **LLMClient**:
|
||||
- baut ChatCompletion- oder Completion-Request.
|
||||
- sendet HTTP-Request (mit API-Key, Timeout, Retries).
|
||||
5. **AgentService** sammelt Antwort, führt optional Postprocessing aus (z. B. extrahierte Schritte).
|
||||
6. **Router** liefert HTTP-Response mit Task-ID, Status, generiertem Output.
|
||||
|
||||
Für `GET /v1/tasks/{task_id}` werden Ergebnisse aus internem Store (in-memory, Pydantic-`Dict[str, TaskStatus]`) gelesen; langfristig Persistenz (Redis/DB).
|
||||
|
||||
---
|
||||
|
||||
## Integration mit Haupt-App
|
||||
|
||||
- `00_Globale_Richtlinien/Entworfener_Code/app/code/app/main.py` erweitert Try-Import:
|
||||
```python
|
||||
try:
|
||||
from agent_api.router import agent_router
|
||||
app.include_router(agent_router, prefix="/api")
|
||||
except Exception:
|
||||
...
|
||||
```
|
||||
- `agent_api.router` sorgt selbst für Prefix `/agent`.
|
||||
- Konfiguration: `agent_api.yaml` wird in `start.py` oder neuem Initialisierungsschritt geladen (via `config_loader.Settings` oder separatem Loader).
|
||||
|
||||
---
|
||||
|
||||
## Tests & Qualität
|
||||
|
||||
- Unit-Tests für Service + LLMClient (Mock HTTPX).
|
||||
- FastAPI TestClient für Endpunkte (Beispiel-Request + Response).
|
||||
- Konfig-Validierung (Fehlende API-Keys → Fehler).
|
||||
- Logging-Integration (ggf. in SQLite/External Logging einspeisen).
|
||||
|
||||
---
|
||||
|
||||
## Offene Punkte / Nächste Schritte
|
||||
|
||||
1. **Planung finalisieren** (dieses Dokument).
|
||||
2. **Konfigurationsdatei** `app/config/agent_api.yaml` erstellen.
|
||||
3. **Codegerüst** unter `app/src/agent_api/` implementieren:
|
||||
- `config.py`, `models.py`, `service.py`, `worker_adapter.py`, `llm_client.py`, `router.py`.
|
||||
4. **Tests**: `app/tests/test_agent_api.py`.
|
||||
5. **Integration** in `create_app` + `start.py`.
|
||||
6. **Security**: API-Key-Check und Rate-Limiting (Basis).
|
||||
7. **Dokumentation**: README + Beispiel-Requests.
|
||||
|
||||
Dieses Dokument dient als Referenz und Abstimmungspunkt, bevor mit der Implementierung fortgefahren wird.
|
||||
Reference in New Issue
Block a user