Alle Projekte

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

Diagramm: wie die pacod-Projekte zusammenpassen LLM-Aufrufe Tippe auf ein Projekt, um zu sehen, womit es verbunden ist.

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_url eines 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:

  1. Authentifizierung — das pacod-id-Token wird geprüft; eine beendete Sitzung oder ein deaktiviertes Konto wird abgewiesen.
  2. Agent — der angefragte Agent muss dem Benutzer zugewiesen sein; wer keinen nennt, bekommt seine einzige Zuweisung, nie eine Vermutung.
  3. Sprache — wird in jeder Runde erkannt und mit den Sprachen des Agenten abgeglichen.
  4. Kontingent — das Token-Limit pro Benutzer im Gateway, dazu ein Anfragekontingent und eine Drosselung in Redis.
  5. 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/models listet 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:

  1. 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).
  2. 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.
  3. Monitoring — Prometheus, Alertmanager und Grafana; optional, und make up-all startet es, wenn monitoring/.env existiert.

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 ProfileSpec in pacod-api/scripts/profiles/<id>.py (Thema, Sprachen, Prompt- und Einstellungs-Overrides) und Daten in pacod-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

Tech-Stack

Geschrieben in
  • Python
  • TypeScript
Tech-Stack
  • FastAPI
  • LangGraph
  • MCP
  • SvelteKit
  • PostgreSQL
  • Redis
  • Qdrant
  • Caddy
  • Grafana

Schnellstart

Schnellstart auf dem Laptop
make secrets-initmake up-allmake bootstrap-localmake smoke-allopen http://localhost:8080

Funktioniert mit

  • pacod-gw

    Alle LLM-Aufrufe laufen über das Gateway — Modelle, Preise, Anbieterschlüssel, Token-Limits, Nutzung und Kosten liegen beim Gateway.

  • pacod-id

    Konten, Passwörter, Sitzungen und Rollen liegen in pacod-id; die App und die Gateway-Konsole teilen sich ein Konto.

Lizenz

Apache-2.0