cassandra

module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 27, 2026 License: Apache-2.0

README

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.

Flag Description Default
--cwd Working directory
--base Base commit/branch for diff main
--head Head commit/branch for diff HEAD
--provider LLM provider to use (google, anthropic, openai)
--model LLM provider's specific model ID
--provider-api-key API key for the selected provider
--provider-url Optional API endpoint URL override (useful for OpenAI-compatible providers like Ollama)
--config Path to a configuration file (toml) cassandra.toml
--main-guidelines Path to a file or a named prompt from the library (general, asana-do-try-consider, google, conventional-comments, palantir, minimalist, security-first) general
--supplemental-guidelines Additive paths or named library prompts for supplemental guidelines (can be used multiple times)
--approval-evaluation-prompt-file Path to a file containing custom approval evaluation guidelines
--review-output-file Path to a file where the final review will be written
--output-json Path to a file where the structured JSON review will be written
--mcp-config Path to an mcp.json file configuring custom tools for the reviewer
--extraction-model Optional model override for the structured JSON extraction pass
--max-tokens Max tokens for the LLM response 8192

GitHub Action Inputs

Input Description Default Required
provider LLM provider to use (google, anthropic, openai) No
model_id LLM provider's specific model ID No
provider_api_key API key for the selected provider Yes
provider_url Optional API endpoint URL override (useful for OpenAI-compatible providers like Ollama) No
config_file Path to a configuration file (toml) cassandra.toml No
base Base commit/branch for diff main No
head Head commit/branch for diff HEAD No
max_tokens Max tokens for the LLM response 8192 No
working_directory Working directory to review . No
main_guidelines Path to a file or a named prompt from the library (general, asana-do-try-consider, google, conventional-comments, palantir, minimalist, security-first) general No
supplemental_guidelines Additive guidelines to supplement the main guidelines. Multiline string where each line is a path or library prompt name. No
approval_evaluation_prompt_file Path to a file containing custom approval evaluation guidelines No
metadata_tag Tag to identify Cassandra comments (inner text only, will be wrapped in <!-- ... -->) cassandra-ai-review-${{ github.workflow }} No
reaction_icon The reaction icon to add to the PR description while the review is in progress (e.g., eyes, rocket, heart) eyes No
reviewer_github_token GitHub token for posting comments and reactions ${{ github.token }} No
use_inline_comments Whether to post inline comments to the PR (requires structured JSON output) true No
submit_review_action Whether to allow formal "approve/reject" actions or force neutral "comment" false No
delete_old_comments Whether to delete previous bot-authored inline comments before posting a new review true No
mcp_config Path to an mcp.json file configuring custom tools for the reviewer No

GitHub Action Outputs

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

Output Description
review_file Absolute path to the generated markdown review file on the runner.
json_file Absolute path to the structured JSON review file (only set when the JSON was successfully written).
approved The approval decision: APPROVE, REQUEST_CHANGES, or COMMENT.
review_rationale The 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 = [
  ".github/ai-reviewer/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:

Permission Why it's needed
contents: read To check out the repository and compute the git diff.
pull-requests: write To post reviews, inline comments, and manage PR reactions.
issues: write To 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.

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.

Directories

Path Synopsis
cmd
ai_reviewer command
github command
mcp_godoc command
llm
Package llm defines the provider-agnostic interface and types used throughout Cassandra.
Package llm defines the provider-agnostic interface and types used throughout Cassandra.
anthropic
Package anthropic implements llm.Model using the official Anthropic Go SDK.
Package anthropic implements llm.Model using the official Anthropic Go SDK.
factory
Package factory constructs llm.Model instances for the supported providers.
Package factory constructs llm.Model instances for the supported providers.
google
Package google implements llm.Model using the official Google Gen AI Go SDK.
Package google implements llm.Model using the official Google Gen AI Go SDK.
openai
Package openai implements llm.Model using the official OpenAI Go SDK.
Package openai implements llm.Model using the official OpenAI Go SDK.
mcp

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL