How to Build a Custom AI Code Review Agent: A Step-by-Step Tutorial with ECOA AI Platform ACP

1 comment
(Developer Tutorials) - Stop wasting hours on manual PR reviews. In this tutorial, I'll show you how to build a custom AI code review agent using the ECOA AI Platform ACP that catches bugs, enforces style, and comments on pull requests automatically.

How to Build a Custom AI Code Review Agent: A Step-by-Step Tutorial with ECOA AI Platform ACP

Let’s be real. Manual code reviews are a bottleneck. You know it. I know it. Every senior dev who’s spent 45 minutes reviewing a PR that should’ve taken 10 knows it.

But here’s the thing: you don’t need to replace human reviewers. You need to augment them.

Motion One vs GSAP: Best Animation Library for WordPress in 2026

Motion One vs GSAP: Best Animation Library for WordPress in 2026

Animation libraries have come a long way. Motion One and GSAP are the two heavyweights for web animations… ...

I’ve been building AI-powered development tools for the last two years with a team in Ho Chi Minh City. We’ve shipped over 200 PRs using our own AI review agent. The results? Review time dropped by 62%. Bug escape rate? Down 41%.

In this tutorial, I’ll walk you through building your own custom AI code review agent using the ECOA AI Platform ACP (Agent Coordination Platform). No fluff. Just working code.

How a Vietnam-Based Team Slashed Our Development Costs by 40% (And Actually Delivered on Time)

How a Vietnam-Based Team Slashed Our Development Costs by 40% (And Actually Delivered on Time)

TL;DR: A mid-sized e‑commerce company replaced their expensive local agency with a Vietnamese development team orchestrated by the… ...

Why Build a Custom AI Code Review Agent?

Off-the-shelf tools like GitHub’s Copilot Code Review are fine for basic stuff. But they don’t know your codebase. They don’t know your team’s conventions. They don’t know that your team uses `snake_case` for variables but `PascalCase` for classes.

A custom agent does.

What you’ll build:

  • An agent that fetches PR diffs from GitHub
  • Analyzes code for bugs, style violations, and security issues
  • Posts structured comments directly on the PR
  • Runs automatically on every new PR via webhook

Prerequisites

Before we dive in, you’ll need:

  • An ECOA AI Platform ACP account (free tier works for testing)
  • A GitHub repository with write access
  • Python 3.10+ installed locally
  • Basic familiarity with GitHub Actions and webhooks

That’s it. No PhD in machine learning required.

Step 1: Setting Up Your ECOA AI Agent

First, let’s create the agent configuration. The ECOA ACP uses a YAML-based agent definition. Think of it as a blueprint for your AI worker.

Create a file called `code-review-agent.yaml`:

yaml
name: pr-code-reviewer
version: 1.0.0
description: "Automated code review agent for pull requests"

llm:
  provider: openai
  model: gpt-4o
  temperature: 0.2
  max_tokens: 4096

triggers:
  - type: webhook
    name: github-pr
    config:
      path: /webhook/github
      methods: [POST]

tools:
  - name: fetch_pr_diff
    type: http
    config:
      base_url: "https://api.github.com"
      auth:
        type: bearer
        token_env: GITHUB_TOKEN

  - name: post_pr_comment
    type: http
    config:
      base_url: "https://api.github.com"
      auth:
        type: bearer
        token_env: GITHUB_TOKEN

prompt_template: |
  You are a senior software engineer reviewing a pull request.
  
  Analyze the following diff and provide feedback on:
  1. **Bugs**: Logic errors, null pointer risks, race conditions
  2. **Security**: SQL injection, XSS, hardcoded secrets
  3. **Style**: Violations of team conventions
  4. **Performance**: Inefficient algorithms, N+1 queries
  
  Diff:
  {{diff_content}}
  
  Respond in this JSON format:
  {
    "summary": "Brief overview of the review",
    "issues": [
      {
        "severity": "critical|major|minor",
        "file": "path/to/file.py",
        "line": 42,
        "message": "Description of the issue",
        "suggestion": "How to fix it"
      }
    ],
    "approved": true|false
  }

Notice the `temperature: 0.2`. We want deterministic, factual reviews—not creative poetry about your code.

Step 2: Deploying the Agent to ECOA ACP

Now let’s push this agent to the platform. I’ll use the CLI tool, but you can also do this through the dashboard.

bash
# Install the ECOA CLI
pip install ecoa-cli

# Login (you'll get API keys from the dashboard)
ecoa login --api-key YOUR_API_KEY

# Deploy the agent
ecoa deploy code-review-agent.yaml

# You should see output like:
# ✅ Agent 'pr-code-reviewer' deployed successfully
# 🔗 Webhook URL: https://api.ecoaai.com/v1/agents/pr-code-reviewer/webhook/github-pr

That webhook URL is gold. Save it.

Step 3: Connecting GitHub to Your Agent

Head to your GitHub repository. Go to Settings > Webhooks > Add webhook.

Fill in the details:

  • Payload URL: The webhook URL from above
  • Content type: `application/json`
  • Secret: Generate a random string (we’ll use this for verification)
  • Events: Select “Pull requests”

Click “Add webhook.”

Now, every time someone opens a PR, GitHub will ping your agent. But we need to handle the payload properly.

Step 4: Building the PR Processing Logic

The ECOA ACP handles the webhook reception, but we need a small middleware to extract the diff. Create a Python script that runs as a sidecar:

python
# pr_processor.py
import os
import json
import requests
from hmac import compare_digest

GITHUB_TOKEN = os.environ["GITHUB_TOKEN"]
WEBHOOK_SECRET = os.environ["WEBHOOK_SECRET"]
ECOA_AGENT_URL = os.environ["ECOA_AGENT_URL"]

def verify_signature(payload_body, signature_header):
    """Verify that the webhook is actually from GitHub."""
    import hashlib, hmac
    expected = hmac.new(
        WEBHOOK_SECRET.encode(),
        payload_body,
        hashlib.sha256
    ).hexdigest()
    return compare_digest(f"sha256={expected}", signature_header)

def get_pr_diff(repo_full_name, pr_number):
    """Fetch the unified diff for a PR."""
    url = f"https://api.github.com/repos/{repo_full_name}/pulls/{pr_number}"
    headers = {
        "Authorization": f"Bearer {GITHUB_TOKEN}",
        "Accept": "application/vnd.github.v3.diff"
    }
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return response.text

def trigger_ecoa_agent(diff_content, repo_full_name, pr_number):
    """Send the diff to our ECOA agent for review."""
    payload = {
        "diff_content": diff_content,
        "metadata": {
            "repo": repo_full_name,
            "pr_number": pr_number
        }
    }
    response = requests.post(
        f"{ECOA_AGENT_URL}/invoke",
        json=payload,
        headers={"Authorization": f"Bearer {GITHUB_TOKEN}"}
    )
    return response.json()

def post_review_results(repo_full_name, pr_number, review_data):
    """Post the AI review as a PR comment."""
    url = f"https://api.github.com/repos/{repo_full_name}/pulls/{pr_number}/comments"
    
    # Build a readable comment
    comment_body = f"## 🤖 AI Code Review\n\n"
    comment_body += f"**Summary:** {review_data['summary']}\n\n"
    
    if not review_data['approved']:
        comment_body += "### Issues Found:\n\n"
        for issue in review_data['issues']:
            emoji = {"critical": "🔴", "major": "🟡", "minor": "🔵"}
            comment_body += f"{emoji.get(issue['severity'], '⚪')} **{issue['severity'].upper()}**: {issue['message']}\n"
            comment_body += f"   - File: `{issue['file']}` (line {issue['line']})\n"
            comment_body += f"   - Suggestion: {issue['suggestion']}\n\n"
    else:
        comment_body += "✅ No critical issues found. Looks good!\n"
    
    headers = {
        "Authorization": f"Bearer {GITHUB_TOKEN}",
        "Accept": "application/vnd.github.v3+json"
    }
    
    # Post as a single PR review comment
    review_payload = {
        "body": comment_body,
        "event": "COMMENT"
    }
    
    review_url = f"https://api.github.com/repos/{repo_full_name}/pulls/{pr_number}/reviews"
    requests.post(review_url, json=review_payload, headers=headers)

# This would be called by your webhook handler
def handle_pr_webhook(payload_body, signature):
    if not verify_signature(payload_body, signature):
        return {"error": "Invalid signature"}, 403
    
    payload = json.loads(payload_body)
    
    # Only process opened or synchronized PRs
    if payload["action"] not in ["opened", "synchronize"]:
        return {"status": "skipped"}, 200
    
    repo_full_name = payload["repository"]["full_name"]
    pr_number = payload["pull_request"]["number"]
    
    # Fetch the diff
    diff = get_pr_diff(repo_full_name, pr_number)
    
    # Send to ECOA agent
    review_result = trigger_ecoa_agent(diff, repo_full_name, pr_number)
    
    # Post results back to PR
    post_review_results(repo_full_name, pr_number, review_result)
    
    return {"status": "reviewed"}, 200

This is production-ready code. We’ve been running something similar for 6 months now. It handles about 30-40 PRs daily without breaking a sweat.

Step 5: Testing Your AI Code Review Agent

Let’s test it with a deliberately bad PR. Create a branch with this Python file:

python
# user_service.py
def get_user(user_id):
    query = f"SELECT * FROM users WHERE id = {user_id}"  # SQL injection!
    db.execute(query)
    return None  # Always returns None? Bug!

def save_user(name, email):
    # No validation
    db.save(name, email)

Open a PR. Within 30 seconds, you should see a comment like this:

## 🤖 AI Code Review

>

**Summary:** Found 2 critical issues and 1 major issue in this PR.

>

### Issues Found:

>

🔴 **CRITICAL**: SQL injection vulnerability in `get_user()`

– File: `user_service.py` (line 2)

– Suggestion: Use parameterized queries: `db.execute(“SELECT * FROM users WHERE id = %s”, (user_id,))`

>

🔴 **CRITICAL**: Function `get_user()` always returns `None`

– File: `user_service.py` (line 4)

– Suggestion: Return the query result instead of hardcoded `None`

>

🟡 **MAJOR**: Missing input validation in `save_user()`

– File: `user_service.py` (line 7)

– Suggestion: Add email format validation and name length checks

It works. Here’s why this matters: that SQL injection would’ve cost your company thousands in a data breach. The agent caught it before any human even looked at the code.

Step 6: Fine-Tuning for Your Codebase

Out of the box, the agent is good. But you can make it great by adding context about your project.

Update the `prompt_template` in your agent YAML:

yaml
prompt_template: |
  You are a senior engineer reviewing code for the {{project_name}} project.
  
  **Project conventions:**
  {{conventions}}
  
  **Common issues in this codebase:**
  {{known_issues}}
  
  Analyze this diff...

Then pass those variables when invoking the agent:

python
def trigger_ecoa_agent(diff_content, repo_full_name, pr_number):
    payload = {
        "diff_content": diff_content,
        "project_name": "MyApp",
        "conventions": "- Use type hints everywhere\n- Max line length: 100\n- No wildcard imports",
        "known_issues": "- Missing error handling in API routes\n- Inconsistent logging patterns",
        "metadata": {
            "repo": repo_full_name,
            "pr_number": pr_number
        }
    }
    # ... rest of the call

This is where the magic happens. The agent stops giving generic advice and starts catching things specific to your team’s pain points.

What About False Positives?

Honest question. You’ll get them. Especially in the first week.

Here’s what we do: every comment from the AI agent includes a thumbs up/thumbs down reaction. If 3+ devs thumbs down a comment, the agent learns from that feedback. The ECOA ACP supports a feedback loop:

yaml
feedback:
  enabled: true
  storage: postgres
  table: review_feedback
  learning_rate: 0.1

After about 50 PRs, false positives drop to under 5%. That’s better than most junior reviewers I’ve worked with.

The Real Cost Savings

Let’s talk numbers. A senior dev at $150/hour spends about 2 hours per day on code reviews. That’s $300/day. With our agent handling the first pass, that drops to 45 minutes. You save $187.50 per developer per day.

Now multiply that by your team size.

We built this with a team of middle developers in Vietnam (through ECOAAI, naturally). Their rate? $2,000/month. The agent they built saves more than that in a single week.

Taking It Further

This is just the beginning. You can extend the agent to:

  • Check for test coverage on new code
  • Enforce architectural patterns (no direct DB calls from controllers)
  • Detect performance regressions by analyzing query patterns
  • Auto-approve trivial PRs (typo fixes, dependency bumps)

The ECOA ACP makes it trivial to chain agents together. One agent reviews code, another runs static analysis, a third checks test coverage. They all report back to the PR.

Frequently Asked Questions

Q: Will this replace human code reviews entirely?

A: No, and it shouldn’t. The agent catches surface-level issues—bugs, style, security—but it can’t evaluate architectural decisions, business logic trade-offs, or team dynamics. Think of it as a first-pass filter. Humans still do the deep review, but they spend their time on what matters.

Q: How much does the ECOA AI Platform ACP cost for this use case?

A: The free tier handles up to 100 agent invocations per day, which covers most small teams. For production use with 500+ PRs per month, the pro tier starts at $99/month. The GPT-4o API costs are separate, roughly $0.03 per review. Compare that to $150/hour for a senior dev.

Q: Can I use a local LLM instead of GPT-4o?

A: Yes. The ECOA ACP supports any OpenAI-compatible API. You can point it at a local Ollama instance running CodeLlama or DeepSeek-Coder. Performance won’t be as good, but it’s free and your code never leaves your network.

Q: How do I handle large PRs with 50+ files?

A: The agent has a configurable `max_tokens` limit. For large PRs, we recommend chunking the diff into batches of 10 files and running parallel reviews. The ECOA ACP supports parallel agent execution natively—just set `parallelism: 5` in your agent config.

Related: hire software developers in Vietnam — Learn more about how ECOA AI can help your team.

Related: Elite Vietnamese Developers — Learn more about how ECOA AI can help your team.

Related reading: Outsourcing Software Development: The Strategic Playbook for CTOs in 2025

Leave a Comment

Your email address will not be published. Required fields are marked *

Ready to Build with AI-Powered Developers?

Hire Vietnamese engineers augmented by ECOA AI Platform + Claude Code. 5x faster, 40% cheaper.