Pydantic review model

Typed models are the spine of the service. They give every layer a contract. The MCP tool hands a PRDiff to the review engine, the engine returns a ReviewResult, and the GitHub client accepts a list of ReviewComment objects. If any layer sends the wrong shape, Pydantic catches it before the call goes over the wire.

models.py
python
from pydantic import BaseModel, Field
from typing import List, Literal, Optional


class PRDiff(BaseModel):
    """Raw pull request diff plus identifying metadata."""
    owner: str
    repo: str
    pr_number: int
    title: Optional[str] = None
    diff: str = Field(..., description="Unified diff text for the PR")
    changed_files: List[str] = Field(default_factory=list)


class ReviewComment(BaseModel):
    file: str = Field(..., description="Path to the file being commented on")
    line: int = Field(..., description="Line number in the new version of the file")
    severity: Literal["info", "warning", "critical"] = "info"
    suggestion: str = Field(..., description="Actionable suggestion for the author")


class ReviewResult(BaseModel):
    """Full review output: a summary plus structured line comments."""
    owner: str
    repo: str
    pr_number: int
    summary: str
    comments: List[ReviewComment] = Field(default_factory=list)

Three models carry the whole workflow. PRDiff is what the GitHub client produces. ReviewComment is what the LLM produces. ReviewResult wraps everything together. Field descriptions double as documentation for MCP clients.

review_engine.py
python
from pydantic import ValidationError

comments: list[ReviewComment] = []
for raw_comment in parsed.get("comments", []):
    try:
        comments.append(ReviewComment(**raw_comment))
    except ValidationError as exc:
        logger.warning(
            "Skipping malformed comment %s: %s", raw_comment, exc
        )

Parsing is defensive. Each comment is validated individually. A malformed entry (missing line, invalid severity) is logged and dropped, but the rest of the review still ships. One bad comment never kills the full review.

Quiz: Quiz

Loading practice…