KI-Konzil/_bmad-output/implementation-artifacts/stories/2-5-langgraph-graph-bauen-und-ausfuehren.md
copilot-swe-agent[bot] d4cfb34423 Changes before error encountered
Co-authored-by: Kenearos <86194771+Kenearos@users.noreply.github.com>
2026-03-12 15:00:09 +00:00

62 lines
2.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Story 2.5: LangGraph-Graph bauen und ausführen
<!-- 🏃 Prepared by BMAD SM Skill — Agent: Bob (Scrum Master) -->
<!-- Skill Command: /bmad-agent-bmm-sm → [CS] Context Story -->
Status: done
## Story
Als **Backend-Entwickler**,
möchte ich **einen kompilierten LangGraph-Graphen** (`build_council_graph`),
so dass er **Master→Critic→(conditional)→Writer ausführt**.
## Acceptance Criteria
1. `build_council_graph()` gibt kompilierten, `invoke`-fähigen `StateGraph` zurück
2. Graph-Topologie: `master_agent → critic_agent → (rework: master_agent | approve: writer_agent) → END`
3. `route_after_critic(state)` liest `route_decision` und leitet korrekt weiter
4. `run_council_async()` führt den Graph in einem Thread-Pool aus (blockiert Event Loop nicht)
5. WebSocket-Callback `on_node_start` wird vor jedem Node aufgerufen
## Tasks / Subtasks
- [x] Task 1: `services/graph_builder.py` mit `build_council_graph()` (AC: 1, 2)
- [x] Subtask 1.1: `StateGraph(CouncilState)` mit drei Nodes
- [x] Subtask 1.2: `set_entry_point("master_agent")`
- [x] Subtask 1.3: `add_conditional_edges` für Critic-Routing
- [x] Task 2: `route_after_critic(state)` Routing-Funktion (AC: 3)
- [x] Task 3: `run_council_async()` mit `asyncio.get_event_loop().run_in_executor()` (AC: 4, 5)
- [x] Task 4: Integration-Tests (LLMs gemockt) (AC: 13)
## Dev Notes
- `interrupt_before` nicht in Phase-1-Graph (nur in dynamischem Builder Phase 3)
- `on_node_start`-Callback: `lambda run_id, node_name: broadcast_event(run_id, {...})`
- Thread-Pool: `asyncio.get_event_loop().run_in_executor(None, graph.invoke, state)`
### Project Structure Notes
- `backend/services/graph_builder.py`
- `backend/tests/test_routing.py`
### References
- [Source: _bmad-output/planning-artifacts/architecture.md#ADR-002]
- [Source: CLAUDE.md#Key Design Constraints — Cycles are first-class]
## Dev Agent Record
### Agent Model Used
Amelia (💻 BMAD Dev Agent)
### Completion Notes List
- `run_in_executor(None, ...)` nutzt Standard-Thread-Pool von asyncio; kein expliziter ThreadPoolExecutor nötig.
- Wrapper-Nodes für `on_node_start`-Callback werden zur Laufzeit um den Original-Node gelegt.
### File List
- `backend/services/graph_builder.py`
- `backend/tests/test_routing.py`