KI-Konzil/_bmad-output/planning-artifacts/epics.md
copilot-swe-agent[bot] 3be3cb73b6 Add all BMAD skill artifacts: epics, stories, sprint-status, QA tests, project-context, readiness report
Co-authored-by: Kenearos <86194771+Kenearos@users.noreply.github.com>
2026-03-12 14:26:40 +00:00

18 KiB
Raw Blame History

stepsCompleted inputDocuments bmadSkill bmadWorkflow
step-01-validate-prerequisites
step-02-design-epics
step-03-create-stories
step-04-final-validation
_bmad-output/planning-artifacts/prd.md
_bmad-output/planning-artifacts/architecture.md
_bmad-output/planning-artifacts/ux-design.md
PM Agent (John) — /bmad-agent-bmm-pm → [CE] Create Epics and Stories _bmad/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md

CouncilOS — Epic & Story Breakdown

Autor: John (📋 BMAD PM Agent) Datum: 2026-03-12 Version: 1.0.0


Anforderungs-Inventar

Funktionale Anforderungen

ID Anforderung
FR-01.1 Agent-Nodes per Drag & Drop auf den Canvas
FR-01.2 Node-Einstellungs-Panel (Name, System-Prompt, Modell, Tools)
FR-01.3 Lineare Edges zwischen Nodes
FR-01.4 Bedingte Edges mit Routing-Label
FR-01.5 Council unter Namen speichern
FR-01.6 Gespeicherten Council laden und bearbeiten
FR-01.7 Blueprint-JSON-Export
FR-02.1 Prompt-Eingabe als Council-Input
FR-02.2 PDF-Upload als Council-Input
FR-02.3 Auto-Pilot / God Mode Toggle
FR-02.4 Auto-Pilot läuft autonom
FR-02.5 God Mode pausiert vor jedem Agent
FR-02.6 Finales Dokument anzeigen
FR-02.7 Run-Verlauf einsehen
FR-03.1 Aktiver Node pulsiert im Canvas
FR-03.2 WebSocket-Events mit node_name + status
FR-03.3 done-Event nach Run-Abschluss
FR-04.1 God Mode Approval-Popup
FR-04.2 Approve → nächster Node
FR-04.3 Reject → Run abbrechen
FR-04.4 Modify → Draft bearbeiten vor Fortsetzung
FR-05.1 LLM-Modell pro Agent konfigurierbar
FR-05.2 Web-Suche optional aktivierbar
FR-05.3 PDF-Reader optional aktivierbar
FR-06.1 Blueprint-CRUD REST-API
FR-06.2 Blueprints in PostgreSQL JSONB
FR-06.3 version-Feld im Blueprint

Nicht-Funktionale Anforderungen

ID Anforderung
NFR-01.1 WebSocket < 500 ms
NFR-01.2 Blueprint-CRUD < 200 ms P95
NFR-01.3 ≥ 10 parallele Runs
NFR-02.1 API-Keys nur in Umgebungsvariablen
NFR-03.1 Test-Coverage ≥ 80 % agents/, ≥ 90 % state.py
NFR-03.2 Alembic für Migrationen
NFR-03.3 Dynamischer Graph ab Phase 3

FR-Abdeckungskarte

Epic Abgedeckte FRs
Epic 1 NFR-0103, Infrastruktur
Epic 2 FR-02.102.4, FR-02.6, FR-03.103.3 (Phase 1 Backend)
Epic 3 FR-01.101.7, FR-06.106.3 (Phase 2 Frontend)
Epic 4 FR-02.102.7, FR-03.103.3 (Phase 3 Integration)
Epic 5 FR-02.2, FR-04.104.4, FR-05.205.3 (Phase 4 Tools & God Mode)

Epic-Liste

  1. Epic 1: Projekt-Setup & Infrastruktur
  2. Epic 2: LangGraph Engine Backend (Phase 1)
  3. Epic 3: Visueller Baukasten Frontend (Phase 2)
  4. Epic 4: Frontend-Backend-Integration (Phase 3)
  5. Epic 5: Tools & God Mode (Phase 4)

Epic 1: Projekt-Setup & Infrastruktur

Ziel: Vollständig konfiguriertes, lauffähiges Entwicklungsumfeld mit Docker Compose, PostgreSQL, FastAPI-Skeleton und Next.js-Skeleton.

Story 1.1: Docker-Compose-Umgebung aufsetzen

Als Entwickler möchte ich eine vollständige lokale Docker-Compose-Umgebung, damit ich ohne lokale Python/Node-Installation entwickeln kann.

Akzeptanzkriterien:

Gegeben ein frisch geclontes Repository Wenn ich docker compose up -d ausführe Dann starten drei Services: db (PostgreSQL 16), api (FastAPI Port 8000), frontend (Next.js Port 3000) Und GET /api/health gibt {"status": "ok"} zurück Und das Frontend ist unter http://localhost:3000 erreichbar

Gegeben der db-Service läuft Wenn ich pg_isready im Container ausführe Dann antwortet PostgreSQL mit accepting connections

Story 1.2: Backend-Python-Umgebung & Requirements

Als Backend-Entwickler möchte ich eine vollständige requirements.txt mit allen Abhängigkeiten, damit ich reproduzierbar installieren kann.

Akzeptanzkriterien:

Gegeben ein Python 3.11+ Environment Wenn ich pip install -r requirements.txt ausführe Dann sind FastAPI, LangGraph, langchain-anthropic, langchain-openai, SQLAlchemy, alembic, chromadb, tavily-python, pypdf, pytest und alle Transitivabhängigkeiten installiert

Gegeben die Abhängigkeiten sind installiert Wenn ich pytest backend/tests/ ausführe Dann laufen alle Tests durch (auch wenn noch keine Testfälle existieren: 0 passed, 0 failed)

Story 1.3: Datenbank-Migrationen mit Alembic

Als Backend-Entwickler möchte ich Alembic-Migrationen für blueprints und council_runs, damit ich das Schema versioniert verwalten kann.

Akzeptanzkriterien:

Gegeben eine laufende PostgreSQL-Instanz Wenn ich alembic upgrade head ausführe Dann werden die Tabellen blueprints und council_runs erstellt Und alembic current zeigt die aktuelle Revision

Gegeben die Tabellen existieren Wenn ich ein Blueprint via REST-API erstelle Dann wird es in blueprints mit UUID, JSONB-Daten und Timestamps gespeichert


Epic 2: LangGraph Engine Backend (Phase 1)

Ziel: Funktionierender, hartcodierter LangGraph-Graph (Master→Critic→Writer) mit CouncilState, Routing-Logik und FastAPI-Endpunkten. Verifikation via Terminal/Postman.

Story 2.1: CouncilState TypedDict implementieren

Als Backend-Entwickler möchte ich den CouncilState TypedDict mit allen Feldern und Reducern, damit er das einzige State-Objekt für alle Agents ist.

Akzeptanzkriterien:

Gegeben state.py ist implementiert Wenn ich feedback_history mit operator.add als Reducer definiere Dann werden neue Feedback-Einträge angehängt — niemals überschrieben

Wenn ich messages mit operator.add als Reducer definiere Dann akkumuliert der LLM-Nachrichtenverlauf korrekt über mehrere Nodes

Wenn APPROVAL_THRESHOLD = 8.0 und MAX_ITERATIONS = 5 definiert sind Dann sind diese Konstanten importierbar und in Tests verwendbar

Story 2.2: Master-Agent-Node implementieren

Als Backend-Entwickler möchte ich den master_agent_node, damit er auf Basis von input_topic und feedback_history einen Draft erstellt.

Akzeptanzkriterien:

Gegeben ein CouncilState ohne feedback_history Wenn master_agent_node(state) aufgerufen wird (LLM gemockt) Dann enthält der Rückgabe-Dict current_draft mit einem nicht-leeren String Und messages enthält genau 3 Elemente (SystemMessage, HumanMessage, AIMessage) Und iteration_count ist um 1 erhöht

Gegeben ein State mit feedback_history = ["Too short"] Wenn master_agent_node(state) aufgerufen wird Dann enthält der User-Prompt den Text „feedback" oder die Feedback-Einträge

Story 2.3: Critic-Agent-Node implementieren

Als Backend-Entwickler möchte ich den critic_agent_node mit Score-Parsing und Routing, damit er Drafts bewertet und route_decision setzt.

Akzeptanzkriterien:

Gegeben ein Score < 8 in der LLM-Antwort Wenn critic_agent_node(state) aufgerufen wird Dann ist route_decision = "rework" Und feedback_history enthält einen neuen Eintrag

Gegeben ein Score ≥ 8 Dann ist route_decision = "approve" Und feedback_history bleibt unverändert

Gegeben iteration_count >= MAX_ITERATIONS Dann ist route_decision = "approve" ohne LLM-Aufruf (Safety Valve)

Gegeben eine nicht-parsbare LLM-Antwort Dann fällt route_decision auf "rework" zurück — kein Crash

Story 2.4: Writer-Agent-Node implementieren

Als Backend-Entwickler möchte ich den writer_agent_node, damit er den finalen Draft für die Ausgabe formatiert.

Akzeptanzkriterien:

Gegeben ein CouncilState mit current_draft Wenn writer_agent_node(state) aufgerufen wird (LLM gemockt) Dann enthält der Rückgabe-Dict current_draft (finaler Output) Und active_node = "writer_agent"

Story 2.5: LangGraph-Graph bauen und ausführen

Als Backend-Entwickler möchte ich einen kompilierten LangGraph-Graphen (build_council_graph), damit er Master→Critic→(conditional)→Writer ausführt.

Akzeptanzkriterien:

Gegeben build_council_graph() wird aufgerufen Dann ist der zurückgegebene Graph kompiliert und invoke-fähig

Gegeben ein hartcodierter Test-Input (LLMs gemockt, Score 9 bei 2. Iteration) Wenn graph.invoke(initial_state) aufgerufen wird Dann durchläuft der Graph: master→critic→(rework)→master→critic→(approve)→writer→END Und der finale State hat route_decision = "approve" und iteration_count = 2

Story 2.6: FastAPI-Run-Endpunkte implementieren

Als API-Nutzer möchte ich POST /api/councils/run und GET /api/councils/run/{run_id}, damit ich einen Council-Run starten und sein Ergebnis abrufen kann.

Akzeptanzkriterien:

Gegeben POST /api/councils/run mit {"input_topic": "Test"} Wenn der Endpunkt aufgerufen wird Dann gibt er 202 Accepted mit run_id zurück Und der Run läuft asynchron im Hintergrund

Gegeben ein abgeschlossener Run Wenn GET /api/councils/run/{run_id} aufgerufen wird Dann gibt er status: "completed" und final_draft zurück

Gegeben eine unbekannte run_id Dann gibt er 404 Not Found zurück


Epic 3: Visueller Baukasten Frontend (Phase 2)

Ziel: React Flow Canvas mit Custom Nodes/Edges, Node-Einstellungs-Panel, Blueprint-Parser und PostgreSQL-Speicherung.

Story 3.1: React-Flow-Canvas mit Custom Agent Node

Als Nutzer möchte ich Agent-Nodes per Drag & Drop auf den Canvas ziehen, damit ich meinen KI-Rat visuell zusammenstellen kann.

Akzeptanzkriterien:

Gegeben der Rat-Architekt-Tab ist geöffnet Wenn ich einen Node aus der Seitenleiste auf den Canvas ziehe Dann erscheint ein Custom-Agent-Node mit Default-Name, Default-Modell und Tool-Badges

Gegeben ein Node ist auf dem Canvas Wenn ich ihn anklicke Dann öffnet sich das rechte Einstellungs-Panel

Gegeben das Einstellungs-Panel ist offen Wenn ich den Namen ändere Dann aktualisiert sich der Canvas-Node sofort (Live-Bindung)

Story 3.2: Lineare und bedingte Edges

Als Nutzer möchte ich Pfeile zwischen Nodes ziehen und als linear/bedingt markieren, damit ich den Workflow meines Councils definieren kann.

Akzeptanzkriterien:

Gegeben zwei Nodes auf dem Canvas Wenn ich vom Ausgangs-Handle des ersten zum Eingangs-Handle des zweiten ziehe Dann erscheint ein linearer Pfeil (grau, durchgehend)

Gegeben ich klicke eine Edge an Wenn ich sie als „bedingt" mit Label „rework" markiere Dann wird sie gestrichelt rot mit Label dargestellt

Gegeben ich markiere eine Edge als „approve" Dann wird sie grün dargestellt

Story 3.3: Blueprint-Parser (React Flow → JSON)

Als System möchte ich eine parseGraphToBlueprint()-Funktion, damit sie den Canvas-State in ein valides Blueprint-JSON konvertiert.

Akzeptanzkriterien:

Gegeben ein Canvas mit zwei Nodes und einer linearen Edge Wenn parseGraphToBlueprint(nodes, edges, name) aufgerufen wird Dann enthält das JSON version, name, nodes[], edges[]

Gegeben eine bedingte Edge mit Condition-Label Dann ist type: "conditional" und condition: "<label>" im Edge-JSON

Gegeben ein isolierter Node (keine Edges) Dann erscheint eine Konsolenwarnung — der Node wird nicht aus dem JSON entfernt

Story 3.4: Blueprint CRUD — Frontend & Backend

Als Nutzer möchte ich Councils speichern, laden und löschen können, damit ich meine Configurations wiederverwenden kann.

Akzeptanzkriterien:

Gegeben ein ausgefüllter Canvas Wenn ich „Speichern" klicke Dann wird POST /api/councils/ aufgerufen und eine id zurückgegeben Und eine Erfolgsmeldung erscheint

Gegeben bestehende Blueprints Wenn ich die Blueprint-Liste abrufe (GET /api/councils/) Dann sehe ich alle gespeicherten Councils mit Name und Datum

Gegeben einen Blueprint per id Wenn ich DELETE /api/councils/{id} aufrufe Dann gibt der Endpunkt 204 No Content zurück Und ein anschließender GET gibt 404 zurück


Epic 4: Frontend-Backend-Integration (Phase 3)

Ziel: LangGraph liest JSON-Blueprint und baut Graph dynamisch. WebSocket-Events pulsieren Nodes im Canvas. Finaler Output erscheint im Frontend.

Story 4.1: Dynamischer Graph-Builder aus Blueprint-JSON

Als Backend-Entwickler möchte ich dynamic_graph_builder.py, damit er aus einem Blueprint-JSON zur Laufzeit einen LangGraph-Graphen baut.

Akzeptanzkriterien:

Gegeben ein valides Blueprint-JSON mit 2 Nodes und 1 linearer Edge Wenn build_graph_from_blueprint(blueprint) aufgerufen wird Dann gibt er einen kompilierten StateGraph zurück

Gegeben ein Blueprint mit Zyklus (A→B→A, bedingt) Dann kompiliert der Graph korrekt — kein Fehler, Zyklus bleibt erhalten

Gegeben ein Blueprint mit nicht-existenter Node-ID in einer Edge Dann wird ein ValueError mit klarer Fehlermeldung geworfen

Gegeben ein Blueprint mit 0 Nodes Dann wird ein ValueError geworfen

Story 4.2: WebSocket-Agent-Events integrieren

Als Frontend möchte ich WebSocket-Events vom Backend, damit der aktive Node im Canvas pulsiert.

Akzeptanzkriterien:

Gegeben ein laufender Council-Run Wenn LangGraph in master_agent_node eintritt Dann sendet das Backend {"node": "master_agent", "status": "running"} über WS

Gegeben das Frontend verbindet sich mit WS /ws/council/{run_id} Wenn ein Node-Event empfangen wird Dann wechselt der entsprechende Node im Canvas in den Pulsier-Zustand (gelb)

Gegeben der Run ist abgeschlossen Dann sendet das Backend {"status": "done"} und das Frontend bricht die WS-Verbindung

Story 4.3: Konferenzzimmer — Live-Execution-UI

Als Nutzer möchte ich im Konferenzzimmer-Tab den laufenden Council sehen, damit ich transparent nachvollziehen kann, was die KI tut.

Akzeptanzkriterien:

Gegeben ich starte einen Blueprint-Run Wenn der Run läuft Dann zeigt das Canvas (read-only) den aktuell aktiven Node pulsierend

Wenn der Run abgeschlossen ist Dann erscheint das finale Dokument im Output-Bereich

Gegeben ein Run schlägt fehl Dann erscheint eine klare Fehlermeldung mit dem Fehlergrund


Epic 5: Tools & God Mode (Phase 4)

Ziel: Tavily-Web-Suche, PDF-Reader mit ChromaDB, und Human-in-the-Loop via interrupt_before.

Story 5.1: Tavily Web-Suche als Agent-Tool

Als Nutzer möchte ich Web-Suche als optionales Tool für jeden Agent, damit Agents aktuelle Informationen aus dem Internet nutzen können.

Akzeptanzkriterien:

Gegeben ein Agent mit tools.web_search = true Wenn der dynamische Graph-Builder den Agent aufbaut Dann wird web_search als Tool an den Agent gebunden

Gegeben TAVILY_API_KEY ist gesetzt Wenn web_search("KI-Trends 2025") aufgerufen wird Dann gibt die Funktion eine formatierte Liste von Treffern zurück (gemockt in Tests)

Gegeben TAVILY_API_KEY ist nicht gesetzt Dann gibt die Funktion eine klare Fehlermeldung zurück — kein Crash

Story 5.2: PDF-Upload & ChromaDB-Ingestion

Als Nutzer möchte ich ein PDF hochladen, das als Wissensquelle für Agents dient, damit Agents auf Inhalte aus langen Dokumenten zugreifen können.

Akzeptanzkriterien:

Gegeben POST /api/councils/upload-pdf mit einer validen PDF-Datei Wenn der Endpunkt aufgerufen wird Dann wird das PDF in Chunks aufgeteilt, in ChromaDB gespeichert, und chunks_ingested zurückgegeben

Gegeben eine Nicht-PDF-Datei Dann gibt der Endpunkt 400 Bad Request zurück

Gegeben ein Agent mit tools.pdf_reader = true Wenn pdf_search("Schlüsselergebnisse") aufgerufen wird Dann gibt die Funktion die Top-K semantisch ähnlichsten Chunks zurück

Story 5.3: God Mode — Human-in-the-Loop

Als Nutzer möchte ich im God Mode jeden Schritt des Councils genehmigen, damit ich volle Kontrolle über den Prozess habe.

Akzeptanzkriterien:

Gegeben ein Blueprint-Run mit god_mode = true Wenn LangGraph den ersten Node abschließt Dann pausiert der Graph via interrupt_before und status = "paused"

Gegeben ein pausierter Run Wenn POST /api/councils/run/{run_id}/approve mit {"action": "approve"} aufgerufen wird Dann setzt der Graph am nächsten Node fort

Gegeben {"action": "reject"} Dann wird der Run mit status = "failed" beendet

Gegeben {"action": "modify", "modified_state": {"current_draft": "..."}} Dann setzt der Graph mit dem modifizierten Draft fort

Gegeben das Frontend verbindet sich im God Mode Wenn der Run pausiert Dann erscheint das God-Mode-Overlay mit Agent-Name, Vorschlag, Grund und den drei Buttons

Story 5.4: Run-Verlauf (History)

Als Nutzer möchte ich vergangene Council-Runs einsehen, damit ich Ergebnisse nachträglich nachschlagen kann.

Akzeptanzkriterien:

Gegeben abgeschlossene Runs Wenn GET /api/runs/ aufgerufen wird Dann gibt er eine paginierte Liste aller Runs zurück

Gegeben eine run_id Wenn GET /api/runs/{run_id} aufgerufen wird Dann gibt er status, final_draft, critic_score, iteration_count zurück

Gegeben eine unbekannte run_id Dann gibt er 404 Not Found zurück