Eine 3060 und null Cloud-Budget. KI-Modelle hinter einem einzigen Endpoint: fünf Cloud-Anbieter mit Gratis-Tarif, fünf lokale Engines, die auf deiner eigenen Hardware laufen, der Rest auf Abo oder pro Token als letzte Rettung.
Nicht theoretisch. Genau jetzt. aigate ist ein Docker-Stack hinter einem einzigen nginx-Port. Textgenerierung, Bildgenerierung, Sprachsynthese, Transkription, Websuche, Browser-Automatisierung, Objektspeicher, agentische Codeausführung, abgeschottete Codeausführung über viele Sprachen, ein E-Mail-Gateway, dein Telegram-Konto als MCP-Tool, Zeitreihen-Prognosen, Audioproduktion, ein Video-Werkzeugkasten mit Lipsync, eine asynchrone Job-Queue und eine Weboberfläche. Auf Hardware, die weniger kostet als ein einziger Monat OpenAI-API-Rechnung.
Das Ganze ist OpenAI-kompatibel. Richte irgendeinen Client auf http://localhost:4000 und es läuft. Bestehender Code, bestehende SDKs, bestehende Tools: die reden alle mit ihm, als wäre er OpenAI. Ist er nicht. Er gehört dir.
Modelle, die meisten davon gratis
Fünf Anbieter, Groq, OpenRouter, HuggingFace, Mistral, Cohere, haben einen Gratis-Tarif. Keine Kreditkarte zum Loslegen. Aber seien wir ehrlich, was “gratis” heißt, denn die Marketingseiten sind es nicht: gratis heißt ratenbegrenzt und gedeckelt, nicht unbegrenzt. Groq gibt dir 30 RPM und je nach Modell zwischen 1K und 14,4K Anfragen pro Tag. OpenRouter sind 50 Anfragen pro Tag bei 0 Dollar, 1K pro Tag, wenn du jemals 10 Dollar reingesteckt hast. HuggingFace reicht dir 0,10 Dollar Guthaben im Monat, also ein Testbudget, kein Tarif. Der Cohere-Test sind 1K Aufrufe pro Monat und ist schnell weg. Mistrals “Experiment”-Tarif veröffentlicht überhaupt keine genauen Grenzen. Cerebras stand mal auf dieser Liste. Steht nicht mehr drauf: beim letzten Audit antwortete dort jedes Modell mit “payment required”, also steckt es als bezahlter Anbieter mit drei Modellen im Stack, nicht als Gratis-Tarif. Das ist die andere Sache mit Gratis-Tarifen, sie werden zurückgezogen, und ein Stack, der auf genau einem davon steht, ist ein Stack, der an dem Tag bricht, an dem er verschwindet.
Also nein, du betreibst keine Firma auf Gratis-Tokens. Aber du fährst deine eigenen Workloads darauf, und wenn einer trockenläuft, übernimmt der nächste. Das ist der ganze Sinn.
Drei weitere, claudebox, pibox-zai und pibox, sind Agent-Container. Die ersten beiden laufen auf Abos, was nicht dasselbe ist wie gratis: das Kontingent wird trotzdem gezählt, du bezahlst es nur monatlich statt pro Token. Anthropic und OpenAI stecken im Stack, sind aber letzte Rettung. Fünf lokale Engines laufen auf deiner eigenen Hardware: kein Netz, keine Ratenlimits, überhaupt keine Kosten.
Die Routing-Philosophie ist simpel: zahl nie für einen Token, den du gratis hättest haben können.
LiteLLM erledigt das. Du fragst groq-llama-3.3-70b an. Groq limitiert dich. LiteLLM fällt still auf cerebras-gpt-oss-120b. Cerebras ist unten. Fällt auf mistral-small. Mistral antwortet. Du bekommst deine Antwort. Der Client hat nie erfahren, dass irgendwas passiert ist. Jedes Modell hat seine Fallback-Kette: erst Gratis-Cloud, dann Abo, dann Bezahlung pro Token, dann lokal. Die Kette wird bei jedem Start des Stacks neu gebaut, gefiltert auf genau die Anbieter, die du tatsächlich aktiviert hast.
groq-llama-3.3-70b → 429 rate limited
↓ fallback
cerebras-gpt-oss-120b → 503 unavailable
↓ fallback
mistral-small → 200 ✓Du hast keine Retry-Logik geschrieben. Du hast keine Fallback-Logik geschrieben. Du hast eine Anfrage geschickt und eine Antwort bekommen.
Die Architektur
nginx :4000 ┌──────────── always on ────────────┐
├─► /claudebox/ → claudebox │ nginx, LiteLLM, PostgreSQL, Redis │
├─► /pibox-zai/ → pibox-zai │ proxq — everything else is opt-in │
├─► /pibox/ → pibox └───────────────────────────────────┘
├─► /stealthy-auto-browse/ → HAProxy → [×5]
├─► /storage/ → hybrids3
├─► /q/ → proxq → LiteLLM (async, returns job ID)
├─► /librechat/ → LibreChat (web UI, LIBRECHAT=1)
├─► /searxng/ → SearXNG (meta-search, SEARXNG=1)
├─► /telethon/ → Telethon (Telegram client, TELETHON=1)
├─► /mailbox/ → mailbox (IMAP+SMTP gateway, MAILBOX=1)
├─► /piston/ → piston (sandboxed code execution, PISTON=1)
├─► /predictalot/ → predictalot (forecasting + tabular ML, PREDICTALOT=1)
├─► /audiolla/ → audiolla (audio production, AUDIOLLA=1)
├─► /flickies/ → flickies (video toolkit, FLICKIES=1)
└─► / → LiteLLM (sync)
├─ Groq (free: 30 RPM, 1K-14.4K RPD per model, GROQ=1)
├─ Cerebras (paid plan, 3 models, CEREBRAS=1)
├─ OpenRouter (free: 50 RPD $0 / 1K RPD with $10+, OPENROUTER=1)
├─ HuggingFace (free: $0.10/mo credits — eval only, HUGGINGFACE=1)
├─ Mistral (free "Experiment" tier, MISTRAL=1)
├─ Cohere (trial: 1K calls/MONTH, COHERE=1)
├─ Ollama (local CPU + CUDA, OLLAMA=1 / OLLAMA_CUDA=1)
├─ Talkies (local ASR + TTS, TALKIES=1 / TALKIES_CUDA=1)
├─ sd.cpp (local image gen, SDCPP=1 / SDCPP_CUDA=1)
├─ vLLM (local text LLM + embeddings, VLLM=1 / VLLM_CUDA=1)
├─ llama.cpp (local GGUF + vision-VLM, LLAMACPP=1 / LLAMACPP_CUDA=1)
├─ claudebox (subscription, CLAUDEBOX=1)
├─ pibox-zai (subscription, PIBOX_ZAI=1)
├─ pibox (points back at this stack's LiteLLM, PIBOX=1)
├─ Anthropic (pay-per-token, ANTHROPIC=1)
└─ OpenAI (pay-per-token, OPENAI=1)
MCP servers (all optional):
├─ stealthy_auto_browse — run_script: multi-step browser automation (BROWSER=1)
├─ hybrids3 — upload, download, list, delete, presign (HYBRIDS3=1)
├─ claudebox — agentic Claude Code via OAuth or API key (CLAUDEBOX=1)
├─ pibox_zai — agentic pi-coding-agent via z.ai/GLM (PIBOX_ZAI=1)
├─ pibox — agentic pi-coding-agent on your own models (PIBOX=1)
├─ telethon — your Telegram account as a tool (TELETHON=1)
├─ mailbox — IMAP+SMTP across N accounts (MAILBOX=1)
├─ predictalot — time-series forecasting (PREDICTALOT=1)
├─ audiolla — audio production, MIR, mastering, MIDI (AUDIOLLA=1)
├─ flickies — lipsync, face restore, ffmpeg ops (FLICKIES=1)
└─ mcp_tools — generate_image + generate_tts + search_web
+ execute_code (auto-enabled)Alles ist opt-in. Du schaltest Flags in .env um. Keinen Anthropic-Key? Setz ihn nicht. Nur eine CPU? Lass die CUDA-Flags weg. Der Stack passt sich an das an, was du hast, und baut seine Config entsprechend neu. Der immer laufende Kern sind fünf Dinge: nginx, LiteLLM, PostgreSQL, Redis, proxq. Alles andere ist ein Flag.
Werkzeuge, die jedes Modell aufrufen kann
Das ist es, was aigate zu mehr macht als einem Proxy mit Fallback-Kette. Ein ganzer Haufen MCP-Server, dutzende Werkzeuge. Jedes Modell mit Function Calling kann sie alle eigenständig aufrufen. Du promptest. Das Modell entscheidet, welche Werkzeuge es braucht. Du bekommst Ergebnisse.
Der konkrete Ablauf: du schickst einen Prompt an Groq, gratis, schnell. Das Modell entscheidet, dass es etwas recherchieren muss. Es ruft search_web auf, SearXNG fragt Google, Bing und DuckDuckGo gleichzeitig ab und liefert Treffer. Das Modell braucht mehr Details zu einem Treffer. Es ruft das Browser-Tool auf. Eine Camoufox-Instanz öffnet einen echten Firefox, bewegt einen echten Mauszeiger, lädt die Seite, zieht den Inhalt raus. Das Modell liest, entscheidet sich, das Ergebnis zu sichern. Ruft das Storage-Tool auf. hybrids3 schreibt die Datei und gibt eine öffentliche URL zurück. Das Modell entscheidet, dass es ein Bild für den Bericht braucht. Ruft generate_image auf. stable-diffusion.cpp rendert es lokal, lädt es in den Speicher, gibt eine URL zurück. Das Modell reicht dir eine strukturierte Antwort mit Links auf alles, was es produziert hat. Ein einziger API-Aufruf. Null bezahlte Tokens. Der Client sah eine Anfrage und eine Antwort.
stealthy_auto_browse
Fünf Camoufox-Repliken hinter einem HAProxy. Camoufox ist ein gehärteter Firefox: echte Maus- und Tastatureingaben auf OS-Ebene über PyAutoGUI, null CDP-Exposition, persistente Fingerprints pro Sitzung. Kommt an Cloudflare vorbei. An CreepJS. An BrowserScan. An Pixelscan. Nicht “kommt meistens vorbei”, sondern kommt wirklich vorbei, weil er auf den Wegen, die diese Systeme prüfen, nicht als Automatisierung erkennbar ist.
Ein einziges Werkzeug: run_script. Mehrstufige Skripte: navigieren, klicken, tippen, extrahieren, Screenshot machen, scrollen, auf Elemente warten, JavaScript ausführen. Das Modell schreibt das Skript, der Browser führt es aus, du bekommst strukturierte Daten aus der echten Seite zurück.
hybrids3
S3-kompatibler Objektspeicher, lokal betrieben. Der uploads-Bucket ist öffentlich lesbar: Dateien sind über eine direkte URL erreichbar, ohne Signatur. Vorsignierte PUT-URLs für direkte Uploads. Automatischer Ablauf. Werkzeuge für put, get, list, delete, info, presign und Buckets auflisten.
Das löst ein konkretes Problem agentischer Workflows. Wenn ein Modell etwas Großes produziert, einen gescrapten Datensatz, ein generiertes Bild, einen gerenderten Bericht, stopfst du das nicht ins Kontextfenster. Du legst es in den Speicher, holst dir eine URL, reichst die URL weiter. Der nächste Schritt kann sie abholen. Du auch. Der Kontext bleibt sauber.
Drei Coding-Agenten: claudebox, pibox-zai und pibox
Drei verschiedene agentische Coding-Agenten, nicht drei Kopien desselben. claudebox fährt Claude Code auf deinem Abo oder deinem API-Key. pibox-zai fährt pi-coding-agent, gerichtet auf z.ai für die GLM-Modelle (glm-5.3 und glm-5.3-flash). pibox ist derselbe Agent, zurückgerichtet auf das LiteLLM dieses Stacks, er programmiert also auf allem, was du ohnehin aktiviert hast: du benennst die Modelle mit PIBOX_MODELS, wählst ein Standardmodell mit PIBOX_DEFAULT_MODEL. Zwei Vorbehalte dabei, und beide beißen: ein Modell, das du aufführst, muss Tool Calling wirklich können, sonst hat der Agent nichts zu steuern, und gib einem Agenten nicht sein eigenes Modell zurück in die Liste, außer du magst Rekursion. Alle drei bekommen vollen Shell-Zugriff, dauerhafte Workspaces, Datei-I/O und Tool-Nutzung, und alle drei stellen eine REST-API, einen OpenAI-kompatiblen Endpoint und einen MCP-Server bereit.
Du nutzt Groq wegen der Geschwindigkeit. Groq stößt auf etwas, das echte Code-Arbeit verlangt. Groq ruft das claudebox-Tool auf. Claude Code übernimmt, bekommt eine Shell, schreibt Code, lässt Tests laufen, gibt strukturierte Ergebnisse zurück. Zurück in Groqs Kontext. Die Orchestrierung passiert in der Function-Calling-Schleife des Modells, und du hast nichts von dieser Logik geschrieben.
piston: Codeausführung in der Sandbox
LLMs sind katastrophal schlecht in Arithmetik, Hashing und Parsen. Also lass sie nicht raten. execute_code führt echten Code in einer nsjail-Sandbox aus, mit eigenem User-Namespace, chroot, seccomp-Filter, cgroup-Limits und ohne Netz, und reicht dem Modell ein deterministisches Ergebnis.
Die Standardinstallation ist Python plus Node. Du fügst Bash, Deno, Go, Rust, TypeScript oder vierzig weitere Sprachen über PISTON_LANGUAGES hinzu und baust neu. Das Modell braucht ein SHA-256, eine Datumsdifferenz, eine Regex auf 10K Zeilen? Es schreibt Code, piston führt ihn in der Zelle aus, und die Zahl kommt korrekt zurück statt halluziniert.
mcp_tools
generate_image, generate_tts, search_web und execute_code. Werden automatisch aktiv, sobald das passende Backend läuft. Alle liefern strukturiertes JSON, und erzeugte Dateien wandern automatisch mit dauerhaften URLs nach hybrids3. Keine base64-Klumpen im Kontextfenster.
Bildgenerierung läuft je nach Aktivierung über FLUX, DALL-E oder stable-diffusion.cpp. TTS läuft über Kokoro (CPU plus CUDA), Qwen3-TTS mit Stimmklonung, Stimmdesign und Emotionssteuerung (CUDA) oder OpenAI TTS. Die Websuche fragt SearXNG. Die Codeausführung geht an piston. Die Werkzeuge ermitteln dynamisch aus LiteLLM, welche Modelle es gibt, spiegeln also immer das, was tatsächlich läuft.
telethon
Dein echtes Telegram-Konto als Werkzeug. Nicht die Bot-API, sondern volles MTProto, genau der Zugriff, den du auf dem Handy hast. Nachrichten lesen, senden, Dialoge auflisten, Gruppen verwalten, Inhalte weiterleiten, bearbeiten, löschen, als gelesen markieren, Dateien schicken. Das Modell entscheidet wann. Der Agent handelt in deinem Namen.
Ein Groq-Modell im Gratis-Tarif, das im Web sucht, eine Seite scrapt, ein Bild erzeugt und das Ergebnis in deine gespeicherten Nachrichten schickt: null bezahlte Tokens, ein Gespräch, mehrere Tool-Aufrufe. Oder ein Cronjob, der dir die letzten 24 Stunden deiner Arbeitsgruppe zusammenfasst und sie dir jeden Morgen privat schickt. Dein Konto, programmierbar.
Angetrieben von telethon-plus. Du schaltest TELETHON=1 um, setzt TELETHON_API_ID / TELETHON_API_HASH / TELETHON_SESSION in .env. Der Session-String ist voller Kontozugriff, also behandle ihn wie das Passwort, das er faktisch ist.
mailbox: E-Mail als Werkzeug
Zustandsloses IMAP plus SMTP über N Konten aus einer einzigen YAML-Config. Vereinheitlichter Posteingang, list/search/CRUD pro Konto, Versand über SMTP. REST-API plus ein flacher MCP-Werkzeugsatz, bei dem ein mailbox-Parameter das Konto wählt.
Was heißt, dass ein Modell dir den Posteingang lesen, die Rechnung finden, die Summe herausziehen und antworten kann, ohne dass du eine einzige Zeile IMAP-Handhabung schreibst. MAILBOX=1, du richtest MAILBOX_CONFIG auf dein YAML, fertig.
predictalot: Prognose und tabellarisches ML
Fünf Zero-Shot-Foundation-Modelle für Zeitreihen, chronos-2, timesfm-2.5, moirai-2, toto-1, sundial-base-128m, über sechs Prognosetypen (univariat, multivariat, vergangene Kovariaten, künftige Kovariaten, Samples und je Typ gewichtete Ensembles) unter /v1/timeseries/<type>/….
Dann eine ganze Schwesterfamilie unter /v1/tabular/*: neun überwachte Backends (lightgbm, xgboost, hist-gbt, random-forest, logistic, mlp, svm-rbf, knn, naive-bayes) und drei Meta-Learner (calibrated, stacking, diversified). 26 MCP-Werkzeuge decken die Foundation-Modelle ab; der tabellarische Teil läuft nur über REST. CPU oder CUDA.
Zero-Shot heißt ohne Trainingslauf. Du reichst ihm eine Reihe, er prognostiziert. Das war’s.
audiolla: Audioproduktion
Der hier ist im Umfang absurd. Stem-Trennung (Demucs / UVR). Restauration: Nachhall raus, Echo raus, Rauschen raus. Mastering über matchering und pedalboard-Ketten, mit kuratierten Presets wie master-for-spotify, podcast-cleanup, vocal-cleanup. MIR-Analyse: BPM, Tonart, LUFS, Beats, Onsets, Melodie, Akkorde, Segmente. DSP-Transformationen über sox und ffmpeg. Lautheitsnormalisierung. Sprachaufbereitung (DeepFilterNet). VAD (silero). Diarisierung (pyannote). CLAP-Embeddings und Zero-Shot-Audioklassifikation. AudioSet-Tagging. Audio→MIDI über basic-pitch, dazu MIDI komponieren / inspizieren / transformieren / rendern über fluidsynth.
Dazu Text-zu-Audio-Generierung, stable-audio-open, musicgen, riffusion, audioldm2, nur unter CUDA.
Asynchrone Jobs und Webhooks durchgehend. Der Vertrag ab v1.0 ist streng: JSON-Body an jedem Audio-Endpoint, rohe Bytes nur bei PUT /v1/files/{path}, und output_path xor output_url zwingend bei allem, was Audio erzeugt.
flickies: Video und Lipsync
Lipsync über LatentSync 1.5 (ByteDance, Apache-2.0, ~8 GB VRAM, Standard unter CUDA) und Wav2Lip / Wav2Lip-GAN (LRS2, nicht kommerziell, zugangsbeschränkt). Gesichtsrestauration über GFPGAN v1.4. ffmpeg-Operationen: schneiden, aneinanderhängen, transkodieren inklusive gif-, fps- und Codec-Wechsel, skalieren, Audio muxen, Audio extrahieren, Thumbnail-Raster. ffprobe-Infos. Asynchrone Jobs und Webhooks. 11 MCP-Werkzeuge, derselbe JSON-Body- und output_path-xor-output_url-Vertrag wie bei audiolla.
GFPGAN und LatentSync 1.5 laufen nur unter CUDA. Das CPU-Image macht trotzdem die ffmpeg-Operationen und ein sehr langsames Wav2Lip.
Lokale Inferenz: langsamer, aber deine
Fünf lokale Engines. Jede einzelne davon hat einen CPU-Modus.
Das ist der Teil “Rechner für Arme”. Dein alter Laptop mit 16GB RAM schafft Textgenerierung, Bildgenerierung, Transkription und Sprachsynthese. Kein API-Key. Kein Netz. Kein Ratenlimit. Keine Rechnung. Es ist langsamer als die Cloud. Manchmal viel langsamer. Aber es gehört dir, es ist privat, und es geht offline.
Ollama: llama3.2:3b, qwen3:4b, smollm2:1.7b, qwen2.5-coder:1.5b, qwen2.5-coder:3b, phi4-mini (Reasoning, 128K Kontext), gemma4:e2b (Vision), gemma3:4b (Vision), nuextract-v1.5 (strukturierter Text nach JSON), dolphin-phi, dazu zwei Embedding-Modelle für RAG. Das kleinste braucht 1GB RAM. OLLAMA_CUDA=1 legt das schwere Set nach: qwen3:8b, gemma4:e4b (Vision), deepseek-coder-v2:16b (MoE, 160K Kontext), deepseek-r1:8b (Reasoning), qwen3-abliterated:16b (unzensiert), gemma4-abliterated:e4b (unzensierte Vision), qwen2.5-coder:7b, llama3.1:8b. Flash Attention, quantisierter KV-Cache, gemeinsamer Modellspeicher mit dem CPU-Dienst, also keine doppelten Downloads.
talkies: der vereinheitlichte ASR- plus TTS-Dienst und der Ersatz für das, was in diesem Stack mal Speaches war. Die CPU bringt inzwischen 13 Modelle mit: whisper-large-v3 und -turbo, canary-180m-flash, nemotron-3.5-asr-0.6b, vier Sherpa-ONNX-Zipformer-Varianten, Vosk small English, und zwei Phonem-Erkenner, die dir statt Wörtern einen rohen IPA-Lautstrom mit Zeitstempel pro Laut geben; Kokoro für TTS. Unter CUDA werden es bis zu 22, dazu kommen parakeet-tdt-0.6b-v3, canary-1b-flash, canary-qwen-2.5b, Chatterbox Turbo und die Qwen3-TTS-Familie, 0.6B und 1.7B, mit Stimmklonung, Stimmdesign und Emotionssteuerung über das Feld instructions. Chatterbox ist das einzige davon, das seine Ausgabe überhaupt markiert: das neuronale PerTh-Wasserzeichen von ResembleAI, standardmäßig an, und TALKIES_CHATTERBOX_WATERMARK=false schaltet es für sauberes Audio ab, während Kokoro und Qwen3-TTS nie etwas einbetten. OpenAI-kompatible Endpoints, deine bestehenden Whisper-Aufrufe laufen also unverändert. TALKIES=1 / TALKIES_CUDA=1.
Die Sherpa- und Vosk-Zugänge landen als zehn neue Transkriptions-Aliase: die fünf Modelle unter local-talkies-, dann dieselben fünf noch einmal unter local-talkies-cuda-. Die int8-Builds sind quantisiert (kleiner und schneller, etwas ungenauer); left-64 gegen left-128 legt das linke Kontextfenster der Attention fest. Alle fünf machen natives Live-ASR über den Streaming-WebSocket, zusätzlich zum gewohnten POST /v1/audio/transcriptions, und das CUDA-Image installiert ein hash-geprüftes Sherpa-CUDA-Wheel von upstream, damit sie dessen CUDA-Execution-Provider auch wirklich nutzen, statt in einem GPU-Container still auf die CPU zurückzufallen.
Eine Fallback-Feinheit, die es zu klauen lohnt: sechs Ketten in fallbacks.json führten früher ein Geschwister-Modell von talkies an erster Stelle, whisper-large-v3 → whisper-large-v3-turbo, und die Entsprechungen für die CUDA-Variante und beide TTS-Einträge. Das kann nie funktionieren. Jeder talkies-Container bedient ein Modell auf einmal und wirft beim Zulassen das vorherige raus, ein Sprung zum Geschwister findet also keine freie Kapazität, sondern erzwingt einen Modellwechsel, und unter Retries ist das nur noch Rauswerfen im Kreis. Die Ketten gehen jetzt erst zum anderen talkies-Container und dann raus zu den Cloud-Anbietern. Die CPU↔CUDA-Sprünge bleiben, weil das tatsächlich unabhängige Prozesse sind.
stable-diffusion.cpp: lokale Bildgenerierung. Die CPU fährt sd-turbo und sdxl-turbo ab Werk. SDCPP_CUDA=1 für Hardwarebeschleunigung und den vollen Modellsatz: sd-turbo, sdxl-turbo, sdxl-lightning, flux-schnell, juggernaut-xi. Modelle laden bei der ersten Nutzung herunter und werden lokal zwischengespeichert. Der OpenAI-kompatible Endpoint /images/generations heißt, dass bestehender Code unverändert läuft.
vLLM: lokale Text-LLMs plus Embeddings. qwen3-0.6b für Generierung, nomic-embed-v2 für Embeddings. VLLM=1 / VLLM_CUDA=1.
llama.cpp: GGUF-Modelle und Vision-VLMs, darunter Surya OCR 2 fürs Dokumentenverständnis. LLAMACPP=1 / LLAMACPP_CUDA=1.
Lokale Modelle sitzen standardmäßig am Ende der Fallback-Kette. Cloud fällt aus? Lokal übernimmt. Oder du zielst direkt darauf: "model": "local-ollama-cpu-llama3.2-3b". Null Netz. Null Kosten. Langsamer, aber es antwortet.
Eine GPU, alles
Hier das Ingenieursproblem: du hast eine GPU. Ollama will VRAM für das LLM. sd.cpp will VRAM für die Bildgenerierung. talkies will VRAM für Transkription und Sprache. audiolla will es für die Stem-Trennung. flickies will rund 8GB davon für LatentSync. Lade sie alle und du läufst in OOM.
Der Ressourcenmanager löst das von selbst. Ein LiteLLM-Callback erzwingt gegenseitigen Ausschluss pro Hardware: ein CUDA-Job zur Zeit. Kommt eine Bildgenerierungsanfrage, während ein LLM geladen ist, greift der Manager die Semaphore, entlädt das LLM und lässt dann die Bildgenerierung durch. Kommt danach eine TTS-Anfrage, entlädt er zuerst den Bildgenerator. Dieselbe Logik auf der CPU.
Jeder Dienst hat seine eigene Entlade-API, und der Ressourcenmanager kennt sie alle: Ollama nimmt keep_alive: 0, sd.cpp hat POST /sdcpp/v1/unload, talkies / vllm-cuda / llamacpp-cuda nehmen DELETE /api/ps/{model_id} pro Modell oder POST /unload, um zu killen, was gerade geladen ist, und audiolla hat POST /v1/unload, um alle geladenen Engines am Stück rauszuwerfen.
Es gibt auch Endpoints für den Betreiber, wenn du von Hand aufräumen willst: POST /v1/unload/cuda fächert nebenläufig auf ollama-cuda, sdcpp-cuda, talkies-cuda, vllm-cuda, llamacpp-cuda, audiolla-cuda und flickies-cuda auf. POST /v1/unload/cpu macht dasselbe für dieselben sieben auf der CPU-Seite. POST /v1/unload fährt beides nacheinander und reicht dir einen Bericht pro Dienst darüber, was tatsächlich rausgeworfen wurde.
Du verwaltest nichts davon. Du schickst Anfragen. Die Plattform jongliert das VRAM von allein. Der einzige Preis ist Latenz: die erste Anfrage nach einem Wechsel enthält die Ladezeit des Modells. Danach ist es schnell, bis der Leerlauf-Timeout das Modell entlädt, um Speicher für das Nächste frei zu machen.
Websuche
SearXNG unter /searxng/. Selbst gehostete Metasuche: fragt Google, Bing, DuckDuckGo und Wikipedia gleichzeitig ab. Kein API-Key. Läuft komplett lokal.
Reparier deinen secret_key, wenn du das früh ausgerollt hast. Der von SearXNG stand fest verdrahtet in der versionierten searxng/settings.yml. Er wird jetzt pro Deployment erzeugt und aus SEARXNG_SECRET_KEY in .env gelesen: setz ihn mit openssl rand -hex 32, wenn du SEARXNG=1 umlegst, sonst startet SearXNG auf dem Platzhalter von upstream. Die versionierte settings.yml ist komplett weg; die Einstellungen werden aus einem searxng_config-Eintrag im configs:-Block gerendert, genauso wie proxq_config schon ${REDIS_PASSWORD} gezogen hat. Die Exposition war begrenzt, /searxng/ sitzt hinter der Admin-Auth von nginx, der Container veröffentlicht keine Host-Ports, und limiter: false hieß, dass der Key keine Ratenlimits bewachte, aber der alte Wert liegt weiter in der Git-Historie, und dieser Teil ent-passiert nicht mehr.
Das MCP-Werkzeug search_web heißt, dass jedes Modell mit Function Calling eigenständig im Web suchen kann. Das Modell entscheidet, dass es etwas nachschlagen muss, ruft das Werkzeug auf, bekommt Treffer, denkt weiter. Du hast keine Suchintegration gebaut. Du hast SEARXNG=1 umgelegt.
LibreChat: der Alltagstreiber
Alles oben drüber läuft über die API. Aber für den täglichen Gebrauch gibt es LibreChat unter /librechat/.
Alle Modelle im Dropdown. Alle MCP-Werkzeuge verdrahtet. Modell wählen, losreden. Das Modell kann weiterhin eigenständig den Browser, den Speicher, die Coding-Agenten, die Bildgenerierung, TTS und die Websuche aufrufen: alles, was über die API geht, geht auch in der Oberfläche. Gesprächsverlauf auf MongoDB. Datei-Uploads. WebSocket-Streaming.
Der erste registrierte Nutzer wird Admin. Setz danach LIBRECHAT_ALLOW_REGISTRATION=false und du bist der Einzige drin.
Einschalten: LIBRECHAT=1 in .env.
Asynchrone Queue
Lange Inferenzanfragen laufen in einen Timeout. Geh auf /q/ statt auf / und die Anfrage wandert in eine Queue auf Redis. Du bekommst sofort eine Job-ID zurück. Die eigentliche Inferenz läuft im Hintergrund. Du fragst den Status ab und holst das Ergebnis, wenn es fertig ist.
# submit — returns 202 immediately
curl http://localhost:4000/q/v1/chat/completions
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "cerebras-gpt-oss-120b", "messages": [{"role":"user","content":"write a novel"}]}'
# → {"jobId": "550e8400-e29b-41d4-a716-446655440000"}
# check status
curl http://localhost:4000/q/__jobs/550e8400-e29b-41d4-a716-446655440000
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
# get the result
curl http://localhost:4000/q/__jobs/550e8400-e29b-41d4-a716-446655440000/content
-H "Authorization: Bearer $LITELLM_MASTER_KEY"Nebenläufigkeit, Aufbewahrung, Timeouts, Retries und Antwort-Caching, alles konfigurierbar. Nur die Pfade der OpenAI-API landen in der Queue; Health Checks und Admin-Anfragen gehen direkt durch.
Er bringt seinen eigenen Agent Skill mit
Das Repo trägt .agents/skills/aigate/, einen auf ClawHub veröffentlichten Agent Skill, der einem Coding-Agenten beibringt, wie er den Stack fährt. Statt also einem Assistenten jede Sitzung deine eigene Infrastruktur zu erklären, installierst du den Skill und er kennt die Endpoints, die Flags und die Werkzeugverträge schon.
Sicherheit
Die internen Dienste, PostgreSQL, MongoDB, Redis, der Browser-Cluster, das Storage-Backend, haben keine Host-Ports. Sie hängen in isolierten Docker-Netzen. Von außerhalb des Stacks erreicht sie nichts. Die einzige freiliegende Fläche ist nginx auf Port 4000, und die verlangt Bearer-Token-Auth.
Die Anwendungscontainer laufen mit no-new-privileges:true. Zwei Ausnahmen, beide bewusst und beide in der Compose-Datei dokumentiert: piston braucht privileged: true, weil nsjail bei jeder Ausführung User-Namespaces und chroots bauen muss, die eigentliche Isolation lebt innerhalb des nsjail-Subprozesses, und der privilegierte Container ist genau das, was nsjail braucht, um diese Zelle zu errichten. tailscale braucht NET_ADMIN für sein tun-Gerät im Userspace. Alles andere legt Privilegien ab. make run prüft vor dem Start, dass Dateipfade aus .env auch wirklich existieren, also keine still kaputten Volume-Mounts.
Du willst ihn öffentlich erreichbar, ohne einen Firewall-Port zu öffnen? CLOUDFLARED=1, also Cloudflare Tunnel. DDoS-Schutz, TLS-Terminierung, keine offenen Ports, keine IP zum Scannen. Quick Tunnel für eine zufällige *.trycloudflare.com-URL, oder ein benannter Tunnel für eine feste Domain.
Du willst ihn gar nicht öffentlich, aber trotzdem vom Laptop, vom Handy oder von einer anderen Kiste erreichen? TAILSCALE=1 mit TS_AUTHKEY=tskey-auth-... und einem TS_HOSTNAME. Ein Tailscale-Sidecar tritt deinem Tailnet bei und fährt tailscale serve im L4-TCP-Forwarding-Modus direkt auf nginx:4000: kein Abgleich über den Host-Header, keine FQDN-Konfiguration auf der Tailscale-Seite, kein HTTPS-Auto-Zertifikat (die TLS-Terminierung lebt, wenn du sie willst, in nginx). nginx bekommt die ursprünglichen Anfrage-Bytes unverändert und routet sie durch seine bestehende vhost- und Pfadlogik. Zugriff über http://<TS_HOSTNAME>.<tailnet>.ts.net, und schlichtes HTTP ist hier in Ordnung, weil WireGuard innerhalb des Tailnets ohnehin jedes Byte verschlüsselt. Läuft mit gehostetem Tailscale oder mit selbst betriebenem Headscale (du nimmst TS_EXTRA_ARGS=--login-server=...). Der Zustand bleibt in .data/tailscale/, Neustarts nutzen also die bestehende Anmeldung weiter. Kombinier das mit der Bearer-Token-Auth und du hast zwei völlig unabhängige Schichten Zugriffskontrolle.
Das ist der Verkehr, der hinein geht. Der Verkehr, der hinaus geht, ist eine eigene Sache, die du jetzt einschalten kannst: Tailnet-Egress für die Coding-Agenten, damit claudebox, pibox-zai und pibox alle Maschinen in deinem Tailnet erreichen und nicht nur das öffentliche Internet. Es kommt als Compose-Overlay (docker-compose.tailscale.yml) und verlangt zwei weitere Werte, TS_MAGICDNS_SUFFIX (das MagicDNS-Suffix deines Tailnets, direkt aus tailscale status) und TS_FALLBACK_DNS (Standard 1.1.1.1). Den zweiten gibt es, weil das DNS am Ende geteilt ist: MagicDNS beantwortet Tailnet-Namen und gibt für alles andere SERVFAIL zurück, öffentliche Namen brauchen also einen Resolver, auf den sie durchfallen können.
Hunderte Tests. Health Checks, Routing, Auth, Validierung der MCP-Werkzeuge, Storage-CRUD, Browser-Automatisierung, agentische Code-Läufe, Lebenszyklus asynchroner Jobs, lokale TTS/STT-Rundläufe, Verifikation des CUDA-Ressourcenmanagers, lokale Bildgenerierung, durchgehendes Tool Calling vom LLM zum MCP, SearXNG-Suche, Telethon-MTProto-Rundläufe gegen ein echtes Konto. Dazu Sicherheit: Isolation zwischen Tokens, Versuche der Session-Übernahme, HTTP Request Smuggling (CL.TE/TE.CL), h2c-Smuggling, SSRF über Browser und über MCP auf interne Dienste, Key-Extraktion per Prompt Injection, Path Traversal, Missbrauch von S3-Presign, gespeichertes XSS, Injektion von Modellnamen, Header-Injektion, Isolation des Docker-Sockets. Das ist keine Testsuite eines Hobbyprojekts. Das ist Paranoia als Feature.
Einrichtung
git clone https://github.com/psyb0t/aigate && cd aigate
make bootstrap # seeds .env; then edit it: add keys, flip flags
make run-bgJede Variable ist in .env.example dokumentiert. Schalte ein, was du hast, ignoriere, was du nicht hast. Du musst diese Datei auch nicht mehr von Hand kopieren: make bootstrap sät das .env, und jedes andere Target sät es vorher, make run auf einem frischen Clone funktioniert also einfach.
Wenn du am Stack selbst etwas ändern willst statt an einem Flag, pack es in docker-compose.override.yml. Das ist jetzt die unterstützte Nahtstelle: das Makefile setzt COMPOSE_FILE aus der Basisdatei, dem Tailscale-Overlay, wenn du es aktiviert hast, und deinem Override zuletzt zusammen. Editier die Basis-Compose-Datei direkt und das nächste Update frisst deine Änderungen; das Override überlebt.
Wenn Ressourcen zählen, und auf einem normalen Rechner tun sie das, liest make limits deinen verfügbaren RAM und die CPU aus und schreibt empfohlene Limits für jeden Dienst. MAXUSE=80 make limits deckelt den ganzen Stack auf 80% der Systemressourcen, wenn du die Maschine mit anderen Lasten teilst. Die CUDA-Dienste kennen den Ressourcenmanager, das Budget rechnet also mit dem größten davon, nicht mit jedem GPU-Dienst bei voller Zuteilung gleichzeitig.
# free tier, auto-fallback
curl http://localhost:4000/chat/completions
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "cerebras-gpt-oss-120b", "messages": [{"role":"user","content":"hello"}]}'
# local, no network, no limits
curl http://localhost:4000/chat/completions
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "local-ollama-cpu-llama3.2-3b", "messages": [{"role":"user","content":"hello"}]}'
# image generation
curl http://localhost:4000/images/generations
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "hf-flux-schnell", "prompt": "a cat riding a skateboard"}'
# local image generation (no network, no cost)
curl http://localhost:4000/images/generations
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "local-sdcpp-cpu-sd-turbo", "prompt": "a red panda in a forest", "size": "512x512"}'
# transcription (local, CPU)
curl http://localhost:4000/audio/transcriptions
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-F "model=local-talkies-whisper-large-v3-turbo" -F "[email protected]"
# text-to-speech (local, multiple voices)
curl http://localhost:4000/audio/speech
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "local-talkies-kokoro-tts", "input": "Hello world", "voice": "af_heart"}'
-o speech.mp3
# web search (no API key, self-hosted)
curl http://localhost:4000/chat/completions
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "groq-qwen3-32b", "messages": [{"role":"user","content":"search the web for latest rust release notes"}]}'
# async — submit and poll
curl http://localhost:4000/q/v1/chat/completions
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "cerebras-gpt-oss-120b", "messages": [{"role":"user","content":"write a novel"}]}'Fünf Anbieter mit Gratis-Tarif, fünf lokale Engines, der Rest als Fallback. Langsamer auf einem normalen Rechner, aber es läuft, es ist privat, und niemand kann dich mit einem Ratenlimit aus deiner eigenen Infrastruktur aussperren.
github.com/psyb0t/aigate
Wie du ihn in deinen Agenten installierst
Dieser Skill ist nicht mehr nur für OpenClaw. Alles unter .agents/ ist in einem einzigen Marketplace katalogisiert, es sind also zwei Befehle:
claude plugin marketplace add psyb0t/agents
claude plugin install aigate@psyb0tCodex nutzt denselben Marketplace mit einem anderen Verb, codex plugin add aigate@psyb0t, weil es codex plugin install nicht gibt. Er findet den Skill außerdem von selbst in einem Checkout des Repos, da er .agents/skills/ nativ scannt, ganz ohne dass irgendwas installiert ist.