Plattform für KI-Agenten
pacod-ap
Beliebig viele KI-Agenten auf einem Deployment hosten — jeder mit eigenem Wissen, eigenen Prompts und Regeln, hinter einer gemeinsamen Anmeldung.
pacod-ap ist eine Plattform zum Bauen von Agenten. Jeder Agent (ein Profil) hat seine eigene Wissensdatenbank, Referenzfakten, Prompts, Direktiven, Konfiguration, Unterhaltungen und Reviews, und alle teilen sich eine Anmeldung, eine Admin-Konsole und ein LLM-Gateway.
- Apache-2.0
- Version 0.1.0
- Vorschau
Funktionen
-
Agenten als Profile
Jeder Agent ist eigenständig — Wissensdatenbank, Referenzfakten, Prompts, Direktiven, Laufzeitkonfiguration und Unterhaltungen.
-
Wissen pro Agent
Ingestion, Embeddings und Retrieval über den eigenen Korpus jedes Agenten, gespeichert in Qdrant.
-
LangGraph und MCP
Agenten laufen auf LangGraph, mit Tools, die über das Model Context Protocol bereitgestellt werden.
-
Visueller Agenten-Editor
Den Ablauf eines Agenten auf einer Arbeitsfläche in der Admin-Konsole gestalten.
-
Streaming-Chat
Chat über Server-Sent Events mit Agentenauswahl; dieselben Agenten stehen auch über eine OpenAI-kompatible API bereit.
-
Verbesserungskreislauf
Reviews pro Gesprächsrunde fließen zurück in Prompts und Direktiven, sodass Agenten mit der Nutzung besser werden.
-
Eine Admin-Konsole
Benutzer, Wissensdatenbanken, Direktiven, Prompts, Modell- und Websuche-Einstellungen, Cache, Analysen und Crawler an einem Ort.
-
Mehrsprachig
Agenten auf Bulgarisch und Englisch direkt einsatzbereit; die Oberfläche auf Englisch, Bulgarisch, Deutsch und Russisch.
Einordnung
Warum es das gibt
pacod-ap ist für Agenten gebaut, deren Aufgabe es ist, in einem Fachgebiet korrekte Antworten mit Quellen zu geben — dort, wo ein falscher Preis, Satz oder Termin schlimmer ist als gar keine Antwort. Drei Regeln prägen die Plattform:
- Jede Zahl stammt aus einer strukturierten Datenquelle, nie aus dem Gedächtnis des Modells.
- Jede Aussage nennt eine Quelle — eine Passage aus der Wissensdatenbank, die
source_urleines Fakts oder eine Webseite von der Allow-List. - Admins korrigieren einen Agenten ohne neues Deployment — Modelle, Prompts, Direktiven, Websuche und Caching greifen ab der nächsten Gesprächsrunde.
Ein Deployment, viele Agenten
Ein Agent ist ein Profil: eine Zeile in der Tabelle profiles plus alles, was dazugehört.
Zwei sind schon dabei:
- starter — eine generische Vorlage: ein kleiner fiktiver Helpdesk („Nimbus Notes“), der die Wissensdatenbank und die Referenzfakten-Tools nutzt. Kopiere ihn, um deinen eigenen Agenten zu starten.
- taxes — ein fortgeschrittenes Beispiel für bulgarisches Steuer- und Rechnungswesen, mit
eigenen Prompts, Fakten, Gesetzeskorpus und einer Allow-List für die Websuche
(
make seed-example PROFILE=taxes). Sein Korpus zeigt Retrieval auf einem echten Gesetzesbestand; er wird nicht aktuell gehalten, und nichts, was der Agent sagt, ist Rechts- oder Steuerberatung.
Die Isolation zwischen Agenten ist eine Sicherheitsgrenze: Jede Zeile eines Agenten trägt eine
profile_id, und jeder Agent hat eigene Qdrant-Collections.
| Pro Agent | Gemeinsam im Deployment |
|---|---|
| Referenzfakten, Direktiven, Prompts, eingelesene Quellen | Konten und Rollen (pacod-id) |
| Modell pro Rolle; Einstellungen für Websuche, Cache und Reviews | LLM-Vorlagen und Websuche-Schlüssel |
| Unterhaltungen, Audit-Logs, Retrieval-Traces | Der Embeddings-Dienst — ein Raum mit 1024 Dimensionen |
| Review-Befunde, Golden Tests, Editor-Versionen | Anbieter, Modelle, Preise und Token-Limits (pacod-gw) |
Benutzer sehen nur die Agenten, die ihnen zugewiesen sind; Admins arbeiten global oder auf einen Agenten beschränkt. Kontingente zählen pro Benutzer über alle Agenten hinweg. Agenten sprechen Bulgarisch und Englisch; eine dritte Sprache ist eine Codeänderung, keine Konfiguration.
Die Bausteine
| Container | Rolle |
|---|---|
pacod-caddy |
Der einzige öffentliche Zugang: TLS und Reverse Proxy |
ap-frontend |
SvelteKit-Backend-for-Frontend: Chat, Agentenauswahl und Admin-Konsole; hält die Tokens auf dem Server |
ap-api |
Die Chat-API und der LangGraph-Agent, dazu ein OpenAI-kompatibles /v1 |
ap-admin-api |
Die Steuerungsebene: Konfiguration pro Agent, Profile, Zuweisungen, Fassaden zu pacod-id und dem Gateway |
ap-ingestion |
Zerlegt, bettet ein und speichert Dokumente in den Collections eines Agenten |
ap-mcp |
Die Referenzfakten-Tools get_fact und list_facts |
pacod-embeddings |
bge-m3-Embeddings und ein bge-reranker-Cross-Encoder, gemeinsam für alle Agenten |
ap-improvement-loop-worker, ap-newsletter-worker |
Dauerhaft laufende Worker, die Warteschlangen-Tabellen in PostgreSQL abarbeiten |
Jeder Container hat im gemeinsamen Docker-Netzwerk pacod-net genau einen Namen: ap-* für die
eigenen Dienste von pacod-ap, pacod-* für die Komponenten, die es mit den anderen pacod-Projekten
teilt. Der Chat der App ist die einzige Chat-Oberfläche.
Wie eine Gesprächsrunde abläuft
Die Prüfungen laufen, bevor irgendetwas gestreamt wird, sodass eine Ablehnung ein sauberer HTTP-Status ist und kein Fehler mitten im Stream:
- Authentifizierung — das pacod-id-Token wird geprüft; eine beendete Sitzung oder ein deaktiviertes Konto wird abgewiesen.
- Agent — der angefragte Agent muss dem Benutzer zugewiesen sein; wer keinen nennt, bekommt seine einzige Zuweisung, nie eine Vermutung.
- Sprache — wird in jeder Runde erkannt und mit den Sprachen des Agenten abgeglichen.
- Kontingent — das Token-Limit pro Benutzer im Gateway, dazu ein Anfragekontingent und eine Drosselung in Redis.
- Thema — ein Filter für illegale Formulierungen, dann ein günstiger Klassifikator: Fragen außerhalb des Themas werden abgelehnt, unklare bekommen Rückfragen.
Dann öffnet sich der Server-Sent-Events-Stream. Eine erste Frage kann aus dem semantischen Antwort-Cache des Agenten beantwortet werden; sonst läuft ein kleiner LangGraph-Graph:
- plan — der Planer liefert JSON: welche Tools aufgerufen werden und ob die Frage komplex ist.
- execute tools — alle geplanten Aufrufe laufen parallel:
kb_search,get_fact/list_facts,web_search. - synthesize — das Hauptmodell streamt die Antwort aus diesem Kontext, bei komplexen Runden mit Extended Thinking, und schlägt zum Schluss Folgefragen vor.
Ältere Runden werden in eine fortlaufende Zusammenfassung gefaltet, sodass ein langer Chat nicht
seinen ganzen Verlauf erneut sendet. Das OpenAI-kompatible /v1 durchläuft dieselben Prüfungen und denselben Agenten (ohne
Antwort-Cache), wobei jeder Agent als Modell erscheint. Es wird nicht über den öffentlichen Zugang
geroutet; Clients erreichen es im internen Netzwerk.
Wissen, Fakten und das Web
Der Planer wählt die Quelle nach der Art der Aussage:
- Zahlen, Preise, Sätze, Limits und Termine kommen nur aus den Referenzfakten — typisierte Zeilen in PostgreSQL, bereitgestellt über MCP. Der Code, nicht das Modell, setzt bei jedem Aufruf den Agenten und das Bezugsjahr, sodass der Planer die Fakten eines anderen Agenten nicht erreichen kann.
- Erklärungen kommen aus der Wissensdatenbank: Dense-Suche in Qdrant, ein Cross-Encoder-Reranking, dann werden kleine Chunks auf ihre Elternpassage erweitert. Eine separate, niedriger gewichtete kuratierte Collection enthält Notizen, die Admins geschrieben oder freigegeben haben.
- Aktuelle Informationen kommen aus der Websuche, beschränkt auf eine Domain-Allow-List pro Agent.
Ein Fakt hat eine einzige generische Form, sodass die Preise eines Helpdesks und die Fristen eines Steueragenten in derselben Tabelle liegen — ein neues Fachgebiet ist Daten, kein Schema:
{"fact_key": "plan_price_monthly", "variant": "plus", "category": "pricing",
"legal_year": 2026, "value_type": "money", "value_num": 6, "unit": "EUR",
"label_en": "Plus plan — price per user per month",
"source_url": "https://acme.example/pricing"}
Ein optionaler Verifier, standardmäßig aus, prüft die Zahlen der Antwort gegen die Tool-Ergebnisse. Das Fine-Tuning des Retrievals anhand von Nutzerfeedback wird von Hand gestartet; nichts plant es ein.
Der Verbesserungskreislauf
Jeder Agent lernt aus seinem eigenen Verkehr. Ein Worker prüft die jüngsten, geschwärzten Unterhaltungen des Agenten täglich oder auf Anfrage. Er bewertet jede Antwort anhand dessen, was der Assistent tatsächlich gelesen hat — des wörtlichen Kontexts und der geltenden Direktiven —, so dass ein Urteil keine Vermutung ist.
| Fehler | Wohin er geht |
|---|---|
| Inhaltslücke | Ein Kandidat für die Wissensdatenbank in der Review-Warteschlange, den ein Mensch freigibt |
| Retrieval-Fehlgriff | Der Retrieval-Trace der Runde, zum Nachjustieren |
| Halluzination, Ton, Verhalten | Eine Prompt-Korrektur oder ein Direktiven-Entwurf, inaktiv angelegt |
| Eine saubere Antwort | Ein Golden Test |
Ähnliche Befunde werden zu Clustern gruppiert, und ein Cluster ist das Ticket, das ein Reviewer bearbeitet. Nichts gelangt in die kuratierte Collection, bevor ein Admin es freigibt — es sei denn, ein Auto-Insert-Flag (standardmäßig aus) ist aktiviert und strenge Prüfungen bestehen; eine Aussage, der die Quellen widersprechen, wird nie automatisch eingefügt.
Sicherheit und Isolation
- Identität ist ausgelagert. Konten, Passwörter, Sitzungen und Rollen liegen in pacod-id. Die API folgt dem Feed von pacod-id, sodass eine beendete Sitzung oder ein deaktiviertes Konto innerhalb von Sekunden abgewiesen wird. Konto- und Rollenänderungen erfolgen in pacod-id im Namen des handelnden Admins: Nur ein Superuser macht einen Superuser, und der letzte Admin kann nicht entfernt werden.
- Agenten sind im Code abgegrenzt. Der Agent wird vor jeder Arbeit autorisiert, Tool-Argumente,
die Agentendaten betreffen, setzt der Code,
/v1/modelslistet nur die Agenten des Aufrufers, und jeder Cache-Schlüssel eines Agenten trägt dessen ID. - Geheimnisse bleiben, wo sie sind. Die Schlüssel der LLM-Anbieter liegen nur im Gateway.
Websuche-Schlüssel sind in der Datenbank verschlüsselt. Geheimnis-Dateien werden generiert, haben
die Rechte 0600 und stehen in
.gitignore; interne Dienste verweigern den Zugriff, wenn ihr gemeinsames Token fehlt. - Prompt-Sicherheit. Die Ablehnung illegaler Anfragen steht ganz oben in den Prompts von Planer und Synthesizer und hat Vorrang vor Admin-Direktiven; Text von Admins und Benutzern wird immer als Wert eingesetzt, nie als Vorlage.
Betrieb
Drei Docker-Compose-Stacks starten der Reihe nach — make up-all erledigt das:
- Die App — zwei Compose-Dateien. Die App-Datei enthält die eigenen Dienste von pacod-ap, Redis, PgBouncer und den Embeddings-Dienst; die Standalone-Datei enthält seine Kopien der gemeinsamen Komponenten: Caddy, PostgreSQL, Qdrant und pacod-id (lokal dazu mailpit).
- Das Gateway — die App-Datei von pacod-gw aus einem Checkout neben diesem. Es meldet sich über dasselbe pacod-id an, legt seine Datenbank in derselben PostgreSQL-Instanz ab und wird über denselben Caddy ausgeliefert.
- Monitoring — Prometheus, Alertmanager und Grafana; optional, und
make up-allstartet es, wennmonitoring/.envexistiert.
Weil die gemeinsamen Komponenten in einer eigenen Datei liegen, kann pacod-demo die App-Datei von pacod-ap neben den anderen pacod-Projekten laden und jede gemeinsame Komponente nur einmal betreiben; das Ergebnis läuft unter demo.pacod.io. Von jeder gemeinsamen Komponente kann pro Host nur eine Kopie laufen, daher läuft pacod-ap allein nicht neben einem anderen pacod-Stack.
Lokal antwortet das Gateway mit seinen Mock-Anbietern: vorgegebene Antworten, keine Kosten.
Konfiguration wird aus einem Redis-Cache gelesen, dann aus einer app_settings-Zeile pro
Agent, dann aus dem Standardwert der Umgebung; bei einem Ausfall greifen die Standardwerte, statt
eine Runde zu blockieren.
LLM-Aufrufe werden Benutzer, Sitzung, Runde, Agent und Zweck zugeordnet, sodass die Nutzungs- und Kostenseiten der Konsole die Berichte des Gateways lesen, statt ein eigenes Kassenbuch zu führen. Ein Aufruf mit Zeitüberschreitung wird nie wiederholt — der Anbieter berechnet ihn ohnehin —, also fragt der Benutzer erneut.
Beobachtbarkeit — eine Audit-Zeile pro Anfrage, eine optionale schrittweise Debug Console, strukturierte Logs und Prometheus-Metriken von jedem Dienst, mit Grafana-Dashboards für App, Infrastruktur, Web-Traffic, Crawler und Nutzung, dazu die des Gateways.
Backup — make backup schreibt ein Archiv mit den Datenbank-Dumps, Qdrant-Snapshots,
Konfiguration und Geheimnissen; make restore stellt es wieder her.
Bau deinen eigenen Agenten
Es gibt zwei Wege:
- In der Konsole — ein Superuser legt einen Agenten auf der Seite Profiles oder im visuellen
Agenten-Editor an. Ein neuer Agent startet in
dev; du testest ihn dort und veröffentlichst ihn, wenn er fertig ist. Versionen werden nur angehängt, sodass Veröffentlichen und Zurückrollen bloß einen Zeiger verschieben. Ein KI-Assistent entwirft Prompts und andere Texte, ändert aber nie den Graphen selbst. - Als Code — eine
ProfileSpecinpacod-api/scripts/profiles/<id>.py(Thema, Sprachen, Prompt- und Einstellungs-Overrides) und Daten inpacod-api/data/profiles/<id>/: Referenzfakten, ein Korpus und ein Golden Set an Fragen.make seed-example PROFILE=<id>installiert ihn.
Dann chatte mit ihm, sieh dir die Debug Console und den Trace einer Runde im Gateway an und lass
make eval gegen das Golden Set laufen. Ab da übernimmt der Verbesserungskreislauf.
Weiterlesen
- Runbook — Stacks, Geheimnisse, echte Anbieter, Backup, Fehlersuche.
- Das LLM-Gateway — Zuordnung, Wiederholungen, Kontingente, Nutzung.
- Bau deinen eigenen Agenten — die komplette Anleitung.
- API-Architektur und UI-Architektur — das Design im Detail.
Tech-Stack
- Geschrieben in
- Python
- TypeScript
- Tech-Stack
- FastAPI
- LangGraph
- MCP
- SvelteKit
- PostgreSQL
- Redis
- Qdrant
- Caddy
- Grafana
Schnellstart
make secrets-initmake up-allmake bootstrap-localmake smoke-allopen http://localhost:8080Funktioniert mit
Lizenz
Apache-2.0