Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
75da75c
docs: add event-driven automation prerequisites and setup guides
openhands-agent May 28, 2026
cb4abbe
docs: improve event-driven automation docs accuracy and consistency
openhands-agent May 28, 2026
7dd4221
docs: address review feedback - team requests, JMESPath null semantic…
openhands-agent May 28, 2026
406681c
docs: address second review - move Note outside code block, document …
openhands-agent May 28, 2026
c7997bd
docs: address third review - FIRST_TIMER guard, valid single-repo fil…
openhands-agent May 28, 2026
9f1b621
docs: address fourth review - document no-resync behavior, reorder te…
openhands-agent May 28, 2026
113c2b6
docs: address fifth review - multi-line QA filter, GitHub App trouble…
openhands-agent May 28, 2026
c0fd827
docs: address sixth review - QA prompt formatting, JMESPath operators…
openhands-agent May 28, 2026
e3bbe16
docs: add qa-this label creation hint to qa-changes.mdx
openhands-agent May 28, 2026
c7dd78d
docs: add APPROVE/REQUEST_CHANGES/COMMENT guidance to automation prompt
openhands-agent May 28, 2026
9257bba
docs: fix team org link to point to organizations overview page
openhands-agent May 29, 2026
7a3fbe3
docs: add GitHub Action option alongside automation approach for code…
openhands-agent May 29, 2026
a7e1dd2
docs: add FIRST_TIMER exclusion to GH Action example for consistency
openhands-agent May 29, 2026
001427f
docs: replace inline GH Action YAMLs with links to example workflows
openhands-agent May 29, 2026
45fa00d
docs: add /codereview conversation trigger to code-review Quick Start
openhands-agent May 29, 2026
ff32092
docs: add /codereview skill trigger to automation prompt Step 4
openhands-agent May 29, 2026
84cf83b
docs: add bot account prerequisite and expand review_requested explan…
openhands-agent May 29, 2026
bc64dc9
Apply suggestion from @xingyaoww
xingyaoww May 29, 2026
6e1660e
fix: correct broken internal link to organizations overview page
openhands-agent May 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 85 additions & 13 deletions openhands/usage/automations/event-automations.mdx
Original file line number Diff line number Diff line change
@@ -1,20 +1,87 @@
---
title: Event-Based Automations

Check warning on line 2 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L2

Did you really mean 'Automations'?
description: Trigger automations from GitHub events or custom webhooks instead of cron schedules.

Check warning on line 3 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L3

Did you really mean 'automations'?

Check warning on line 3 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L3

Did you really mean 'cron'?
---

Event-based automations run when something happens—a PR is opened, an issue is commented on, or a webhook fires—instead of on a schedule. This is ideal for responsive workflows like auto-reviewing PRs, triaging issues, or reacting to external service events.

Check warning on line 6 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L6

Did you really mean 'automations'?

Check warning on line 6 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L6

Did you really mean 'triaging'?

## Prerequisites for GitHub Event Automations

Check warning on line 8 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L8

Did you really mean 'Automations'?

GitHub event automations require some one-time setup before events will flow. If any step is missing, automations will appear to work (manual triggers succeed) but GitHub events will silently never arrive.

Check warning on line 10 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L10

Did you really mean 'automations'?

Check warning on line 10 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L10

Did you really mean 'automations'?

### 1. Install the OpenHands GitHub App

The OpenHands GitHub App must be installed on the GitHub organization that owns the repositories you want to monitor. Install it from your [GitHub integration settings](/openhands/usage/cloud/github-installation). The app needs access to the repositories that will generate events.

### 2. Create an OpenHands Team Organization

If you're working with repositories owned by a GitHub organization (e.g., `myorg/my-repo`), you need an OpenHands **team organization** — not just a personal account. GitHub events for org repos are routed to team orgs, not personal orgs.

Check warning on line 18 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L18

Did you really mean 'repos'?

Check warning on line 18 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L18

Did you really mean 'orgs'?

Check warning on line 18 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L18

Did you really mean 'orgs'?

If you don't already have one, create a team organization — see [What Are Organizations](/openhands/usage/cloud/organizations/overview#what-are-organizations) for details and how to get started.

### 3. Claim Your GitHub Organization

<Warning>
**This is the most commonly missed step.** Without it, GitHub events have nowhere to be routed and will be silently dropped.
</Warning>

Your OpenHands team org must **claim** the GitHub organization to establish the link between GitHub webhooks and your OpenHands org. Claiming tells the event router: _"Events for repos in this GitHub org should go to this OpenHands team org."_

Check warning on line 28 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L28

Did you really mean 'repos'?

To claim a GitHub org:

1. Switch to your team org using the org switcher in the sidebar
2. Go to **Organization Settings**
3. In the **Git Conversation Routing** section, find your GitHub org
4. Click **Claim**

You must be an **Owner** of the OpenHands team org and have **admin access** to the GitHub org to complete the claim. See [Claiming Git Organizations](/openhands/usage/cloud/organizations/settings#claiming-git-organizations) for full details.

<Tip>
Each GitHub organization can only be claimed by one OpenHands team org. If another team has already claimed it, coordinate with them or contact support.
</Tip>

### 4. Create the Automation Under the Team Org

Make sure you are switched to the **team org** (not your personal org) when creating the automation. The automation must live in the same org that claimed the GitHub organization — otherwise events won't match.

### 5. (Optional) Add Service Accounts to the Team Org

If you're using a service account (like a bot account) to create or own automations, that account must be a **member of the team org**. Invite them from the [Organization Members](/openhands/usage/cloud/organizations/managing-members) page.

Check warning on line 49 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L49

Did you really mean 'automations'?

### Troubleshooting

If your automation doesn't trigger on GitHub events:

<AccordionGroup>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The troubleshooting accordion covers four causes of silent event failures but omits the first prerequisite: the GitHub App not being installed on the org. A user who skips step 1 and still completes step 3 (claiming) will find no matching entry here and will cycle through the other accordion items without resolution. Consider adding:

<Accordion title="GitHub App not installed on the org">
  The OpenHands GitHub App must be installed on the GitHub organization that owns
  your repositories. Go to [GitHub integration settings](/openhands/usage/cloud/github-installation)
  and verify it is installed with access to the relevant repos. See step 1 of
  the prerequisites above.
</Accordion>

<Accordion title="GitHub App not installed on the org">
The OpenHands GitHub App must be installed on the GitHub organization that owns your repositories. Go to [GitHub integration settings](/openhands/usage/cloud/github-installation) and verify it is installed with access to the relevant repos. Without this, no webhook events are sent to OpenHands.

Check warning on line 57 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L57

Did you really mean 'repos'?
</Accordion>
<Accordion title="GitHub org not claimed">
The most common cause. Go to **Organization Settings → Git Conversation Routing** and check if your GitHub org shows as claimed. If not, click **Claim**. See [Claiming Git Organizations](/openhands/usage/cloud/organizations/settings#claiming-git-organizations).
</Accordion>
<Accordion title="Automation in personal org instead of team org">
GitHub events for org repos are routed to the **team org** that claimed the GitHub org. If you created the automation under your personal org, events will never reach it. Switch to the team org and recreate the automation.

Check warning on line 63 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L63

Did you really mean 'repos'?
</Accordion>
<Accordion title="Event type or filter mismatch">
Double-check that the event type (e.g., `pull_request.labeled`) and filter expression match the action you're testing. Use wildcards like `pull_request.*` to match all actions during debugging.
</Accordion>
<Accordion title="Automation is disabled">
Verify the automation is enabled. You can check via the automations list or by asking OpenHands to list your automations.

Check warning on line 69 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L69

Did you really mean 'automations'?

Check warning on line 69 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L69

Did you really mean 'automations'?
</Accordion>
</AccordionGroup>

---

## Built-In vs. Custom Integrations

| Type | Setup | Best For |
|------|-------|----------|
| **Built-in (GitHub)** | None—just create the automation | PR reviews, issue triage, push-triggered tasks |
| **Built-in (GitHub)** | One-time org setup ([see above](#prerequisites-for-github-event-automations)), then create the automation | PR reviews, issue triage, push-triggered tasks |
| **Custom Webhooks** | Register webhook first, then create automation | Linear, Stripe, Slack, and other services |

## GitHub Events (Built-In)

GitHub is a built-in integration. Create automations that respond to GitHub events without any webhook setup.

Check warning on line 84 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L84

Did you really mean 'automations'?

### Example: Auto-Review PRs with a Specific Label

Expand Down Expand Up @@ -58,43 +125,48 @@

Filters let you narrow which events trigger your automation. They use [JMESPath expressions](https://jmespath.org/) to match fields in the event payload—so you can trigger only on specific labels, users, branches, or other conditions.

<Note>
OpenHands extends standard JMESPath with custom functions including `icontains` (case-insensitive string match) and `glob` (wildcard path matching). It also supports `!` (negation), `&&` (AND), and `||` (OR) as boolean operators. These extensions are not part of the [JMESPath specification](https://jmespath.org/specification.html).

Check warning on line 129 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L129

Did you really mean 'JMESPath'?

Check warning on line 129 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L129

Did you really mean 'JMESPath'?
</Note>

**Common filter patterns:**

```javascript
// Match a specific label
```
contains(pull_request.labels[].name, 'openhands')

// Case-insensitive mention in comment
icontains(comment.body, '@openhands')

// Match repos in your org
glob(repository.full_name, 'myorg/*')

// Push to main branch only
ref == 'refs/heads/main'

// Combine conditions
glob(repository.full_name, 'myorg/*') && contains(pull_request.labels[].name, 'bug')
```

- `contains(...)` — match a specific label
- `icontains(...)` — case-insensitive mention in a comment body
- `glob(...)` — match repos in your org with wildcards

Check warning on line 148 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L148

Did you really mean 'repos'?
- `==` — exact match (e.g., push to main branch only)
- `&&` — combine multiple conditions

---

## Custom Webhooks

For services beyond GitHub—like Linear, Stripe, or Slack—register a custom webhook first, then create automations that use it.

Check warning on line 156 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L156

Did you really mean 'automations'?

<Note>
**Two-phase workflow for custom webhooks:**

1. **Webhook registration (one-time setup)**: You execute the curl command yourself to register the webhook. This keeps your signing secrets secure—the agent provides the command but never handles your credentials directly.

2. **Automation creation (repeatable)**: Once the webhook is registered, the agent can create, update, and manage automations for that webhook source conversationally—no manual curl commands needed.

Check warning on line 163 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L163

Did you really mean 'automations'?
</Note>

### Walkthrough: Linear Integration

Check warning on line 166 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L166

Did you really mean 'Walkthrough'?

<Note>
This example walks through setting up a Linear webhook to auto-triage new issues using Automations in **[OpenHands Cloud](https://app.all-hands.dev)**.

Check warning on line 169 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L169

Did you really mean 'Automations'?
</Note>

#### Step 1: Get Your Webhook Secret from Linear
Expand Down Expand Up @@ -136,7 +208,7 @@
The response includes a `webhook_url` that you'll configure in Linear.

<Accordion title="Understanding event_key_expr">
The `event_key_expr` is a JMESPath expression that extracts the event type from incoming webhook payloads. This extracted value is what you match against in the automation's `on` field.

Check warning on line 211 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L211

Did you really mean 'JMESPath'?

For example, Linear sends payloads like:
```json
Expand All @@ -159,7 +231,7 @@

#### Step 4: Create the Automation

Now the webhook is registered, the agent can create automations for you end-to-end. Just describe what you want:

Check warning on line 234 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L234

Did you really mean 'automations'?

```
Create an event-based automation called "Triage Linear Issues" that triggers
Expand All @@ -171,7 +243,7 @@

The agent creates the automation with:
- **Source**: `linear` (your registered webhook)
- **Event**: `Issue` (Linear's event type)

Check warning on line 246 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L246

Did you really mean 'Linear's'?
- **Filter**: `action == 'create'`

### Custom Webhook Parameters
Expand All @@ -182,7 +254,7 @@
|-----------|----------|-------------|
| `name` | Yes | Human-readable name |
| `source` | Yes | Unique identifier (lowercase, alphanumeric with hyphens) |
| `event_key_expr` | No | JMESPath to extract event type (default: `type`) |

Check warning on line 257 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L257

Did you really mean 'JMESPath'?
| `signature_header` | No | Header containing HMAC signature (default: `X-Signature-256`) |
| `webhook_secret` | No | Signing secret—provide yours or let the system generate one |

Expand All @@ -190,18 +262,18 @@

These are example configurations for popular services. **Always verify with each service's webhook documentation**, as signature headers and payload formats may change.

| Service | Signature Header | Event Key |
|---------|-----------------|-----------|
| Linear | `Linear-Signature` | `type` |
| Stripe | `Stripe-Signature` | `type` |
| Slack | `X-Slack-Signature` | `type` |
| Twilio | `X-Twilio-Signature` | `type` |
| Service | Signature Header | Event Key | Notes |
|---------|-----------------|-----------|-------|
| Linear | `Linear-Signature` | `type` | |
| Stripe | `Stripe-Signature` | `type` | Uses a custom `t=timestamp,v1=signature` format — verify compatibility |
| Slack | `X-Slack-Signature` | `type` | |
| Twilio | `X-Twilio-Signature` | `type` | Uses HMAC-SHA1 of request URL + params — verify compatibility |

Check warning on line 270 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L270

Did you really mean 'Twilio'?

---

## Next Steps

New to automations? Start with the [Automations Overview](/openhands/usage/automations/overview) for the bigger picture, including cron-based scheduling and general concepts.

Check warning on line 276 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L276

Did you really mean 'automations'?

- [Automations Overview](/openhands/usage/automations/overview) — Cron-based automations and general concepts

Check warning on line 278 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L278

Did you really mean 'automations'?
- [Managing Automations](/openhands/usage/automations/managing-automations) — Update, disable, or delete automations

Check warning on line 279 in openhands/usage/automations/event-automations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/event-automations.mdx#L279

Did you really mean 'automations'?
2 changes: 1 addition & 1 deletion openhands/usage/automations/overview.mdx
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
---
title: Automations Overview

Check warning on line 2 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L2

Did you really mean 'Automations'?
description: Create scheduled tasks that run automatically in OpenHands.
---

Automations let you schedule AI-powered tasks that run automatically—daily reports, health checks, data syncs, and more. Each automation runs a full OpenHands conversation on your chosen schedule, with access to your LLM settings, stored secrets, and integrations.

Check warning on line 6 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L6

Did you really mean 'Automations'?

Your git provider credentials are automatically available—if you logged into OpenHands with GitHub, GitLab, or Bitbucket, that access is included by default.

## What Can Automations Do?

Check warning on line 10 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L10

Did you really mean 'Automations'?

- **Generate reports**: Daily standups, weekly summaries, or monthly metrics

Check warning on line 12 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L12

Did you really mean 'standups'?
- **Monitor systems**: Check API health, SSL certificates, or uptime
- **Sync data**: Pull from external APIs, update spreadsheets, or refresh dashboards
- **Maintain code**: Run dependency checks, security scans, or cleanup tasks
- **Send notifications**: Post updates to Slack, create GitHub issues, or send alerts

<Note>
Automations can only interact with services you've configured access to. For example, posting to Slack requires the [Slack MCP integration](/openhands/usage/settings/mcp-settings). Git providers you logged in with (GitHub, GitLab, Bitbucket) are automatically available.

Check warning on line 19 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L19

Did you really mean 'Automations'?
</Note>

## Two Types of Automations

Check warning on line 22 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L22

Did you really mean 'Automations'?

When you ask OpenHands to create an automation, you can choose between:

Expand All @@ -38,7 +38,7 @@
our open GitHub issues, then posts the summary to #engineering on Slack.
```

For plugin-based automations, mention the plugin:

Check warning on line 41 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L41

Did you really mean 'automations'?

```
Create an automation using the code-review plugin that runs daily
Expand All @@ -61,7 +61,7 @@
3. The conversation is saved so you can review it later
4. You can even continue the conversation if needed

Automations are user-scoped—each automation and its runs belong to you. Conversations created by your automations automatically appear in your conversations list, just like any other conversation you start.

Check warning on line 64 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L64

Did you really mean 'Automations'?

Check warning on line 64 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L64

Did you really mean 'automations'?

Your automation has access to everything a normal OpenHands conversation does: terminal, file editing, your configured LLM, stored secrets, and MCP integrations. Git provider tokens from your login (GitHub, GitLab, or Bitbucket) are automatically included.

Expand All @@ -70,7 +70,7 @@
**Prerequisites**

- **Configured LLM** in your settings
- **Stored secrets** (optional) for any additional API keys your automations need (e.g., Slack tokens)

Check warning on line 73 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L73

Did you really mean 'automations'?

Open a new conversation in OpenHands and ask it to create an automation:

Expand All @@ -79,7 +79,7 @@
our open GitHub issues, then posts to #engineering on Slack.
```

Once you create an automation, you can view them by clicking on the "Automations" icon on the left-hand navigation.

Check warning on line 82 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L82

Did you really mean 'Automations'?

You can also ask OpenHands to list [existing automations, enable/disable them, or trigger manual runs](/openhands/usage/automations/managing-automations).

Expand All @@ -87,7 +87,7 @@

---

## Use Case Automations

Check warning on line 90 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L90

Did you really mean 'Automations'?

{/* BEGIN:use-case-automations — auto-generated from use-case frontmatter */}

Expand Down Expand Up @@ -118,7 +118,7 @@
<Card
title="Automated QA Testing"
icon="vial"
href="/openhands/usage/use-cases/qa-changes"
href="/openhands/usage/use-cases/qa-changes#automate-this"
>
Functionally test PR changes by exercising the software as a real user would.
</Card>
Expand Down Expand Up @@ -257,5 +257,5 @@
## Next Steps

- [Creating Automations](/openhands/usage/automations/creating-automations) — More details on writing prompts
- [Managing Automations](/openhands/usage/automations/managing-automations) — Update, disable, or delete automations

Check warning on line 260 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L260

Did you really mean 'automations'?
- [Use Cases Overview](/openhands/usage/use-cases/overview) — Explore the full use case guides behind these automations

Check warning on line 261 in openhands/usage/automations/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/automations/overview.mdx#L261

Did you really mean 'automations'?
182 changes: 171 additions & 11 deletions openhands/usage/use-cases/code-review.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,27 @@
</Step>
</Steps>

### In a Conversation

You can also trigger a code review manually in any OpenHands conversation. First, install the skill:

```
/add-skill https://github.com/OpenHands/extensions/tree/main/skills/code-review
```

Then invoke it:

```
/codereview
```

The agent will ask for the PR to review, or you can provide context directly:

```
/codereview — Please review PR #123 on my-org/my-repo.
Focus on the new authentication middleware.
```

## Composite Action

<Note>
Expand Down Expand Up @@ -130,11 +151,11 @@
| `use-sub-agents` | Enable sub-agent delegation for file-level reviews in `openhands` mode. Ignored in ACP mode. | No | `'false'` |
| `extensions-repo` | Extensions repository (owner/repo) | No | `OpenHands/extensions` |
| `extensions-version` | Git ref for extensions (tag, branch, or commit SHA) | No | `main` |
| `openhands-sdk-package` | Package spec passed to `uv --with`; override only when pinning a specific SDK build for testing or rollout control | No | `openhands-sdk` |

Check warning on line 154 in openhands/usage/use-cases/code-review.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/use-cases/code-review.mdx#L154

Did you really mean 'rollout'?
| `llm-api-key` | LLM API key. Required when `agent-kind` is `openhands`; ignored in ACP mode. | Yes for OpenHands mode | - |
| `github-token` | GitHub token for API access | Yes | - |
| `lmnr-api-key` | Laminar API key for observability | No | `''` |
| `enable-uv-cache` | Enable setup-uv's GitHub Actions cache for Python deps. Default `false` for security. | No | `'false'` |

Check warning on line 158 in openhands/usage/use-cases/code-review.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/use-cases/code-review.mdx#L158

Did you really mean 'deps'?

<Note>
Use `extensions-version` to pin to a specific version tag (e.g., `v1.0.0`) for production stability, or use `main` to always get the latest features. The extensions repository contains the PR review plugin scripts.
Expand All @@ -148,13 +169,13 @@
authentication, and tool execution.

Use ACP mode when your runner already has an authenticated ACP CLI available.
The action does not install ACP CLIs for you; install and authenticate the ACP

Check warning on line 172 in openhands/usage/use-cases/code-review.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/use-cases/code-review.mdx#L172

Did you really mean 'CLIs'?
server in workflow steps before invoking the PR review action.

<Warning>
ACP mode is experimental. Use it on trusted self-hosted runners where you
control the installed ACP command and the authentication material. Do not expose
subscription credentials to workflows that run untrusted pull request code.

Check warning on line 178 in openhands/usage/use-cases/code-review.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/use-cases/code-review.mdx#L178

Did you really mean 'untrusted'?
</Warning>

### Codex ACP Example
Expand Down Expand Up @@ -326,7 +347,7 @@
The workflow uses `pull_request_target` so the code review agent can work properly for PRs from forks. Only users with write access can trigger reviews via labels or reviewer requests.

<Warning>
**Potential Risk**: A malicious contributor could submit a PR from a fork containing code designed to exfiltrate your `LLM_API_KEY` when the review agent analyzes their code.

Check warning on line 350 in openhands/usage/use-cases/code-review.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/use-cases/code-review.mdx#L350

Did you really mean 'exfiltrate'?

To mitigate this, the PR review workflow passes API keys as [SDK secrets](/sdk/guides/secrets) rather than environment variables, which prevents the agent from directly accessing these credentials during code execution.
</Warning>
Expand All @@ -340,7 +361,7 @@
| [#1927](https://github.com/OpenHands/software-agent-sdk/pull/1927#pullrequestreview-3767493657) | Composite GitHub Action refactor | Comprehensive review with 🔴 Critical, 🟠 Important, and 🟡 Suggestion labels |
| [#1916](https://github.com/OpenHands/software-agent-sdk/pull/1916#pullrequestreview-3758297071) | Add example for reconstructing messages | Critical issues flagged with clear explanations |
| [#1904](https://github.com/OpenHands/software-agent-sdk/pull/1904#pullrequestreview-3751821740) | Update code-review skill guidelines | APPROVED review highlighting key strengths |
| [#1889](https://github.com/OpenHands/software-agent-sdk/pull/1889#pullrequestreview-3747576245) | Fix tmux race condition | Technical review of concurrency fix with dual-lock strategy analysis |

Check warning on line 364 in openhands/usage/use-cases/code-review.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/use-cases/code-review.mdx#L364

Did you really mean 'tmux'?

## Troubleshooting

Expand All @@ -367,23 +388,162 @@

## Automate This

You can schedule daily code reviews using [OpenHands Automations](/openhands/usage/automations/overview).
Copy this prompt into a new conversation to set one up:
There are two ways to automate PR reviews with OpenHands: as a **GitHub Action** (per-repo) or as an **OpenHands Automation** (org-wide, event-driven). Choose the approach that fits your needs, or use both.

### Option A: GitHub Action (Per-Repo)

Use the [pr-review plugin](https://github.com/OpenHands/extensions/tree/main/plugins/pr-review) as a GitHub Actions workflow. Copy the [example workflow](https://github.com/OpenHands/extensions/blob/main/plugins/pr-review/workflows/pr-review-by-openhands.yml) into `.github/workflows/pr-review.yml` in your repository, add your `LLM_API_KEY` to **Settings → Secrets and variables → Actions**, and customize the trigger conditions and model as needed.

See the [action.yml](https://github.com/OpenHands/extensions/blob/main/plugins/pr-review/action.yml) for all available inputs (`llm-model`, `llm-base-url`, `use-sub-agents`, `require-evidence`, and more).

**When to use this:** You want per-repo control, need to integrate with existing CI checks, or want to pin specific action versions per repository.

### Option B: OpenHands Automation (Org-Wide)

<Warning>
Before setting up an event-driven automation, complete the one-time [prerequisites for GitHub event automations](/openhands/usage/automations/event-automations#prerequisites-for-github-event-automations) — install the GitHub App, create a team org, and claim your GitHub organization. Without these steps, GitHub events will silently never arrive.
</Warning>

[OpenHands Automations](/openhands/usage/automations/overview) is an event-triggered automation system that replaces per-repo GitHub Actions workflows. You define the trigger once and it covers all repositories matching your filter — no per-repo workflow files needed. It also leverages the full OpenHands runtime (browser, tools, sandbox), which GitHub Actions cannot.

**When to use this:** You want a single configuration that covers all repos in your org, or you need the full OpenHands runtime for more advanced review workflows.

Check warning on line 409 in openhands/usage/use-cases/code-review.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/use-cases/code-review.mdx#L409

Did you really mean 'repos'?

#### Prerequisites: Bot Account

For org-level automations, you should create a dedicated **bot account** (a separate GitHub user) and add it to your [OpenHands organization](/openhands/usage/cloud/organizations/overview). The bot account is the identity that will approve pull requests, request changes, and post review comments — keeping automated actions separate from human activity. Team members can then request this bot as a reviewer to trigger on-demand reviews.

Check warning on line 413 in openhands/usage/use-cases/code-review.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/use-cases/code-review.mdx#L413

Did you really mean 'automations'?

#### Setup: Create the Automation via Prompt

Log in to [OpenHands Cloud](https://app.all-hands.dev) as your bot account (or under your team org) and send the following prompt in a new conversation. Replace the placeholders with your values:

- `YOUR_ORG` — your GitHub organization name (e.g., `mycompany`)
- `YOUR_BOT_LOGIN` — the GitHub username of your bot account (e.g., `mycompany-bot`)

````
Create an OpenHands Cloud automation using the Plugin Preset with the following configuration:

**Name:** PR Review: YOUR_ORG/* (ready for review, review-this, or reviewer requested)

**Plugin:** github:OpenHands/extensions (repo_path: plugins/pr-review)

**Trigger events:**
- pull_request.opened
- pull_request.ready_for_review
- pull_request.review_requested
- pull_request.labeled

**Filter:**
```
glob(repository.full_name, 'YOUR_ORG/*') && (
label.name == 'review-this'
|| requested_reviewer.login == 'YOUR_BOT_LOGIN'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requested_reviewer is only populated for individual reviewer requests. When a team is requested as reviewer, the payload uses requested_team instead — so this filter branch will silently not match team-based review requests.

If the bot can be requested via a team, add:

|| requested_team.slug == 'YOUR_TEAM_SLUG'

|| (!label && !requested_reviewer
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The !label && !requested_reviewer condition relies on JMESPath treating absent fields as null (and !null evaluating to true). This is why the branch fires for opened and ready_for_review events (which don't have label or requested_reviewer in the payload) but not for labeled or review_requested events.

This is correct behavior, but it's non-obvious to users trying to customize the filter. A <Note> below the filter block explaining this semantics would prevent a lot of head-scratching.

&& pull_request.author_association != 'FIRST_TIME_CONTRIBUTOR'
&& pull_request.author_association != 'FIRST_TIMER'
&& pull_request.author_association != 'NONE'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub's author_association field has more values than the two excluded here. The complete low-trust set is:

  • NONE — no prior association with the repo ✅ excluded
  • FIRST_TIME_CONTRIBUTOR — first PR to this repo ✅ excluded
  • FIRST_TIMER — first PR to any public GitHub repo ❌ missing

FIRST_TIMER contributors will bypass this guard and trigger automatic reviews. Add && pull_request.author_association != 'FIRST_TIMER' or document the intentional inclusion.

&& !pull_request.draft)
)
```

**Timeout:** 600 seconds

**Prompt (use this exactly):**
```
Create an automation called "Daily Code Review" that runs every weekday at 9 AM.
Before starting the code review, complete these steps in order:

Step 1 — Build the session URL.
Run this in terminal:
SESSION_URL="${AUTOMATION_SESSION_URL:-${AUTOMATION_API_URL:-https://app.all-hands.dev}}"
echo "SESSION_URL=${SESSION_URL}"

Step 2 — Extract PR info from the event payload:
PR_NUMBER=$(echo "$AUTOMATION_EVENT_PAYLOAD" | python3 -c "import sys,json; p=json.load(sys.stdin); print(p['pull_request']['number'])")
REPO=$(echo "$AUTOMATION_EVENT_PAYLOAD" | python3 -c "import sys,json; p=json.load(sys.stdin); print(p['repository']['full_name'])")

Step 3 — Post a progress comment and save the comment ID:
COMMENT_ID=$(curl -s -X POST \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$REPO/issues/$PR_NUMBER/comments" \
-d "{\"body\": \"🔍 **Review in progress…**\\n\\nWe are performing the review through OpenHands Cloud Automation. You can log in and [view the conversation here](${SESSION_URL}).\"}" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")

Step 4 — /codereview
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/codereview is a slash command dispatched in interactive conversation context — it isn't available to an automation agent that receives this prompt as plain text. The prose instructions below this label are complete and correct, but readers may copy-paste /codereview into their own automation prompts expecting it to work as a slash command and be confused when it doesn't.

Suggest renaming the annotation:

Step 4 — Run the code review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/codereview is a slash command dispatched in interactive conversation context — it isn't available to an automation agent that receives this prompt as plain text. The prose instructions below this label are complete and correct, but readers may copy-paste /codereview into their own automation prompts expecting it to work as a slash command and be confused when it doesn't.

Suggest renaming the annotation:

Step 4 — Run the code review

Review the pull request using the pr-review plugin. Post a comprehensive code review on GitHub with inline comments on specific changed lines where appropriate, and a concise overall summary. Avoid duplicating existing unresolved review comments.

When submitting the review, choose the appropriate event type:
- Use "event": "APPROVE" when the PR is ready to merge with no blocking issues (minor suggestions are fine)
- Use "event": "REQUEST_CHANGES" when there are blocking issues that must be fixed before merging
- Use "event": "COMMENT" only when you need more information or are providing an informational review without a clear verdict

At the end of the top-level review body include exactly:
_This review was generated by an AI agent (OpenHands) on behalf of the user through OpenHands Automation. [View conversation](${SESSION_URL})_

Step 5 — After the review is posted, update the progress comment:
curl -s -X PATCH \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$REPO/issues/comments/$COMMENT_ID" \
-d "{\"body\": \"✅ **Review complete.**\\n\\nThis review was performed through OpenHands Cloud Automation. You can log in and [view the conversation here](${SESSION_URL}).\"}"
```
````

<Note>
**Team review requests:** The `requested_reviewer` field is only populated for individual reviewer requests. When a *team* is requested as reviewer, GitHub uses `requested_team` instead. To also match team requests, add `|| requested_team.slug == 'YOUR_TEAM_SLUG'` to the filter.

**How `!label` works:** JMESPath treats absent fields as `null`, and `!null` evaluates to `true`. This means the third branch fires for `opened` and `ready_for_review` events (which have no `label` or `requested_reviewer` in the payload), while correctly staying silent for `labeled` and `review_requested` events where those fields are set.

Check warning on line 494 in openhands/usage/use-cases/code-review.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/use-cases/code-review.mdx#L494

Did you really mean 'JMESPath'?
</Note>

#### What This Produces

When the automation is created and a qualifying PR event occurs, the bot will:

It should:
1. Find all open PRs that have no reviews yet
2. For each PR, review the diff for bugs, style issues, and security concerns
3. Post a summary of findings as a comment on each PR
1. **Post a progress comment** on the PR: "🔍 Review in progress…" with a link to the live conversation
2. **Run the pr-review plugin** which analyzes the diff and posts a structured code review with inline comments — approving clean PRs, requesting changes when there are blocking issues, or leaving an informational comment when the verdict is unclear
3. **Update the progress comment** to "✅ Review complete." with the conversation link

Learn more at https://docs.openhands.dev/openhands/usage/use-cases/code-review
The automation triggers on four conditions:
- **`opened`** — when a new non-draft PR is created (for established contributors only)
- **`ready_for_review`** — when a draft PR is marked ready (for established contributors only)
- **`review_requested`** — when your bot account is requested as a reviewer. This is the primary way team members trigger an on-demand review — they simply request the bot from the PR's "Reviewers" sidebar. The bot then posts its review under its own GitHub identity, so approvals and change requests come from a clear, dedicated account.

Check warning on line 508 in openhands/usage/use-cases/code-review.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/use-cases/code-review.mdx#L508

Did you really mean 'PR's'?
- **`labeled`** — when the `review-this` label is added to any PR

The automation does not re-run when new commits are pushed to an existing PR (`pull_request.synchronize` is intentionally excluded to avoid noisy re-reviews). To request a follow-up review after addressing feedback, re-add the `review-this` label or re-request the reviewer.

<Note>
The `$AUTOMATION_SESSION_URL` variable is injected by the automation runtime and resolves to a direct link to the conversation (e.g., `https://app.all-hands.dev/conversations/{uuid}`). The prompt includes fallbacks (`$AUTOMATION_API_URL`, then the default app URL) for environments where the variable is not yet available.

The `$AUTOMATION_EVENT_PAYLOAD` variable contains the full GitHub webhook event as JSON. The `$GITHUB_TOKEN` (from the configured GitHub integration) is also automatically available. No additional configuration is needed for any of these variables.
</Note>

#### Single-Repo vs Org-Wide

The prompt above uses `glob(repository.full_name, 'YOUR_ORG/*')` to cover **all repos** in your org. To target a single repo instead, replace the filter's first condition:

Check warning on line 521 in openhands/usage/use-cases/code-review.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/use-cases/code-review.mdx#L521

Did you really mean 'repos'?

```
repository.full_name == 'YOUR_ORG/YOUR_REPO' && (
label.name == 'review-this'
|| requested_reviewer.login == 'YOUR_BOT_LOGIN'
|| (!label && !requested_reviewer
&& pull_request.author_association != 'FIRST_TIME_CONTRIBUTOR'
&& pull_request.author_association != 'FIRST_TIMER'
&& pull_request.author_association != 'NONE'
&& !pull_request.draft)
)
```

For inline review comments on every push, use the
[pr-review plugin](https://github.com/OpenHands/extensions/tree/main/plugins/pr-review)
as a GitHub Action instead.
<Note>
The `review-this` label and `requested_reviewer` branches do not exclude draft PRs — labeling a draft or requesting the bot on a draft will still fire the automation. This is intentional: explicit review requests should be honored regardless of draft status.
</Note>

#### Testing

After creating the automation:

1. Add the `review-this` label to any open PR in a covered repo — this is the most reliable test since it works regardless of author history (you may need to [create the label](https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels#creating-a-label) in your repo first if it doesn't exist)
2. Alternatively, request your bot as a reviewer on any PR, or open a new non-draft PR (note: the auto-trigger on `opened` requires the PR author to already have contributor history in that specific repo — `FIRST_TIME_CONTRIBUTOR`, `FIRST_TIMER`, and `NONE` associations are excluded)
3. Watch for the "🔍 Review in progress…" comment — it should appear within a few seconds
4. The full review will typically follow within a few minutes, depending on PR size

## Related Resources

Expand Down
Loading
Loading