← back to blog

Running AI in Your CI/CD Pipeline with MonoRouter

Use Claude in GitHub Actions, GitLab CI, or any CI system by routing through MonoRouter. No API credits, no usage surprises.

CI/CD pipelines are one of the best places to use AI — automated code review, test generation, documentation updates. They're also one of the most expensive places to use the Anthropic API, because pipeline runs add up fast. MonoRouter makes this practical.

GitHub Actions: Complete Workflow

Here's a full workflow that runs an AI-powered code review on every pull request:

# .github/workflows/ai-review.yml
name: AI Code Review

on:
  pull_request:
    types: [opened, synchronize]

permissions:
  contents: read
  pull-requests: write

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Need full history for diff

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install dependencies
        run: pip install anthropic

      - name: Get PR diff
        id: diff
        run: |
          git diff origin/${{ github.base_ref }}...HEAD > /tmp/pr.diff
          echo "lines=$(wc -l < /tmp/pr.diff)" >> $GITHUB_OUTPUT

      - name: AI Review
        if: steps.diff.outputs.lines > 0
        env:
          ANTHROPIC_API_KEY: ${{ secrets.MONOROUTER_KEY }}
          ANTHROPIC_BASE_URL: https://api.monorouter.dev/v1
        run: python scripts/ai-review.py /tmp/pr.diff

      - name: Post review comment
        if: steps.diff.outputs.lines > 0
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const review = fs.readFileSync('/tmp/review.md', 'utf8');
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: review
            });

The Review Script

Here's the Python script that powers the review:

#!/usr/bin/env python3
"""AI-powered code review using Claude through MonoRouter."""

import anthropic
import sys

def review_diff(diff_path: str) -> str:
    client = anthropic.Anthropic()  # reads env vars

    with open(diff_path) as f:
        diff = f.read()

    # Truncate very large diffs to stay within context limits
    if len(diff) > 100_000:
        diff = diff[:100_000] + "\n... (truncated)"

    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=4096,
        system="""You are a senior code reviewer. Review the following git diff.

Focus on:
- Bugs and logic errors
- Security vulnerabilities (injection, auth bypass, data exposure)
- Performance issues (N+1 queries, unnecessary allocations)
- Missing error handling

Format your response as markdown. Use ✅ for approvals and ⚠️ for issues.
Start with a one-line summary. Skip style nitpicks.""",
        messages=[{"role": "user", "content": f"```diff\n{diff}\n```"}],
    )

    return response.content[0].text

if __name__ == "__main__":
    review = review_diff(sys.argv[1])

    # Write to file for the GitHub Action to pick up
    with open("/tmp/review.md", "w") as f:
        f.write("## AI Code Review\n\n")
        f.write(review)
        f.write("\n\n---\n*Powered by Claude via MonoRouter*")

    print(review)

GitLab CI Configuration

The same approach works with GitLab CI:

# .gitlab-ci.yml
ai-review:
  stage: review
  image: python:3.12-slim
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  variables:
    ANTHROPIC_API_KEY: $MONOROUTER_KEY
    ANTHROPIC_BASE_URL: "https://api.monorouter.dev/v1"
  before_script:
    - pip install anthropic
  script:
    - git diff $CI_MERGE_REQUEST_DIFF_BASE_SHA...$CI_COMMIT_SHA > /tmp/pr.diff
    - python scripts/ai-review.py /tmp/pr.diff
  artifacts:
    paths:
      - /tmp/review.md
    expire_in: 1 week

AI Test Generation

Beyond code review, you can use Claude to generate test cases for changed code. Here's a script that generates tests for new functions:

#!/usr/bin/env python3
"""Generate test stubs for new functions in a PR diff."""

import anthropic
import re

def generate_tests(diff_path: str) -> str:
    client = anthropic.Anthropic()

    with open(diff_path) as f:
        diff = f.read()

    # Extract only added lines (new code)
    added_lines = [
        line[1:] for line in diff.split("\n")
        if line.startswith("+") and not line.startswith("+++")
    ]

    if not added_lines:
        return "No new code to test."

    new_code = "\n".join(added_lines)

    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=4096,
        system="""Generate pytest test cases for the following new code.
Include edge cases and error conditions.
Use descriptive test names.
Add brief comments explaining what each test verifies.""",
        messages=[{"role": "user", "content": f"```python\n{new_code}\n```"}],
    )

    return response.content[0].text

if __name__ == "__main__":
    import sys
    tests = generate_tests(sys.argv[1])
    print(tests)

Why CI is Expensive on the API

A code review bot that runs on every PR might analyze 50–100 files per review. That's a lot of input tokens. Here's a real cost projection:

MetricDailyMonthly
PRs per day15~300
Avg diff size5,000 tokens
Review output800 tokens
Input tokens (Sonnet)75K1.5M
Output tokens (Sonnet)12K240K
API cost$0.40$8.10

That's just for code review. Add test generation ($15/mo), documentation updates ($10/mo), and commit message suggestions ($5/mo), and CI-driven AI costs hit $40+/month. Through MonoRouter, all of it is covered by your existing subscriptions.

Concurrency and Caching

CI pipelines can trigger multiple jobs simultaneously. MonoRouter's request queuing handles this — jobs wait in the queue rather than failing with 429 errors.

For efficiency, cache your Python dependencies so each CI run doesn't reinstall anthropic:

# GitHub Actions caching
- uses: actions/cache@v4
  with:
    path: ~/.cache/pip
    key: ${{ runner.os }}-pip-anthropic
    restore-keys: ${{ runner.os }}-pip-

- run: pip install anthropic

Set generous timeouts in your CI configuration. A review that normally takes 15 seconds might take 60 seconds during peak hours:

- name: AI Review
  timeout-minutes: 5  # generous timeout for queued requests
  env:
    ANTHROPIC_API_KEY: ${{ secrets.MONOROUTER_KEY }}
    ANTHROPIC_BASE_URL: https://api.monorouter.dev/v1
  run: python scripts/ai-review.py /tmp/pr.diff

Other CI Systems

The same approach works with CircleCI, Jenkins, Buildkite, or any CI system that supports environment variables. The pattern is always the same:

  1. Store MONOROUTER_KEY as an encrypted secret
  2. Set ANTHROPIC_API_KEY and ANTHROPIC_BASE_URL in the job environment
  3. Run your Python/TypeScript script as a build step
  4. Use the output however you need (PR comments, artifacts, Slack notifications)