Skip to main content
The reference workflow is available here!
Automate pull request triage by intelligently assigning reviewers based on git blame analysis, notifying reviewers of pending PRs, and prompting authors on stale pull requests. The agent performs three sequential checks: pinging reviewers on clean PRs awaiting review (3+ days), reminding authors on stale PRs (5+ days), and auto-assigning reviewers based on code ownership for unassigned PRs.

How it works

It relies on the basic action workflow (01_basic_action) which provides a flexible template for running arbitrary agent tasks in GitHub Actions. Core Components:
  • agent_script.py - Python script that initializes the OpenHands agent with configurable LLM settings and executes tasks based on provided prompts
  • workflow.yml - GitHub Actions workflow that sets up the environment, installs dependencies, and runs the agent
Prompt Options:
  1. PROMPT_STRING - Direct inline text for simple prompts (used in this example)
  2. PROMPT_LOCATION - URL or file path for external prompts
The workflow downloads the agent script, validates configuration, runs the task, and uploads execution logs as artifacts.

Assign Reviews Use Case

This specific implementation uses the basic action template to handle three PR management scenarios: 1. Need Reviewer Action
  • Identifies PRs waiting for review
  • Notifies reviewers to take action
2. Need Author Action
  • Finds stale PRs with no activity for 5+ days
  • Prompts authors to update, request review, or close
3. Need Reviewers
  • Detects non-draft PRs without assigned reviewers (created 1+ day ago, CI passing)
  • Uses git blame analysis to identify relevant contributors
  • Automatically assigns reviewers based on file ownership and contribution history
  • Balances reviewer workload across team members

Quick Start

1

Copy workflow to your repository

cp examples/03_github_workflows/01_basic_action/assign-reviews.yml .github/workflows/assign-reviews.yml
2

Configure secrets in GitHub Settings

Go to GitHub Settings → Secrets → Actions, and add LLM_API_KEY (get from https://docs.openhands.dev/openhands/usage/llms/openhands-llms).
3

Configure GitHub Actions permissions

Go to GitHub Settings → Actions → General → Workflow permissions and enable “Read and write permissions”.
4

(Optional) Customize the schedule in the workflow file

The default is: Daily at 12 PM UTC.

Features

  • Intelligent Assignment - Uses git blame to identify relevant reviewers based on code ownership
  • Automated Notifications - Sends contextual reminders to reviewers and authors
  • Workload Balancing - Distributes review requests evenly across team members
  • Scheduled & Manual - Runs daily automatically or on-demand via workflow dispatch

Reference Workflow

examples/03_github_workflows/01_basic_action/assign-reviews.yml
---
# To set this up:
#  1. Change the name below to something relevant to your task
#  2. Modify the "env" section below with your prompt
#  3. Add your LLM_API_KEY to the repository secrets
#  4. Commit this file to your repository
#  5. Trigger the workflow manually or set up a schedule
name: Assign Reviews

on:
    # Manual trigger
    workflow_dispatch:
    # Scheduled trigger (disabled by default, uncomment and customize as needed)
    schedule:
      # Run at 12 PM UTC every day
        - cron: 0 12 * * *

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

jobs:
    run-task:
        runs-on: ubuntu-24.04
        env:
            # Configuration (modify these values as needed)
            AGENT_SCRIPT_URL: https://raw.githubusercontent.com/OpenHands/agent-sdk/main/examples/03_github_workflows/01_basic_action/agent_script.py
            # Provide either PROMPT_LOCATION (URL/file) OR PROMPT_STRING (direct text), not both
            # Option 1: Use a URL or file path for the prompt
            PROMPT_LOCATION: ''
            # PROMPT_LOCATION: 'https://example.com/prompts/maintenance.txt'
            # Option 2: Use direct text for the prompt
            PROMPT_STRING: >
                Use GITHUB_TOKEN and the github API to organize open pull requests and issues in the repo.
                Read the sections below in order, and perform each in order. Do NOT take action
                on the same issue or PR twice.

                # Issues with needs-info - Check for OP Response

                Find all open issues that have the "needs-info" label. For each issue:
                1. Identify the original poster (issue author)
                2. Check if there are any comments from the original poster AFTER the "needs-info" label was added
                3. To determine when the label was added, use: GET /repos/{owner}/{repo}/issues/{issue_number}/timeline
                   and look for "labeled" events with the label "needs-info"
                4. If the original poster has commented after the label was added:
                   - Remove the "needs-info" label
                   - Add the "needs-triage" label
                   - Post a comment: "[Automatic Post]: The issue author has provided additional information. Moving back to needs-triage for review."

                # Issues with needs-triage

                Find all open issues that have the "needs-triage" label. For each issue that has been in this state for more than 4 days since the last
                activity:
                1. First, check if the issue has already been triaged by verifying it does NOT have:
                   - The "enhancement" label
                   - Any "priority" label (priority:low, priority:medium, priority:high, etc.)
                2. If the issue has already been triaged (has enhancement or priority label), remove the needs-triage label
                3. For issues that have NOT been triaged yet:
                   - Read the issue description and comments
                   - Determine if it requires maintainer attention by checking:
                     * Is it a bug report, feature request, or question?
                     * Does it have enough information to be actionable?
                     * Has a maintainer already commented?
                     * Is the last comment older than 4 days?
                   - If it needs maintainer attention and no maintainer has commented:
                     * Find an appropriate maintainer based on the issue topic and recent activity
                     * Tag them with: "[Automatic Post]: This issue has been waiting for triage. @{maintainer}, could you please take a look when you have
                a chance?"

                # Need Reviewer Action

                Find all open PRs where:
                1. The PR is waiting for review (there are no open review comments or change requests)
                2. The PR is in a "clean" state (CI passing, no merge conflicts)
                3. The PR is not marked as draft (draft: false)
                4. The PR has had no activity (comments, commits, reviews) for more than 3 days.

                In this case, send a message to the reviewers:
                [Automatic Post]: This PR seems to be currently waiting for review.
                {reviewer_names}, could you please take a look when you have a chance?

                # Need Author Action

                Find all open PRs where the most recent change or comment was made on the pull
                request more than 5 days ago (use 14 days if the PR is marked as draft).

                And send a message to the author:

                [Automatic Post]: It has been a while since there was any activity on this PR.
                {author}, are you still working on it? If so, please go ahead, if not then
                please request review, close it, or request that someone else follow up.

                # Need Reviewers

                Find all open pull requests that:
                1. Have no reviewers assigned to them.
                2. Are not marked as draft.
                3. Were created more than 1 day ago.
                4. CI is passing and there are no merge conflicts.

                For each of these pull requests, read the git blame information for the files,
                and find the most recent and active contributors to the file/location of the changes.
                Assign one of these people as a reviewer, but try not to assign too many reviews to
                any single person. Add this message:

                [Automatic Post]: I have assigned {reviewer} as a reviewer based on git blame information.
                Thanks in advance for the help!

            LLM_MODEL: <YOUR_LLM_MODEL>
            LLM_BASE_URL: <YOUR_LLM_BASE_URL>
        steps:
            - name: Checkout repository
              uses: actions/checkout@v5

            - name: Set up Python
              uses: actions/setup-python@v6
              with:
                  python-version: '3.13'

            - name: Install uv
              uses: astral-sh/setup-uv@v7
              with:
                  enable-cache: true

            - name: Install OpenHands dependencies
              run: |
                  # Install OpenHands SDK and tools from git repository
                  uv pip install --system "openhands-sdk @ git+https://github.com/OpenHands/agent-sdk.git@main#subdirectory=openhands-sdk"
                  uv pip install --system "openhands-tools @ git+https://github.com/OpenHands/agent-sdk.git@main#subdirectory=openhands-tools"

            - name: Check required configuration
              env:
                  LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
              run: |
                  if [ -z "$LLM_API_KEY" ]; then
                    echo "Error: LLM_API_KEY secret is not set."
                    exit 1
                  fi

                  # Check that exactly one of PROMPT_LOCATION or PROMPT_STRING is set
                  if [ -n "$PROMPT_LOCATION" ] && [ -n "$PROMPT_STRING" ]; then
                    echo "Error: Both PROMPT_LOCATION and PROMPT_STRING are set."
                    echo "Please provide only one in the env section of the workflow file."
                    exit 1
                  fi

                  if [ -z "$PROMPT_LOCATION" ] && [ -z "$PROMPT_STRING" ]; then
                    echo "Error: Neither PROMPT_LOCATION nor PROMPT_STRING is set."
                    echo "Please set one in the env section of the workflow file."
                    exit 1
                  fi

                  if [ -n "$PROMPT_LOCATION" ]; then
                    echo "Prompt location: $PROMPT_LOCATION"
                  else
                    echo "Using inline PROMPT_STRING (${#PROMPT_STRING} characters)"
                  fi
                  echo "LLM model: $LLM_MODEL"
                  if [ -n "$LLM_BASE_URL" ]; then
                    echo "LLM base URL: $LLM_BASE_URL"
                  fi

            - name: Run task
              env:
                  LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
                  PYTHONPATH: ''
              run: |
                  echo "Running agent script: $AGENT_SCRIPT_URL"

                  # Download script if it's a URL
                  if [[ "$AGENT_SCRIPT_URL" =~ ^https?:// ]]; then
                    echo "Downloading agent script from URL..."
                    curl -sSL "$AGENT_SCRIPT_URL" -o /tmp/agent_script.py
                    AGENT_SCRIPT_PATH="/tmp/agent_script.py"
                  else
                    AGENT_SCRIPT_PATH="$AGENT_SCRIPT_URL"
                  fi

                  # Run with appropriate prompt argument
                  if [ -n "$PROMPT_LOCATION" ]; then
                    echo "Using prompt from: $PROMPT_LOCATION"
                    uv run python "$AGENT_SCRIPT_PATH" "$PROMPT_LOCATION"
                  else
                    echo "Using PROMPT_STRING (${#PROMPT_STRING} characters)"
                    uv run python "$AGENT_SCRIPT_PATH"
                  fi

            - name: Upload logs as artifact
              uses: actions/upload-artifact@v4
              if: always()
              with:
                  name: openhands-task-logs
                  path: |
                      *.log
                      output/
                  retention-days: 7