Skip to content
Zurück zum Blog
Fallstudie

Bauen Sie einen AI PR Reviewer mit 3 parallelen Subagenten in Python

Kacper Wlodarczyk · · 10 Min. Lesezeit
Verfügbar in: English · Español · Polski
Inhaltsverzeichnis

Code Reviews sind eine der wertvollsten — und teuersten — Aktivitaeten in der Softwareentwicklung.

Ein Senior-Entwickler verbringt 2-4 Stunden pro Tag mit der Ueberpruefung von Pull Requests. Das sind 10-20 Stunden pro Woche. Kein Code schreiben. Keine Systeme entwerfen. Kein Mentoring. Nur Diffs lesen, auf SQL Injection pruefen, N+1-Queries entdecken und Kommentare ueber fehlende Type Hints hinterlassen.

Multiplizieren Sie das mit einem Team von fuenf Seniors. Das sind 50-100 Stunden menschlicher Gehirnleistung pro Woche, ein Grossteil davon fuer Pruefungen, die klaren, wiederholbaren Mustern folgen.

Was waere, wenn Sie die wiederholbaren Teile automatisieren koennten? Nicht den Senior-Reviewer ersetzen — ihn unterstuetzen. Die offensichtlichen Probleme abfangen, bevor er sich den PR ueberhaupt ansieht, damit er sich auf Architektur, Logik und Design konzentrieren kann.

Genau das haben wir gebaut. Einen AI PR Reviewer, der drei spezialisierte Subagenten parallel ausfuehrt — Sicherheit, Stil und Performance — und ein strukturiertes, nach Prioritaet sortiertes Review in etwa 30 Sekunden liefert.

So funktioniert es, und hier ist der vollstaendige, funktionierende Code, den Sie heute ausfuehren koennen.

Die Architektur: 3 Spezialisten, 1 Koordinator

Die Kernidee ist einfach: Anstatt eines monolithischen “pruefe diesen Code”-Prompts teilen wir das Review in drei Domaenen auf, die jeweils von einem spezialisierten Subagenten behandelt werden.

Security Reviewer — prueft auf:

  • SQL-Injection-Schwachstellen
  • Cross-Site Scripting (XSS)
  • Hardcodierte Secrets und API-Keys
  • Unsichere Deserialisierung
  • Command Injection
  • Unsichere Dateioperationen

Style Reviewer — prueft auf:

  • Verletzte Namenskonventionen
  • Code-Duplikation
  • Uebermassige zyklomatische Komplexitaet
  • Fehlende Type Hints
  • Docstring-Abdeckung
  • Toter Code und ungenutzte Imports

Performance Reviewer — prueft auf:

  • N+1-Query-Muster
  • Unnoetige Speicherallokationen
  • Blockierendes I/O in Async-Kontexten
  • Fehlende Datenbankindizes
  • Caching-Moeglichkeiten
  • Unoptimierte Schleifen und Datenstrukturen

Jeder Subagent erhaelt denselben Git-Diff, prueft ihn durch seine spezialisierte Linse und gibt strukturierte Ergebnisse zurueck. Ein uebergeordneter Agent koordiniert sie — sendet alle drei parallel los und aggregiert dann die Ergebnisse in ein einheitliches Review, sortiert nach Schweregrad.

Das ist das Deep-Agent-Muster: ein Koordinator, der plant, an Spezialisten delegiert und Ergebnisse synthetisiert. Es ist dieselbe Architektur, die von Claude Code, Codex und anderen produktionsreifen Coding-Agenten verwendet wird — aber Open-Source und auf Pydantic AI aufgebaut.

Der Code: ~40 Zeilen, voll funktionsfaehig

Hier ist die komplette Implementierung mit pydantic-deepagents:

import asyncio
from pydantic import BaseModel
from pydantic_deep import create_deep_agent, DeepAgentDeps, LocalBackend
from pydantic_deep.types import SubAgentConfig
class ReviewFinding(BaseModel):
"""A single finding from the code review."""
file: str
line: int
severity: str # critical, warning, info
category: str # security, style, performance
description: str
suggestion: str
# --- Define 3 specialist subagents ---
security_agent = SubAgentConfig(
name="security-reviewer",
description="Reviews code for security vulnerabilities",
instructions=(
"You are a security-focused code reviewer. "
"Check for: SQL injection, XSS, hardcoded secrets, "
"unsafe deserialization, command injection, insecure file ops. "
"Return structured findings with file path, line number, "
"severity (critical/warning/info), and a concrete fix suggestion."
),
)
style_agent = SubAgentConfig(
name="style-reviewer",
description="Reviews code style and conventions",
instructions=(
"You are a code style reviewer. "
"Check for: naming convention violations, code duplication, "
"excessive complexity, missing type hints, missing docstrings, "
"dead code, unused imports. "
"Return structured findings with file path, line number, "
"severity, and a concrete improvement suggestion."
),
)
perf_agent = SubAgentConfig(
name="performance-reviewer",
description="Reviews code for performance issues",
instructions=(
"You are a performance-focused code reviewer. "
"Check for: N+1 queries, unnecessary allocations, "
"blocking I/O in async code, missing indexes, cache opportunities, "
"unoptimized loops. "
"Return structured findings with file path, line number, "
"severity, and a concrete optimization suggestion."
),
)
# --- Create the coordinator agent ---
agent = create_deep_agent(
"claude-sonnet-4-5",
instructions=(
"You are a senior code reviewer. "
"Delegate to your 3 specialist subagents in parallel, "
"then aggregate their findings into a unified review "
"sorted by severity (critical first). "
"Remove duplicates and add an overall summary."
),
subagents=[security_agent, style_agent, perf_agent],
)
# --- Run the review ---
async def main():
deps = DeepAgentDeps(backend=LocalBackend(root_dir="."))
result = await agent.run(
"Review the current git diff and provide a comprehensive code review. "
"Focus on security vulnerabilities, style issues, and performance problems.",
deps=deps,
)
print(result.output)
if __name__ == "__main__":
asyncio.run(main())

Das ist alles. Unter 40 Zeilen eigentlicher Logik. Schauen wir uns an, was passiert.

Wie es funktioniert, Schritt fuer Schritt

1. Strukturierte Ausgabe mit Pydantic

Das ReviewFinding-Modell definiert genau, wie jedes Ergebnis aussieht. Dateipfad, Zeilennummer, Schweregrad, Kategorie, Beschreibung und ein konkreter Vorschlag. Kein Freitext. Kein “vielleicht sollten Sie erwaegen…”. Strukturierte, parsebare, umsetzbare Daten.

Das ist einer der Vorteile des Aufbauens auf Pydantic AI — die Ausgabe des Modells wird zur Laufzeit validiert. Wenn das LLM ein Ergebnis ohne Schweregrad zurueckgibt, wird es sofort erkannt.

2. Drei SubAgentConfigs

Jeder SubAgentConfig definiert einen Spezialisten:

  • name — eindeutiger Bezeichner, den der uebergeordnete Agent zum Delegieren verwendet
  • description — sagt dem uebergeordneten Agenten, wann dieser Subagent eingesetzt werden soll (die Routing-Logik)
  • instructions — der System-Prompt fuer den Subagenten, fokussiert auf seine Domaene

Die Anweisungen sind spezifisch. Wir sagen nicht “pruefe diesen Code”. Wir sagen “pruefe auf SQL Injection, XSS, hardcodierte Secrets…” Diese Spezifitaet macht die Reviews tatsaechlich nuetzlich. Jeder Subagent ist ein Experte in seiner Domaene, kein Generalist, der versucht, alles abzudecken.

3. Parallele Ausfuehrung ueber Subagenten

Wenn Sie subagents=[security_agent, style_agent, perf_agent] an create_deep_agent() uebergeben, erhaelt der uebergeordnete Agent Tools, um Aufgaben an jeden Subagenten zu delegieren. Der uebergeordnete Agent entscheidet, wie er sie orchestriert — und weil die Anweisungen “parallel delegieren” sagen, laufen alle drei gleichzeitig.

Das unterscheidet sich grundlegend von sequentiellen Ketten. Anstatt zu warten, bis das Sicherheits-Review fertig ist, bevor das Stil-Review beginnt, laufen alle drei gleichzeitig. Deshalb erhalten Sie Ergebnisse in ~30 Sekunden statt ~90 Sekunden.

4. LocalBackend fuer Dateizugriff

LocalBackend(root_dir=".") gibt dem Agenten (und seinen Subagenten) Lesezugriff auf Ihr lokales Dateisystem. Die Subagenten koennen den Git-Diff lesen, bestimmte Dateien fuer Kontext inspizieren und die Codebase-Struktur verstehen.

Wenn Sie stattdessen sandboxed Ausfuehrung wollen, tauschen Sie LocalBackend gegen StateBackend() (im Speicher) oder DockerSandbox() (containerisiert). Der Agent-Code bleibt gleich — nur das Backend aendert sich.

5. Aggregation durch den uebergeordneten Agenten

Die Anweisungen des uebergeordneten Agenten sagen ihm, dass er aggregieren, deduplizieren und nach Schweregrad sortieren soll. Wenn also der Security-Reviewer und der Style-Reviewer dieselbe Zeile markieren (z.B. ein hardcodierter API-Key ist sowohl ein Sicherheits- als auch ein Stilproblem), fuegt der uebergeordnete Agent sie zu einem einzelnen Ergebnis mit dem hoechsten Schweregrad zusammen.

Die Ausgabe ist ein sauberes, priorisiertes Review — kritische Probleme zuerst, Warnungen als naechstes, informative Hinweise zuletzt.

Wie die Ausgabe aussieht

Hier ist ein Beispiel dessen, was der Reviewer bei einem echten PR produziert:

## Code Review Summary
**Files reviewed:** 4
**Total findings:** 7 (2 critical, 3 warning, 2 info)
### Critical
1. **[SECURITY]** `api/auth.py:42` — SQL query built with f-string interpolation.
Vulnerable to SQL injection.
→ Use parameterized queries: `cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))`
2. **[SECURITY]** `config.py:15` — AWS secret key hardcoded in source.
→ Move to environment variable: `os.environ["AWS_SECRET_KEY"]`
### Warning
3. **[PERFORMANCE]** `api/users.py:78` — Querying user.posts inside a loop (N+1 pattern).
→ Use `selectinload(User.posts)` in the initial query.
4. **[STYLE]** `api/users.py:23-45` — Function `process_user_data` is 67 lines with 8 branches.
Cyclomatic complexity too high.
→ Extract validation logic into separate function.
5. **[PERFORMANCE]** `api/export.py:31` — Building CSV by string concatenation in loop.
→ Use `io.StringIO` or `csv.writer` for O(n) instead of O(n^2).
### Info
6. **[STYLE]** `models/user.py:12` — Missing type hints on `calculate_score` parameters.
→ Add: `def calculate_score(self, weights: list[float], threshold: float = 0.5) -> float:`
7. **[STYLE]** `api/auth.py:1-5` — `import os, sys, json` — unused imports `sys` and `json`.
→ Remove unused imports.

Jedes Ergebnis hat eine Datei, eine Zeilennummer, eine Kategorie und einen konkreten Fix. Ein Senior-Reviewer kann das in 30 Sekunden durchscannen und entscheiden, welche Ergebnisse er akzeptiert, welche er aendert und welche er verwirft.

Ausfuehrung: Als Skript oder Slash-Command

Eigenstaendiges Skript

Speichern Sie den obigen Code als review.py und fuehren Sie aus:

Terminal window
pip install pydantic-deep
python review.py

Der Agent liest das aktuelle Verzeichnis, holt den Git-Diff und gibt das Review aus.

Als pydantic-deep Slash-Command

Wenn Sie pydantic-deepagents als CLI verwenden (wie Claude Code), koennen Sie dies als Slash-Command registrieren:

Terminal window
# Fuehren Sie den eingebauten Review-Befehl aus
pydantic-deep review

In CI/CD (GitHub Actions)

- name: AI Code Review
run: |
pip install pydantic-deep
python review.py > review.md
- name: Post Review Comment
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const review = fs.readFileSync('review.md', 'utf8');
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: review
});

Jetzt bekommt jeder PR automatisch ein AI-Review, bevor ein Mensch ihn sich ueberhaupt ansieht.

Warum 3 Subagenten statt 1 Prompt?

Sie fragen sich vielleicht: Warum nicht einem Agenten einfach einen einzelnen Prompt geben, der sagt “pruefe diesen Code auf Sicherheit, Stil und Performance”?

Drei Gruende:

1. Spezialisierung schlaegt Generalisierung. Wenn Sie ein LLM bitten, alles zu tun, neigt es dazu, breit und oberflaechlich zu sein. Ein sicherheitsfokussierter Prompt mit spezifischen Schwachstellenmustern produziert gruendlichere Ergebnisse als ein generischer “pruefe diesen Code”-Prompt.

2. Parallele Ausfuehrung. Drei Subagenten laufen gleichzeitig. Ein Agent, der drei Durchlaeufe macht, laeuft sequentiell. Im Massstab ist das der Unterschied zwischen 30-Sekunden-Reviews und 2-Minuten-Reviews.

3. Unabhaengige Skalierung. Wollen Sie einen vierten Subagenten fuer Barrierefreiheitspruefungen hinzufuegen? Oder einen fuenften fuer API-Vertragsvalidierung? Fuegen Sie einfach einen weiteren SubAgentConfig hinzu. Der uebergeordnete Agent uebernimmt die Koordination automatisch. Sie koennen auch Modelle pro Subagent tauschen — ein schnelleres Modell fuer Stilpruefungen und ein leistungsfaehigeres fuer Sicherheitsanalysen.

Das groessere Bild: Deep Agent Muster

Dieser PR Reviewer ist ein Beispiel fuer das Deep Agent Muster — dieselbe Architektur, die Claude Code, OpenAI Codex und Cursor im Hintergrund antreibt.

Das Muster:

  1. Planen — eine komplexe Aufgabe in Teilaufgaben zerlegen
  2. Delegieren — Teilaufgaben an Spezialisten (Subagenten) senden
  3. Ausfuehren — jeder Spezialist arbeitet unabhaengig mit seinen eigenen Tools
  4. Synthetisieren — der uebergeordnete Agent aggregiert Ergebnisse zu einer kohaerenten Ausgabe

pydantic-deepagents ist eine Open-Source-Implementierung dieses Musters, gebaut auf Pydantic AI. Es ist das Framework, das wir bei Vstorm verwenden, um produktionsreife AI-Agenten zu deployen — und der PR Reviewer ist eines der einfachsten Dinge, die Sie damit bauen koennen.

Probieren Sie es aus

Der PR-Reviewer-Code aus diesem Artikel befindet sich im examples/-Verzeichnis. Klonen Sie es, richten Sie es auf Ihr Repo und sehen Sie, was es findet.

Wenn Sie bereits manuell Code Reviews durchfuehren, versuchen Sie, dies eine Woche lang neben Ihrem bestehenden Prozess laufen zu lassen. Vergleichen Sie die Ergebnisse. Sie koennten ueberrascht sein, wie viele Probleme die KI erkennt, die Menschen uebersehen — besonders die langweiligen, musterbasierte wie N+1-Queries und fehlende Type Hints.

Die Menschen in Ihrem Team sollten Architektur, Logik und Design ueberpruefen. Lassen Sie die Subagenten die Checkliste abarbeiten.


Ich bin Kacper, AI Engineer bei Vstorm — einer Applied Agentic AI Engineering Consultancy. Wir bauen und veroeffentlichen produktionsreife AI-Agent-Tools in Python als Open Source. Geben Sie pydantic-deepagents einen Stern auf GitHub, wenn Sie es nuetzlich finden.

Artikel teilen

Verwandte Artikel

Bereit, deine KI-App zu shippen?

Wähle deine Frameworks, generiere ein produktionsreifes Projekt und deploye. 75+ Optionen, ein Befehl, null Config-Schulden.

Brauchen Sie Hilfe beim Aufbau von KI-Agenten?