Automated code review is one of the most practical applications of AI in software development. In this guide, you’ll learn how to build an AI-powered code review agent using LangChain4j and Spring Boot that integrates with GitHub to automatically review pull requests.

Why Build an AI Code Review Agent?

Manual code reviews are time-consuming and inconsistent. Studies show that developers spend up to 6 hours per week on code reviews. An AI agent can:

Architecture Overview

1
2
3
4
5
GitHub Webhook → Spring Boot API → LangChain4j Agent → LLM (GPT-4 / Claude)
                              Structured Analysis
                              GitHub PR Comment

The agent receives a GitHub webhook when a pull request is opened or updated, analyzes the diff using an LLM, and posts review comments back to the PR.

Prerequisites

Step 1: Project Setup

Create a new Spring Boot project and add the LangChain4j dependency:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
    <version>0.36.2</version>
</dependency>
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j</artifactId>
    <version>0.36.2</version>
</dependency>

Step 2: Configure the AI Service

LangChain4j’s @AiService annotation makes it incredibly simple to define an AI-powered interface:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@AiService
public interface CodeReviewService {

    @SystemMessage("""
        You are an expert Java code reviewer. Analyze the provided code diff and:
        1. Identify bugs, security vulnerabilities, and performance issues
        2. Check for proper error handling
        3. Verify thread safety
        4. Suggest improvements with specific code examples
        5. Rate severity: CRITICAL, WARNING, or SUGGESTION
        
        Be specific. Reference exact line numbers and provide fix suggestions.
        """)
    String reviewPullRequest(
        @UserMessage String diffContent,
        @UserMessage String context
    );
}

Step 3: GitHub Integration

Use the GitHub API to fetch pull request diffs:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@Service
public class GitHubService {

    private final GitHubClient gitHubClient;
    
    public PullRequestDiff getDiff(String repoOwner, String repoName, long prNumber) {
        String url = "/repos/%s/%s/pulls/%d".formatted(repoOwner, repoName, prNumber);
        return gitHubClient.get(url, PullRequestDiff.class);
    }
    
    public void postReviewComment(String repoOwner, String repoName, 
                                   long prNumber, String comment) {
        String url = "/repos/%s/%s/pulls/%d/comments".formatted(
            repoOwner, repoName, prNumber);
        gitHubClient.post(url, new CommentRequest(comment));
    }
}

Step 4: Build the Webhook Endpoint

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@RestController
@RequestMapping("/api/webhooks/github")
public class GitHubWebhookController {

    private final CodeReviewService reviewService;
    private final GitHubService gitHubService;
    
    @PostMapping
    public ResponseEntity<Void> handleWebhook(
            @RequestBody GitHubWebhookEvent event,
            @RequestHeader("X-GitHub-Event") String eventType) {
        
        if (!"pull_request".equals(eventType)) {
            return ResponseEntity.ok().build();
        }
        
        if (!"opened".equals(event.getAction()) && 
            !"synchronize".equals(event.getAction())) {
            return ResponseEntity.ok().build();
        }
        
        // Fetch the diff
        PullRequestDiff diff = gitHubService.getDiff(
            event.getRepo().getOwner(), 
            event.getRepo().getName(),
            event.getPullRequest().getNumber()
        );
        
        // Run AI review
        String review = reviewService.reviewPullRequest(
            diff.getContent(),
            buildContext(event)
        );
        
        // Post comments back
        gitHubService.postReviewComment(
            event.getRepo().getOwner(),
            event.getRepo().getName(),
            event.getPullRequest().getNumber(),
            review
        );
        
        return ResponseEntity.ok().build();
    }
}

Step 5: Java-Specific Review Rules

For Java projects, enhance the system prompt with specific rules:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@SystemMessage("""
    You are reviewing Java/Spring Boot code. Pay special attention to:
    
    Security:
    - SQL injection (especially MyBatis ${} vs #{})
    - Improper input validation
    - Sensitive data exposure in logs
    
    Spring Boot:
    - Missing @Transactional on write operations
    - Incorrect transaction propagation
    - Bean scope issues (singleton vs prototype)
    - Missing @Valid on request DTOs
    
    Concurrency:
    - Race conditions in synchronized blocks
    - Improper use of CompletableFuture
    - Thread pool configuration issues
    
    Performance:
    - N+1 query problems (Hibernate/MyBatis)
    - Missing pagination
    - Inefficient collection operations
    - Memory leaks (unclosed resources)
    """)

Step 6: Rate Limiting and Cost Control

LLM API calls can get expensive. Implement rate limiting:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@Configuration
public class RateLimitConfig {
    
    @Bean
    public Bucket reviewBucket() {
        return Bucket.builder()
            .addLimit(Bandwidth.classic(50, Refill.intervally(50, 
                Duration.ofHours(1))))
            .build();
    }
}

// In your service
public Optional<String> reviewWithLimit(String diff) {
    if (reviewBucket.tryConsume(1)) {
        return Optional.of(reviewService.reviewPullRequest(diff, ""));
    }
    return Optional.empty();
}

Deployment

Deploy as a Spring Boot application. For GitHub integration, use ngrok for local testing or deploy to a cloud platform.

Key configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
langchain4j:
  open-ai:
    chat-model:
      model-name: gpt-4o
      temperature: 0.1
      timeout: 60s

github:
  webhook-secret: ${GITHUB_WEBHOOK_SECRET}
  token: ${GITHUB_TOKEN}

Results and Next Steps

After deploying, expect the agent to catch common issues like:

Next improvements:

Conclusion

Building an AI code review agent with LangChain4j takes surprisingly few lines of code. The combination of LangChain4j’s @AiService and Spring Boot’s dependency injection makes it easy to create production-ready AI tools.

The full source code is available on GitHub.

Have questions? Leave a comment below or reach out on Twitter @javadevai.

langchain4j spring-boot code-review ai-agent java