Back to .md Directory

Cassandra - AI Review Agent

> *The truth about your code. Seeing bugs before the fall of production. Ignore at your own peril.*

May 2, 2026
0 downloads
25 views
ai agent llm prompt mcp claude openai gemini
View source

Cassandra - AI Review Agent

The truth about your code. Seeing bugs before the fall of production. Ignore at your own peril.

An autonomous code review tool built in Go. This tool provides structured, actionable code reviews using a configurable and adjustable feedback framework.

Features

  • Local Git Diff Review: Review your local uncommitted changes against a base branch before pushing.
  • Provider Agnostic: Natively supports Anthropic and Google models through a unified abstraction.
  • Agentic Context Gathering: The LLM agent operates in a ReAct loop and has access to repository tools (like reading files, glob matching, and pattern searching with grep) to autonomously gather surrounding context about your codebase before finalizing feedback.
  • Visual Status Indicators: Automatically adds an "eyes" reaction to Pull Requests while the review is in progress, providing immediate feedback.
  • Inline PR Reviews: Supports formal GitHub PR Reviews with line-level feedback, including automatic dismissal of stale reviews and deduplication of comments.
  • Model Context Protocol (MCP) Support: Connect to custom local or remote tools through the Model Context Protocol to extend the reviewer's capabilities.
  • CI/CD Ready: Supports outputting reviews directly to files or as structured JSON, making it easy to integrate with GitHub Actions or other CI pipelines.

Requirements

  • Go 1.24.4+
  • Bazel 8.6.0 (if building with bzlmod)
  • A valid API key for your chosen LLM provider (Google Gemini or Anthropic Claude).

Installation

Build the binary using standard Go commands:

go build -o ai-review-agent ./cmd/ai_reviewer

(Alternatively, you can build using Bazel: bazel run //cmd/ai_reviewer:ai_reviewer)

Usage

Review Changes

To review changes between a base and a head commit/branch:

./ai-review-agent \
  --base main \
  --head feature-branch \
  --provider google \
  --model gemini-3.1-pro-preview \
  --provider-api-key "YOUR_API_KEY"

CLI Options

The following settings can be provided via CLI flags, environment variables, or a cassandra.toml file.

Note: provider, model, and provider-api-key are mandatory and must be provided via one of these methods.

FlagDescriptionDefault
--cwdWorking directory
--baseBase commit/branch for diffmain
--headHead commit/branch for diffHEAD
--providerLLM provider to use (google, anthropic, openai)
--modelLLM provider's specific model ID
--provider-api-keyAPI key for the selected provider
--provider-urlOptional API endpoint URL override (useful for OpenAI-compatible providers like Ollama)
--configPath to a configuration file (toml)cassandra.toml
--main-guidelinesPath to a file or a named prompt from the library (general, asana-do-try-consider, google, conventional-comments, palantir, minimalist, security-first)general
--supplemental-guidelinesAdditive paths or named library prompts for supplemental guidelines (can be used multiple times)
--approval-evaluation-prompt-filePath to a file containing custom approval evaluation guidelines
--review-output-filePath to a file where the final review will be written
--output-jsonPath to a file where the structured JSON review will be written
--mcp-configPath to an mcp.json file configuring custom tools for the reviewer
--extraction-modelOptional model override for the structured JSON extraction pass
--max-tokensMax tokens for the LLM response8192

GitHub Action Inputs

InputDescriptionDefaultRequired
providerLLM provider to use (google, anthropic, openai)No
model_idLLM provider's specific model IDNo
provider_api_keyAPI key for the selected providerYes
provider_urlOptional API endpoint URL override (useful for OpenAI-compatible providers like Ollama)No
config_filePath to a configuration file (toml)cassandra.tomlNo
baseBase commit/branch for diffmainNo
headHead commit/branch for diffHEADNo
max_tokensMax tokens for the LLM response8192No
working_directoryWorking directory to review.No
main_guidelinesPath to a file or a named prompt from the library (general, asana-do-try-consider, google, conventional-comments, palantir, minimalist, security-first)generalNo
supplemental_guidelinesAdditive guidelines to supplement the main guidelines. Multiline string where each line is a path or library prompt name.No
approval_evaluation_prompt_filePath to a file containing custom approval evaluation guidelinesNo
metadata_tagTag to identify Cassandra comments (inner text only, will be wrapped in <!-- ... -->)cassandra-ai-review-${{ github.workflow }}No
reaction_iconThe reaction icon to add to the PR description while the review is in progress (e.g., eyes, rocket, heart)eyesNo
reviewer_github_tokenGitHub token for posting comments and reactions${{ github.token }}No
use_inline_commentsWhether to post inline comments to the PR (requires structured JSON output)trueNo
submit_review_actionWhether to allow formal "approve/reject" actions or force neutral "comment"falseNo
delete_old_commentsWhether to delete previous bot-authored inline comments before posting a new reviewtrueNo
mcp_configPath to an mcp.json file configuring custom tools for the reviewerNo

GitHub Action Outputs

After the review completes, the action exposes the following outputs that downstream steps can consume:

OutputDescription
review_fileAbsolute path to the generated markdown review file on the runner.
json_fileAbsolute path to the structured JSON review file (only set when the JSON was successfully written).
approvedThe approval decision: APPROVE, REQUEST_CHANGES, or COMMENT.
review_rationaleThe high-level rationale for the approval decision (may be multi-line).

Example — gating a subsequent step on the review outcome:

      - name: Run Cassandra AI Review
        id: cassandra
        uses: menny/cassandra@v1
        with:
          provider: 'google'
          model_id: 'gemini-2.5-flash'
          provider_api_key: ${{ secrets.GEMINI_API_KEY }}
          base: ${{ github.event.pull_request.base.sha }}
          head: ${{ github.event.pull_request.head.sha }}

      - name: Fail if changes requested
        if: steps.cassandra.outputs.approved == 'REQUEST_CHANGES'
        env:
          REVIEW_RATIONALE: ${{ steps.cassandra.outputs.review_rationale }}
        run: |
          echo "Cassandra requested changes: $REVIEW_RATIONALE"
          exit 1

Configuration File (cassandra.toml)

Cassandra automatically looks for a cassandra.toml file in your repository's root. This allows you to centralize settings and avoid redundant CLI flags or GitHub Action inputs.

# Example cassandra.toml
provider = "google"
model = "gemini-3.1-pro-preview"
main-guidelines = "security-first"
supplemental-guidelines = [
  ".cassandra/haiku-praise.md"
]

Supported Models

For a full list of available models and their IDs, refer to the official documentation:

GitHub Actions Integration

Cassandra can be integrated into your GitHub Actions workflow to automatically review Pull Requests.

Key Benefits

  • Persistent Comments: Manages a single "persistent comment" on the Pull Request, updating it as new changes are pushed to keep the conversation history clean.
  • Visual Feedback: Automatically adds an "eyes" reaction to the PR description when the review starts and removes it when finished.
  • Secure Token Handling: Uses a dedicated token preparation step with masking for secure and robust interactions.

Required Permissions

The workflow job running Cassandra needs the following permissions:

PermissionWhy it's needed
contents: readTo check out the repository and compute the git diff.
pull-requests: writeTo post reviews, inline comments, and manage PR reactions.
issues: writeTo post general (non-inline) PR comments via the GitHub Issues API.

Approving PRs (submit_review_action: 'true'): pull-requests: write covers submitting formal APPROVE / REQUEST_CHANGES reviews. Note that the default GITHUB_TOKEN cannot approve a PR opened by the same user/actor — this is a GitHub restriction, not a Cassandra limitation. Use a dedicated bot token via reviewer_github_token if self-approval is required.

Complete Workflow Example

Create .github/workflows/cassandra-review.yml in your repository:

name: Cassandra AI Review
on:
  pull_request:
    types: [opened, synchronize, reopened]

permissions:
  contents: read
  pull-requests: write
  issues: write

jobs:
  review:
    name: AI Code Review
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Run Cassandra AI Review
        uses: menny/cassandra@v1
        with:
          provider: 'google'
          model_id: 'gemini-2.5-flash'
          provider_api_key: ${{ secrets.GEMINI_API_KEY }}

Per-Directory Review Guidelines — REVIEWERS.md and AGENTS.md

Cassandra automatically discovers REVIEWERS.md and AGENTS.md files in your repository and incorporates their contents into the review prompt. Both file types use the same discovery logic, letting teams provide targeted, directory-specific guidance to the AI reviewer and to AI coding assistants alike.

How it works:

For each file that changed in the PR, Cassandra walks up the directory tree from that file's location to the repository root, collecting every REVIEWERS.md and AGENTS.md file it finds. All discovered files are injected into the system prompt, scoped by directory.

Example:

my-repo/
├── REVIEWERS.md              # Root-level review guidelines (apply to all files)
├── AGENTS.md                 # Root-level instructions for AI coding assistants
├── backend/
│   ├── REVIEWERS.md          # Backend-specific review guidelines
│   ├── AGENTS.md             # Backend-specific assistant instructions
│   └── api/
│       └── handlers.go       # If this file changes, both backend/ and root files are loaded
└── frontend/
    └── REVIEWERS.md          # Frontend-specific review guidelines

REVIEWERS.md — guidance aimed at the AI reviewer:

# Backend Review Guidelines

- All public functions must have godoc comments.
- Database queries must use parameterized statements — never string interpolation.
- Error values must be wrapped with `fmt.Errorf("...: %w", err)`.
- New HTTP endpoints must have a corresponding integration test.

AGENTS.md — instructions shared with AI coding assistants (e.g. GitHub Copilot, Claude):

# Backend Agent Instructions

- Follow the repository style guide in docs/style.md.
- Prefer table-driven tests over individual test functions.
- Do not modify generated files under gen/.

Both file types can coexist in the same directory and are loaded independently.

Custom Tools with Model Context Protocol (MCP)

Cassandra supports the Model Context Protocol (MCP), allowing you to extend the reviewer's capabilities with custom tools. This is useful for integrating with internal APIs, specialized linters, or documentation search.

Configuration (mcp.json)

Create an mcp.json file to define your MCP servers. Cassandra supports both local stdio servers and remote sse (HTTP) servers. Environment variables in the configuration are automatically expanded using os.ExpandEnv.

{
  "mcpServers": {
    "my-local-tool": {
      "command": "node",
      "args": ["/path/to/server.js"],
      "env": {
        "DEBUG": "true"
      }
    },
    "my-remote-tool": {
      "url": "https://mcp.example.com/sse",
      "headers": {
        "Authorization": "Bearer ${MY_API_KEY}"
      }
    }
  }
}

Usage in GitHub Actions

Pass the path to your mcp.json via the mcp_config input. Ensure any environment variables required by your MCP configuration are available in the step's environment.

      - name: Run Cassandra AI Review
        uses: menny/cassandra@v1
        with:
          provider: 'google'
          model_id: 'gemini-2.5-flash'
          provider_api_key: ${{ secrets.GEMINI_API_KEY }}
          mcp_config: '.github/mcp.json'
        env:
          MY_API_KEY: ${{ secrets.MY_INTERNAL_TOOL_KEY }}

Troubleshooting

Cassandra posts a comment but no inline annotations appear

Cause: Inline comments require use_inline_comments: 'true' (the default) and a valid structured JSON output. This can fail if:

  1. The LLM returned a line number outside the PR diff (a "line hallucination"). Cassandra automatically retries without inline comments in this case, appending all feedback to the main review body.
  2. The pull-requests: write permission is missing.

Error: GITHUB_TOKEN is not permitted to approve

Cause: The default GITHUB_TOKEN cannot approve a PR opened by the same user or actor.

Fix: Use a dedicated Personal Access Token (PAT) or a GitHub App token:

reviewer_github_token: ${{ secrets.REVIEWER_GITHUB_TOKEN }}

Alternatively, set submit_review_action: 'false' to use comment-only mode.


The Bazel build step takes a long time

Cause: Cassandra builds its Go binaries with Bazel on first run. Subsequent runs use the Bazel disk cache.

Fix: The setup-bazel step in the action configures a persistent disk cache keyed to cassandra-ai-review. This cache is shared across all workflow runs in your repository. The first run for a new runner may still take 1–2 minutes; subsequent runs are significantly faster.


Error: No GitHub token available

Cause: The reviewer_github_token input was set to a secret that doesn't exist or is empty.

Fix: Check that the secret name is correct in your repository settings. The action falls back to github.token automatically, but if that is also unavailable the step will fail.

Choosing the Right GitHub Token

Cassandra can work with any GitHub token passed via the reviewer_github_token input. Choosing the right one depends on your needs for cross-repo access and PR approval.

FeatureGITHUB_TOKEN (Default)Classic PAT (repo scope)GitHub App Token
Setup ComplexityNone (Automatic)Low (Create token)Medium (Create & Install App)
Identitygithub-actions[bot]Your User AccountYour App Name
Self-ApprovalNoYesYes
Cross-Repo AccessLimitedFull (Everything you see)Scoped (Where installed)
SecurityHighest (Ephemeral)Lower (Long-lived/Global)High (Scoped/Short-lived)

Architecture

The project features a lean, custom native Go ReAct loop. Provider-specific interactions are handled via native SDKs (not langchaingo). Tools for codebase context gathering are injected securely through model-native Function Calling capabilities.

Token Efficiency

Cassandra structures every system prompt with static content first and dynamic, per-PR content last. This "stable-prefix" ordering means the large, unchanging portion of the prompt — reviewer instructions, the chosen review guideline, and approval rules — is byte-for-byte identical across all reviews of the same repository. Both Anthropic (via cache_control breakpoints) and Google Gemini 2.5 (via implicit prefix caching) can reuse cached intermediate states for this prefix, reducing input token costs by up to 75–90% and cutting the time-to-first-token on repeated reviews of the same repository.

Related Documents