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

2.2 KiB
Raw Blame History

Story 2.5: LangGraph-Graph bauen und ausführen

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

  • Task 1: services/graph_builder.py mit build_council_graph() (AC: 1, 2)
    • Subtask 1.1: StateGraph(CouncilState) mit drei Nodes
    • Subtask 1.2: set_entry_point("master_agent")
    • Subtask 1.3: add_conditional_edges für Critic-Routing
  • Task 2: route_after_critic(state) Routing-Funktion (AC: 3)
  • Task 3: run_council_async() mit asyncio.get_event_loop().run_in_executor() (AC: 4, 5)
  • 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