11 KiB
Agenten-API – Planung & Architektur
Zielsetzung
Die Agenten-API erweitert die Basis-API aus 00_Globale_Richtlinien 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:
- Entgegennahme von Nutzeranfragen (z. B. Anweisungen, Aufgabenbeschreibungen, Kontextdaten).
- Anreicherung, Validierung und Normalisierung der Anfragen.
- Koordination eines Worker/Agenten, der Vorverarbeitungsschritte ausführt (z. B. Kontextsuche, Prompt-Erweiterung, Werkzeugaufrufe).
- Weiterleitung der aufbereiteten Anfrage an ein LLM mit OpenAI-kompatibler REST-API.
- 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, optionalemeta).
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
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)
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.
adapterkann 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
- Async-Standardmodus (
execution.mode = "async")POST /v1/tasksantwortet unmittelbar mit202 Accepted+task_id.- Verarbeitung geschieht im Hintergrund (WorkerAdapter).
- Client ruft periodisch
GET /v1/tasks/{task_id}auf. Optional ermöglichtallow_long_pollinglängeres Offenhalten der Verbindung mitRetry-After-Headern.
- Synchroner Modus (
execution.mode = "sync")- Die API wartet maximal
response_timeout_seconds. - Benötigt das LLM länger, wird eine Antwort mit
408 Request Timeoutoder erneut202 Acceptedplus Hinweis zurückgegeben. - Die Aufgabe bleibt aktiv; Clients können später den Status abrufen.
- Die API wartet maximal
- TTL und Heartbeat
queue_ttl_secondsbegrenzt die Gesamtlebensdauer eines Tasks (z. B. 5 Minuten).heartbeat_interval_secondsdefiniert, wie oft Worker/Adapter Aktivität melden. Bleibt der Heartbeat aus, wird der Task alsexpiredmarkiert.
Status-Codes und Rückmeldungen
202 Accepted: Aufgabe angenommen, Verarbeitung läuft. Response enthälttask_id,status = processing, optionalretry_after.200 OK: Aufgabe abgeschlossen. Antwort enthält fertigeresult-Payload sowie Metadaten (duration_ms,completed_at).408 Request Timeout: Synchroner Modus, Ergebnis liegt noch nicht vor. Response enthälttask_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
AgentServiceverwaltet Task-Status (processing,succeeded,failed,expired) und entscheidet anhand der Konfiguration über Sync/Async-Verhalten.WorkerAdaptersendet Heartbeats; bleibt dieser aus, sorgt die TTL für automatisches Aufräumen.LLMClientrespektiertrequest_timeout_secondsundretry-Parameter; nach ausgeschöpften Retries wird der Task auffailedgesetzt.- Persistenzschicht (später Redis/DB) speichert
expires_atundlast_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)
- Client sendet POST
/v1/tasksmit Payload (user_input, optionalcontext,metadata). - Router validiert Payload → ruft
AgentService.submit_task. - AgentService:
- erzeugt Task-ID, speichert Minimalzustand (in-memory, später DB).
- ruft
WorkerAdapter.pre_processfür Kontextanreicherung. - erstellt Request an
LLMClient.generate.
- LLMClient:
- baut ChatCompletion- oder Completion-Request.
- sendet HTTP-Request (mit API-Key, Timeout, Retries).
- AgentService sammelt Antwort, führt optional Postprocessing aus (z. B. extrahierte Schritte).
- 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.pyerweitert Try-Import:try: from agent_api.router import agent_router app.include_router(agent_router, prefix="/api") except Exception: ...agent_api.routersorgt selbst für Prefix/agent.- Konfiguration:
agent_api.yamlwird instart.pyoder neuem Initialisierungsschritt geladen (viaconfig_loader.Settingsoder 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
- Planung finalisieren (dieses Dokument).
- Konfigurationsdatei
app/config/agent_api.yamlerstellen. - Codegerüst unter
app/src/agent_api/implementieren:config.py,models.py,service.py,worker_adapter.py,llm_client.py,router.py.
- Tests:
app/tests/test_agent_api.py. - Integration in
create_app+start.py. - Security: API-Key-Check und Rate-Limiting (Basis).
- Dokumentation: README + Beispiel-Requests.
Dieses Dokument dient als Referenz und Abstimmungspunkt, bevor mit der Implementierung fortgefahren wird.