COOKBOOK:_CODE_REVIEW_AGENT
Build an AI-powered code reviewer that catches bugs, security issues, and style problems before they reach production.
The Problem#
Code reviews are essential but time-consuming. Junior developers need guidance, and even senior developers miss issues. An AI reviewer can:
- Catch security vulnerabilities and common bugs
- Enforce coding standards and best practices
- Provide instant feedback during development
- Scale review capacity without additional headcount
- Learn from your team's preferences and patterns
Architecture Overview#
Static Analysis
Parse code for security issues, bugs, and anti-patterns using AST analysis
Style Checking
Ensure consistent formatting, naming conventions, and code organization
Review Synthesis
Generate comprehensive feedback with actionable suggestions and severity levels
1
CREATE_CODE_ANALYSIS_TOOLS
tools/code-analysis.ts
import { Agent } from '@akios/core'
import { z } from 'zod'
// Tool for analyzing code
const analyzeCode = new Tool({
name: 'analyze_code',
description: 'Analyze code for bugs, security issues, and best practices',
schema: z.object({
code: z.string(),
language: z.string(),
context: z.string().optional()
}),
handler: async ({ code, language, context }) => {
// In practice, this would call a code analysis service
const issues = []
// Basic checks
if (code.includes('eval(')) {
issues.push({
type: 'security',
severity: 'high',
message: 'Use of eval() is dangerous and should be avoided'
})
}
if (code.includes('console.log') && !code.includes('// DEBUG')) {
issues.push({
type: 'best_practice',
severity: 'low',
message: 'Remove console.log statements before production'
})
}
return JSON.stringify({ issues, suggestions: [] })
}
})
// Tool for checking code style
const checkStyle = new Tool({
name: 'check_style',
description: 'Check code style and formatting consistency',
schema: z.object({
code: z.string(),
language: z.string()
}),
handler: async ({ code, language }) => {
const styleIssues = []
// Check indentation
const lines = code.split('\n')
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
const leadingSpaces = line.length - line.trimStart().length
if (leadingSpaces % 2 !== 0) {
styleIssues.push({
line: i + 1,
message: 'Inconsistent indentation (use 2 spaces)'
})
}
}
return JSON.stringify({ styleIssues })
}
})
// Tool for generating review comments
const generateReview = new Tool({
name: 'generate_review',
description: 'Generate a comprehensive code review with actionable feedback',
schema: z.object({
code: z.string(),
analysis: z.string(),
style_check: z.string(),
language: z.string()
}),
handler: async ({ code, analysis, style_check, language }) => {
const analysisData = JSON.parse(analysis)
const styleData = JSON.parse(style_check)
let review = '# Code Review\n\n'
// Security issues
const securityIssues = analysisData.issues.filter(i => i.type === 'security')
if (securityIssues.length > 0) {
review += '## 🚨 Security Issues\n'
securityIssues.forEach(issue => {
review += `- **${issue.severity.toUpperCase()}**: ${issue.message}\n`
})
review += '\n'
}
// Code quality issues
const qualityIssues = analysisData.issues.filter(i => i.type !== 'security')
if (qualityIssues.length > 0) {
review += '## 🔍 Code Quality\n'
qualityIssues.forEach(issue => {
review += `- ${issue.message}\n`
})
review += '\n'
}
// Style issues
if (styleData.styleIssues.length > 0) {
review += '## 💅 Style Issues\n'
styleData.styleIssues.forEach(issue => {
review += `- Line ${issue.line}: ${issue.message}\n`
})
review += '\n'
}
// Overall assessment
const hasHighSeverity = [...securityIssues, ...qualityIssues]
.some(i => i.severity === 'high')
if (hasHighSeverity) {
review += '## 📋 Overall Assessment\n'
review += '❌ **Requires changes** before merging.\n'
} else {
review += '## 📋 Overall Assessment\n'
review += '✅ **Approved** with suggestions.\n'
}
return review
}
})2
BUILD_THE_CODE_REVIEW_AGENT
code-review-agent.ts
import { Agent } from '@akios/core'
const codeReviewAgent = new Agent({
name: 'CodeReviewAgent',
model: 'gpt-4',
systemPrompt: `You are an expert code reviewer. Your job is to:
1. Analyze code for bugs, security vulnerabilities, and performance issues
2. Check code style and consistency
3. Provide actionable feedback
4. Be constructive and helpful
5. Focus on important issues first
Guidelines:
- Prioritize security > correctness > performance > style
- Be specific about problems and suggest solutions
- Explain why something is an issue
- Don't nitpick minor style issues unless they affect readability
- End with an overall assessment of merge readiness`,
tools: [analyzeCode, checkStyle, generateReview]
})
// Example usage
async function reviewPullRequest(code: string, language: string) {
// Step 1: Analyze code
const analysisResult = await analyzeCode.execute({
code,
language,
context: 'pull_request_review'
})
// Step 2: Check style
const styleResult = await checkStyle.execute({
code,
language
})
// Step 3: Generate comprehensive review
const review = await generateReview.execute({
code,
analysis: analysisResult,
style_check: styleResult,
language
})
return review
}
// Or use the agent directly
async function agentReview(code: string, language: string) {
const prompt = `Please review this ${language} code:
```${language}
${code}
```
Provide a comprehensive code review focusing on:
- Security vulnerabilities
- Code quality and potential bugs
- Performance issues
- Style and readability
- Best practices
Be specific about issues and suggest improvements.`
const result = await codeReviewAgent.run(prompt)
return response.text
}`3
INTEGRATE_WITH_GITHUB_GITLAB
github-integration.ts
import { createNodeMiddleware, createProbot } from 'probot'
const probot = createProbot()
probot.on('pull_request.opened', async (context) => {
const pr = context.payload.pull_request
const files = await context.octokit.pulls.listFiles({
owner: pr.base.repo.owner.login,
repo: pr.base.repo.name,
pull_number: pr.number
})
// Get changed files
const changedFiles = files.data.filter(f =>
f.status === 'added' || f.status === 'modified'
)
// Review each file
for (const file of changedFiles) {
if (file.filename.endsWith('.js') || file.filename.endsWith('.ts')) {
const content = await context.octokit.repos.getContent({
owner: pr.base.repo.owner.login,
repo: pr.base.repo.name,
path: file.filename,
ref: pr.head.sha
})
const code = Buffer.from(content.data.content, 'base64').toString()
const language = file.filename.endsWith('.ts') ? 'typescript' : 'javascript'
const review = await agentReview(code, language)
// Post review comment
await context.octokit.pulls.createReview({
owner: pr.base.repo.owner.login,
repo: pr.base.repo.name,
pull_number: pr.number,
body: `## AI Code Review for ${file.filename}\n\n${review}`,
event: 'COMMENT'
})
}
}
})
export default createNodeMiddleware(probot)Advanced Features#
Learning From Team Feedback
learning-reviews.ts
class LearningCodeReviewer extends Agent {
private teamPreferences: Map<string, { approved: number, rejected: number }> = new Map()
async reviewWithLearning(code: string, language: string) {
const review = await this.run(`Review this code: ${code}`)
// After human reviewer provides feedback, learn from it
this.learnFromFeedback(review.output, humanFeedback)
return review
}
private learnFromFeedback(aiReview: string, humanFeedback: string) {
// Parse human feedback to understand what was accepted/rejected
const acceptedSuggestions = this.extractAcceptedSuggestions(humanFeedback)
const rejectedSuggestions = this.extractRejectedSuggestions(humanFeedback)
acceptedSuggestions.forEach(suggestion => {
const key = this.categorizeSuggestion(suggestion)
const current = this.teamPreferences.get(key) || { approved: 0, rejected: 0 }
this.teamPreferences.set(key, { ...current, approved: current.approved + 1 })
})
rejectedSuggestions.forEach(suggestion => {
const key = this.categorizeSuggestion(suggestion)
const current = this.teamPreferences.get(key) || { approved: 0, rejected: 0 }
this.teamPreferences.set(key, { ...current, rejected: current.rejected + 1 })
})
}
private categorizeSuggestion(suggestion: string): string {
if (suggestion.includes('security') || suggestion.includes('vulnerability')) {
return 'security'
}
if (suggestion.includes('style') || suggestion.includes('format')) {
return 'style'
}
if (suggestion.includes('performance') || suggestion.includes('efficiency')) {
return 'performance'
}
return 'other'
}
}
// Usage
const learningReviewer = new LearningCodeReviewer({
name: 'LearningCodeReviewer',
model: 'gpt-4',
tools: [analyzeCode, checkStyle, generateReview]
})Real Time Ide Integration
vscode-extension.ts
import * as vscode from 'vscode'
export function activate(context: vscode.ExtensionContext) {
// Register code review command
const reviewCommand = vscode.commands.registerCommand('akiou.reviewCode', async () => {
const editor = vscode.window.activeTextEditor
if (!editor) return
const code = editor.document.getText()
const language = editor.document.languageId
// Show progress
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: 'AI Code Review in progress...',
cancellable: false
}, async (progress) => {
const review = await agentReview(code, language)
// Show results in new document
const doc = await vscode.workspace.openTextDocument({
content: review,
language: 'markdown'
})
await vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)
})
})
// Register on-save review
const onSave = vscode.workspace.onDidSaveTextDocument(async (document) => {
const config = vscode.workspace.getConfiguration('akiou')
if (!config.get('reviewOnSave')) return
if (document.languageId === 'typescript' || document.languageId === 'javascript') {
const code = document.getText()
const diagnostics = await quickReview(code, document.languageId)
// Show diagnostics in problems panel
const diagnosticCollection = vscode.languages.createDiagnosticCollection('akiou')
diagnosticCollection.set(document.uri, diagnostics)
}
})
context.subscriptions.push(reviewCommand, onSave)
}
async function quickReview(code: string, language: string) {
const issues = await analyzeCode.execute({ code, language })
const parsed = JSON.parse(issues)
return parsed.issues.map(issue => {
const severity = issue.severity === 'high' ? vscode.DiagnosticSeverity.Error :
issue.severity === 'medium' ? vscode.DiagnosticSeverity.Warning :
vscode.DiagnosticSeverity.Information
return new vscode.Diagnostic(
new vscode.Range(0, 0, 0, 0), // Would need line parsing for accuracy
issue.message,
severity
)
})
}Testing your Code Review Agent#
To verify your agent works, run it against a sample code snippet with known issues.
typescript
const badCode = `
function calculateTotal(items) {
let total = 0;
// Bug: i <= items.length will cause index out of bounds
for (let i = 0; i <= items.length; i++) {
total += items[i].price;
}
return total;
}
`;
const result = await reviewAgent.run(badCode);
console.log(result);Best Practices
- START_WITH_SECURITY: Always check for vulnerabilities first
- BE_SPECIFIC: Point to exact lines and suggest concrete fixes
- LEARN_FROM_YOUR_TEAM: Incorporate human reviewer preferences
- DONT_REPLACE_HUMANS: Use AI as a first pass, not final authority
- CONTEXT_MATTERS: Consider the codebase, team norms, and project constraints