Strona główna / Artykuły

Agenci LangGraph działające równolegle, które przeglądają prośby o pull request za pośrednictwem webhooków FastAPI.

Jak webhook, kolejka Redis oraz cztery agenty LangGraph przekształcają prośbę o pull request w ocenioną, ustrukturyzowaną recenzję AI w ciągu około 30 sekund, przy użyciu ngrok do testów lokalnych.

Wydawca: REACTAPP.TOP12 min czytania2837 słów

Źródła: Building a Multi-Agent PR Code Review System With LangGraph, FastAPI, Webhooks, and Docker

Każdy, kto otwierał prośbę o połączenie kodu, zna to oczekiwanie. Funkcja zostaje ukończona, kod wysyłany, a potem mijają dwie godziny, cały dzień lub nawet więcej. Gdy koledzy z zespołu w końcu ją sprawdzą, pojawia się tuzin komentarzy, z których połowa dotyczy błędów, które oprogramowanie mogło samo wykryć: stała klucz API, funkcja nazwana x, zapytanie SQL podatne na iniekcję. Autor naprawia wszystko, ponownie wysyła kod i znów czeka.

Sama ocena kodu jest niezbędna, więc to nie jest temat skargi. Frustrację budzi fakt, że tak wiele informacji po pierwszej weryfikacji ma charakter mechaniczny – zawsze te same kategorie problemów w każdej prośbie o połączenie kodu. Ideą tego systemu jest umożliwienie sztucznej inteligencji natychmiastowego wykrycia wszystkich oczywistych błędów, aby ludzcy recenzenci mogli skupić się na architekturze i logice, tam gdzie rzeczywiście potrzebna jest ludzka ocena. Działa lepiej, niż można by się spodziewać.

Dlaczego kilka agentów jest lepsze niż jeden

Naiwny projekt wysyła różnicę w PR do modelu z poleceniem jej przejrzenia. To wystarcza przy małych zmianach. Gdy PR stają się większe, model, który musi jednocześnie brać pod uwagę kwestie bezpieczeństwa, wydajności i jakości kodu, traci koncentrację, a wyniki oceny się pogarszają.

Specjalizacja rozwiązuje ten problem. Każdemu agentowi przydzielamy jedno zadanie: jeden ma myśleć wyłącznie o bezpieczeństwie, drugi o wydajności, trzeci o jakości kodu, a czwarty bierze te trzy raporty i pisze klarowną, profesjonalną ocenę. Ten model wielu agentów daje znacznie lepsze rezultaty niż jeden agent ogólnikowy.

Ogólny projekt, w którym każdy komponent ma jedną odpowiedzialność:

You open a Pull Request on GitHub
              │
              ▼
    GitHub fires a webhook
              │
              ▼
    FastAPI receives it instantly
    └── Verifies HMAC signature
    └── Pushes job to Redis queue
    └── Returns 202 to GitHub ✅
              │
              ▼
    ARQ Worker picks up the job
              │
              ▼
    LangGraph Pipeline starts
              │
    ┌─────────┼─────────┐
    ▼         ▼         ▼
 Agent 1   Agent 2   Agent 3
 Quality   Security  Performance
    │         │         │
    └─────────┼─────────┘
              ▼
           Agent 4
        Final Reviewer
              │
              ▼
    Comment posted on your PR ✅
    (in under 30 seconds)

Krok 1: webhook GitHub

Wszystko zaczyna się od webhooka. Gdy otwierana lub aktualizowana jest prośba o połączenie (pull request), GitHub wysyła żądanie HTTP POST do skonfigurowanej przez Ciebie adresu URL, a w tym żądaniu znajduje się numer PR, tytuł, autor, repozytorium oraz akcja, która je wywołała. Serwer FastAPI oczekuje na to żądanie w tym adresie URL.

Pierwszym krokiem serwera w odpowiedzi na każde żądanie jest sprawdzenie podpisu. GitHub podpisywał każdy przekazane dane za pomocą hasza HMAC-SHA256, wykorzystując sekret określony przez Ciebie; niezgodność podpisu oznacza natychmiastową odrzucenie żądania, dzięki czemu nikt nie może wysyłać fałszywych zdarzeń PR do tego endpointu.

Następna decyzja jest kluczowa: serwer nie rozpoczyna natychmiast przeglądu przez AI. Umieszcza zadanie w kolejce Redis i odpowiada GitHubowi kodem 202 Accepted w mniej niż sekundę. Powodem jest to, że GitHub oczekuje odpowiedzi webhook w ciągu 10 sekund, natomiast pełny przegląd z trzema równoległymi wywołaniami LLM zajmuje od 25 do 30 sekund. Przeglądanie w trybie inline sprawiłoby, że GitHub uznałby, iż serwer zawiodł, i spróbowałby ponownie, więc PR byłby przeglądany kilka razy z duplikowanymi komentarzami. Kolejka zadań rozwiązuje ten problem całkowicie – GitHub otrzymuje szybką odpowiedź, a rzeczywła praca odbywa się w tle.

Krok 2: ngrok do lokalnego rozwoju

Podczas lokalnego rozwoju serwer FastAPI działa pod adresem localhost:8000, do którego GitHub nie może uzyskać dostępu z Internetu. ngrok wypełnia tę lukę, tworząc bezpieczny tunel pomiędzy publicznym adresem URL a lokalnym komputerem. Wystarczy jeden polecenie, aby to uruchomić:

ngrok http 8000

Od razu zwraca publiczny adres https w postaci:

https://abc123.ngrok-free.app

Wklej ten adres do ustawień webhooka GitHuba, a GitHub będzie mógł przesyłać zdarzenia bezpośrednio na laptopa. Za każdym razem, gdy otwiera się PR, żądanie przemieszcza się od serwerów GitHuba przez serwery ngrok do lokalnej aplikacji FastAPI. W terminalu cała wymiana pojawia się jako jedna linia:

23:03:02 POST /api/webhook    202 Accepted  ✅

Jedna linia pod drugą – GitHub jest zadowolony, podczas gdy prawdziwa praca rozpoczyna się w tle. Jedna uwaga: darmowa wersja ngrok wydaje nowy adres URL przy każdym restartowaniu, więc adres webhooka GitHuba musi być aktualizowany za każdym razem.

Krok 3: pipeline LangGraph

To jest serce systemu. LangGraph to framework do prac złożonych z wielu agentów o stanach pamięci. Agenci stają się węzłami w grafie, łączą je krawędzie, a pomiędzy nimi przepływa wspólny stan. Wyobraź sobie schemat przepływowy, w którym każda kwadratowa komórka to agent AI, a strzałki wskazują, jakie dane przemieszczają się dokąd i w jakiej kolejności.

Wspólny stan

Wszystkie agenty czytają i zapisują dane do jednego wspólnego obiektu stanu, który przechowuje numer PR oraz szczegóły repozytorium, pobrany rozbieżność z rzeczywistymi zmianami w kodzie, wyniki przeglądania każdego z agentów oraz ostateczny skompilowany komentarz. Informacje te przekazywane są w grafie jak sztafeta – każdy agent dodaje swój element, zanim go przekaże dalej.

Węzeł 0: pobieranie PR

Specjalny węzeł działa przed każdym agentem i wysyła zapytanie do API GitHuba w celu uzyskania tytułu PR, nazwiska autora i gałęzi oraz pełnej rozbieżności każdego zmienionego pliku. Wszystko to przekształca się w uporządkowany ciąg tekstu, który mogą odczytać modele językowe, a ta sama sformatowana rozbieżność jest przekazywana każdemu z recenzentów.

Równoległe rozprzestrzenianie: agenci 1, 2 i 3

Po pobraniu danych graf rozprzestrzenia się jednocześnie do trzech agentów. Otrzymują oni tę samą rozbieżność, działają w tym samym momencie i nie wiedzą nic o siebie nawzajem.

Agent ds. jakości kodu funkcjonuje wyłącznie we własnym świecie. Jego instrukcje systemowe obejmują czytelność, zasady nazywania, naruszenia zasady DRY, obsługę błędów oraz możliwość utrzymania kodu, a on zwraca ustrukturyzowany JSON z oceną od 0 do 10 oraz listą konkretnych problemów, z których każdy zawiera nazwę pliku, numer wiersza i zalecaną poprawkę.

Agent ds. bezpieczeństwa szuka wyłącznie słabości: iniekcji SQL spowodowanych nieprzefiltrowanymi danymi wejściowymi, haseł lub tokenów zapisanych w kodzie źródłowym, braku sprawdzeń autoryzacji oraz wrażliwych danych w dziennikach. Nie wie nic o wydajności ani stylu kodu.

Agent ds. wydajności myśli wyłącznie o efektywności: wzorcach zapytań do bazy danych typu N+1, pętlach nawzajem zawartych o złożoności O(n²) lub gorszej, blokujących wywołaniach IO wewnątrz funkcji asynchronicznych oraz braku indeksów lub możliwości cache’owania.

Paralelizm ma znaczenie dla czasu. Jeśli działają sekwencyjnie, wszystkie trzy agenty potrzebują łącznie od 60 do 90 sekund. Jeśli działają jednocześnie, kończą pracę w około 7 do 12 sekund – to czas najwolniejszego z agentów, a nie suma czasu wszystkich trzech.

Fan-in: agent 4

Ostateczny recenzent automatycznie czeka, aż wszyscy trzej specjaliści skończą pracę. LangGraph zajmuje się tą synchronizacją, więc nie trzeba pisać żadnej logiki czekania ani pytań. Gdy trzy raporty przychodzą w formie zstrukturyzowanego JSON, agent 4 wykonuje jedno zadanie – pisze ostateczny komentarz recenzji w formacie Markdown.

Agent 4 nie przeprowadza żadnej analizy. Nigdy ponownie nie sprawdza kodu, a jedynie łączy i formatuje to, co zgłosili specjaliści. Jest to celowe: nawet jeśli sformułowania są nieco niestabilne, wyniki pozostają dokładnie takie same jak te uzyskane przez specjalistów. Jego komentarz zaczyna się od ogólnej oceny i wyniku będącego średnią wyników trzech agentów, następnie podsumowuje to, co znalazł każdy agent, i kończy się listą „Must Fix Before Merge” zawierającą wyłącznie krytyczne i poważne problemy.

Pułapka w stanie równoległym

Nieznaczny szczegół techniczny łatwo przeoczyć. Gdy agenci równoległe zakończą pracę i zapiszą zmiany do wspólnego stanu, każdy z nich musi zwrócić tylko klucz, który posiada. Gdyby każdy agent miał zwracać cały obiekt stanu, LangGraph otrzymywałby jednocześnie trzy sprzeczne kopie każdego wspólnego pola i wywołał błąd InvalidUpdateError. Rozwiązanie jest proste, ale nieoczywiste: należy do pól, w które zapisują dane agenci równoległe, dodać reduktora typu Annotated i sprawić, by każdy agent zwracał tylko swój własny wynik. Dowiaduje się o tym dopiero w momencie napotkania błędu, a większość tutoriali dotyczących LangGraph w ogóle o tym nie wspomina.

Krok 4: wynik

Dowód znajduje się w teście. Plik w języku Python zawierający cztery celowo umieszczone problemy, sztywno zdefiniowaną tajemnicę, lukę podatną na SQL injection, pętlę nawiasową typu O(n²) oraz nieodpowiednie nazewnictwo został umieszczony na gałęzi i otwarty jako pull request. Recenzja pojawiła się 27 sekund później. Oto kod, który trafił do projektu:

import sqlite3

# Hardcoded secret — security agent should catch this
API_KEY = "sk-prod-supersecretkey123"

def get_user(user_id):
    conn = sqlite3.connect("users.db")
    # SQL injection — security agent should catch this
    query = f"SELECT * FROM users WHERE id = {user_id}"
    return conn.execute(query)

def process(users):
    # O(n²) nested loop — performance agent should catch this
    for user in users:
        for item in users:
            print(user, item)

# Bad naming — quality agent should catch this
def x(a, b, c):
    return a + b + c

I oto to, co system opublikował na PR:

## 🤖 AI Code Review

**Overall Verdict:** ❌ REJECTED
**Score:** 2.33/10

---

### 📋 Code Quality
Score: 2/10 | 8 Issues Found

Function naming is completely unclear — x, a, b, c give no
indication of purpose. No error handling on database operations.
No docstrings or type hints on any function.

### 🔒 Security
Score: 2/10 | 4 Critical Vulnerabilities

Hardcoded API key on line 3 exposes credentials in version
control — CRITICAL. SQL query on line 9 directly interpolates
user input, creating a SQL injection vulnerability — CRITICAL.

### ⚡ Performance
Score: 3/10 | 4 Issues Found

Nested loop in process() creates O(n²) complexity — will become
extremely slow as the users list grows. Database connection is
opened but never closed, creating a connection leak.

---

### 🚨 Must Fix Before Merge

- Remove API_KEY hardcoding — use environment variables instead
- Parameterize the SQL query to prevent injection attacks
- Refactor nested loop — use set operations or single pass
- Close database connections properly or use a context manager

---

Great effort on the overall structure! Addressing these critical
issues will significantly improve the security and reliability
of this code. Looking forward to the revised version. 🙌

W ciągu zaledwie 27 sekund od utworzenia prośby o przegląd znaleziono cztery konkretne kategorie problemów wraz z konkretnymi odniesieniami do linii kodu i sugestiami naprawczymi. Nie brał w tym udziału żaden człowiek, nie było konieczności oczekiwania – od razu otrzymano uporządkowane, praktyczne informacje zwrotne.

Ruch lokalny

Wszystko zaczyna się od jednego polecenia Docker: ustawiane są zmienne środowiskowe, tworzony jest token GitHuba i konfigurowany webhook, ngrok łączy lokalny serwer z GitHubem, a testowa prośba o przegląd pokazuje, jak natychmiast pojawiają się informacje zwrotne. Przełączanie między Claude a OpenAI wymaga zmiany tylko jednej zmiennej środowiskowej, a kroki konfiguracji są opisane w pliku README repozytorium.

Lekcje z procesu budowania

Agenci specjalistyczni radzą sobie lepiej niż agenci ogólni. Praca jednego agenta na zadanie daje bardziej precyzyjne i skoncentrowane wyniki, ponieważ agent bezpieczeństwa nie jest rozpraszany przez kwestie stylu kodu, a agent optymalizacji nie marnuje tokenów na nazwy zmiennych.

Kolejka zadań jest częścią architektury, a nie opcją. 10-sekundowy limit czasu oczekiwania w GitHub jest ścisły, a bez Redis oraz procesora w tle nieudane próby dostarczenia są ponawiane, co powoduje gromadzenie się duplikatów recenzji. Wiele tutoriali pomija ten aspekt, a jednak to on sprawia, że system jest niezawodny.

Wykonywanie zadań równolegle zmienia sytuację. Trzy sekwencyjne wywołania po 10 sekund każde wymagają co najmniej 30 sekund, podczas gdy trzy równoległe – tylko 10. LangGraph ułatwia implementację równoległości, a różnica jest znaczna.

Ustrukturyzowany wynik sprawia, że agenci nadają się do użycia w produkcji. Każdy agent zwraca dane zgodne ze ścisłym schematem JSON, a jeśli parsowanie się nie powiedzie, zadanie kończy się bezbłędnie i nic nie jest wysyłane do GitHub. System albo dostarcza dobrą recenzję, albo nic, ale nigdy śmieciowych danych.

Od samego początku abstrahuj LLM. Wzorzec fabryczny, który umożliwia przełączanie się między Claude a OpenAI za pomocą jednej zmiennej środowiskowej, wymaga około dziesięciu minut na stworzenie i oszczędza godziny pracy nad refaktoryzacją później, ponieważ modele można swobodnie testować i porównywać jakość ich oceny.

Jak to wpływa na przegląd kodu

Przegląd kodu nie zniknie, a przy podejmowaniu decyzji architektonicznych, logice biznesowej oraz delikatnych kompromisach projektowych nic nie zastąpi człowieka. Inna sprawa to pierwsza, mechaniczna analiza: hardkodowane sekrety, iniekcje SQL, pętle kwadratowe oraz niejasne nazwy można zautomatyzować, co uwalnia ludzkich recenzentów do pracy wymagającej ludzkiej inteligencji. Ten system wykrywa oczywiste problemy w ciągu około 30 sekund, dzięki czemu koledzy z zespołu mogą skupić się na tych najważniejszych.

Literatura pokrewna

  • Mapowanie ekosystemu AI w Laravel: Prism, LarAgent, Neuron AI i Boost — Od zwykłych wezwań do modeli LLM do pełnych agentów w Laravel: co robią Prism, LarAgent, Neuron AI, SDK AI oraz Boost, wraz z przykładem RAG do pytań dotyczących polityki HR.
  • Porównanie trybów strumieniowania w LangGraph: aktualizacje, wartości i astream_events — Przykład działającego LangGraph pokazuje, kiedy należy strumieniować aktualizacje węzłów, pełne zrzuty stanu lub wydarzenia na poziomie tokenów, a także przedstawia wzorzec stosowany w produkcji oraz częste błędy.
  • Python dla programisty JS: Agent do Gmail i kalendarza z FastAPI oraz LangGraph — Naucz się Pythona, tworząc osobistego asystenta do przechowywania tylko szkiców: FastAPI, Google OAuth dla Gmail i kalendarza, narzędzia LangGraph, lokalne modele Ollama oraz transmisja w czasie rzeczywistym SSE.
  • 10 frameworki agentów AI, które warto znać w 2026 roku: LangGraph, CrewAI i inne — Frameworki agentów uszeregowane według sposobu koordynacji agentów, wraz z zaletami i wadami, najlepszymi zastosowaniami oraz przewodnikiem decyzyjnym pomagającym wybrać odpowiedni dla twojego zespołu.
  • Twój pierwszy agent LangGraph: asystent do piłki nożnej z narzędziami i routowaniem — Krok po kroku: tutorial LangGraph obejmujący wspólny stan, narzędzia, węzeł planistyczny, warunkowe krawędzie oraz podsumowanie w formacie Markdown, stworzony wokół symulowanego asystenta do statystyk piłkarskich.
  • RAG w prostym Pythonie: dzielenie na fragmenty, TF-IDF, podobieństwo kosinowe i promptowanie — Budowa systemu generacji wzbogaconej o wyszukiwanie wyłącznie za pomocą modułu matematycznego: dzielenie na fragmenty metodą okna przesuwającego się, wektory TF-IDF, ranking kosinowy, skuteczne prompty i ich ograniczenia.
  • LLMOps dla agenta zadaniowego: MLflow Traces, Evals i brama CI — Stwórz asystenta zadaniowego PydanticAI przy użyciu FastAPI, śledź jego działanie za pomocą MLflow, oceniaj go za pomocą narzędzi GenAI oraz blokuj regresje w GitHub Actions, wszystko przy użyciu lokalnych modeli.
  • IntentFlow: Zarządzanie agentami LLM za pomocą skompilowanej polityki i śladów podlegających weryfikacji — Przegląd IntentFlow, eksperymentalnego języka, który egzekwuje politykę agenta poza modelem i tworzy ślady w formie łańcuchów haszów, które audytor może niezależnie zweryfikować.
  • Koncepcje LangGraph w prostym języku: stan, pamięć i orkiestracja — Przed pisaniem kodu: co oznaczają orkiestracja, czas wykonywania, agenci z pamięcią, pamięć krótko- i długoterminowa, systemy wieloagentowe oraz udział człowieka w LangGraph.
  • Tworzenie samokorygujących się agentów z użyciem LangGraph: pięć praktycznych wskazówek — Stwórz agenta do wyszukiwania w LangGraph, który próbuje ponownie po niepowodzeniu, z wyjaśnieniem takich elementów jak stan, krawędzie warunkowe, zapisy punktów kontrolnych, zatwierdzenie przez człowieka oraz małe węzły, przy użyciu gotowego kodu.
  • Budowanie agenta podtrzymywania LEPA za pomocą LangGraph — Wire SupportState, węzły do przyjmowania i klasyfikacji danych, krawędzie warunkowe oraz elementy START/END, aby prośba o pomoc szkolną mogła zostać wyjaśniona lub skierowana do odpowiednich dokumentów.
  • Bot do przeglądania pull requestów o otwartym kodzie źródłowym: LangGraph, Node.js i GitHub Webhooks — Przeglądanie pull requestów za pomocą agenta LangGraph, który sprawdza aspekty bezpieczeństwa, wydajności i architektury, a także publikuje komentarze na poziomie poszczególnych linii kodu poprzez API GitHuba.
  • Harness produkcyjny dla Claude Code: sześć warstw od Slack do połączonego kodu — Jak sześciowarstwowy harness przekształca zgłoszenia z Slack w połączony kod: przyjmowanie zdarzeń, pętle agentów z kontrolą dostępu, trwały stan, samoregeneracja, możliwość obserwacji oraz kontrola przez operatora.
  • Inżynieria pętli: cztery nawarstwione pętle dla samodoskonalących się agentów AI — Jak cztery nawarstwione pętle sterujące (ReAct, ponawianie prób, kolejka, wspinaczka po wzgórzach) wraz z mechanizmem oceny, licznikiem budżetu i kontrolą modyfikacji sprawiają, że agent jest niezawodny, przykładem jest to w procesie oceny ubezpieczeń.
  • Orchestracja wielu agentów w Bedrock i LangGraph: cztery wzorce — Wzorce supervisor-worker, pipeline, fan-out i debate z użyciem LangGraph w AWS Bedrock, a także mechanizmy przekazywania zadań, kontrolerów budżetu, śledzenia oraz sposoby radzenia sobie z awariami w produkcji.
  • Notatki praktyczne: Budowa nowoczesnego pipeline ISR dla modalności kodu w dużych systemach — Szczegółowy przewodnik po notatkach praktycznych dotyczących budowy nowoczesnego pipeline ISR dla modalności kodu w dużych systemach: umowy, sprawdzania oraz gotowe elementy kodu dostępne dla zespołów wdrażających ten wzorzec.
  • Biuro obsługi klienta z pięcioma agentami w Gemini 3.1 i ADK: triaż, badania, działanie, kontrola jakości oraz mechanizm koordynacji — Stworzenie systemu wsparcia klienta opartego na wielu agentach przy użyciu Google ADK i Gemini 3.1: przekazy zadaní poprzez wpisywanie tekstu, pętle korekty w ramach kontroli jakości, Agent Engine lub Cloud Run, sesje oraz koszty.
  • Projektowanie narzędzia do znajdowania pracy dla wielu agentów: pipeline, HyDE i możliwości obserwacji — Dziewięciostopniowy pipeline LangGraph służący do dopasowywania CV do ofert pracy, wraz z ośmioma opcjami projektowymi dotyczącymi HyDE, routingu modeli, ograniczeń szybkości i śledzenia procesów.
  • RAG z LangChain od zera: loaderzy, kawałki danych, embeddingi, ocena — Budowanie systemu Q&A dla dokumentów krok po kroku: ładowanie plików, dzielenie na fragmenty, embeddingi, fazy indeksowania i wyszukiwania oraz sposoby oceny wyników wyszukiwania i odpowiedzi.
  • Budowanie systemu badawczego multi-agent z LangChain Deep Agents — Praktyczny przegląd wzorca Deep Agents: orkiestrator, agenci specjalistyczne, bezpieczne narzędzia oraz interfejs Streamlit, przetestowane z lokalnymi i chmurowymi modelami językowymi.
  • Jeden agent z dobrym kontekstem pokonuje rój: dlaczego przekazy niszczą kod wielu agentów — Dlaczego łączenie agentów pomnaża błędy, jak przekazy tracą stan, kiedy agenci równolegli faktycznie pomagają oraz prosta zasada: rozproszyć czytanie, seryjalizować zapisywanie i najpierw naprawić kontekst.