Skip to content

GitHub pull_request.labeled event did not trigger automation run #107

@all-hands-bot

Description

@all-hands-bot

Summary

A GitHub event-triggered automation configured for OpenHands/software-agent-sdk did not create any automation runs when a test PR was labeled with oh-cloud-review.

The GitHub label events were successfully emitted by GitHub, and local inspection of the automation service code indicates the automation trigger/filter should match a representative pull_request.labeled payload. However, the automation service shows zero runs, which suggests the event is not reaching the automation service or is being routed to a different OpenHands org before trigger matching.

Test setup

Automation created via the plugin preset:

  • Automation name: PR Review: software-agent-sdk oh-cloud-review
  • Automation ID: 5938f464-b585-429f-a95a-8f0e12a3a02c
  • Automation org ID: 8e0a0d06-afbe-41b0-ac49-ebfbc774580e
  • Source: github
  • Plugin: github:OpenHands/extensions, repo_path: plugins/pr-review, ref: main
  • Target repo: OpenHands/software-agent-sdk
  • Test PR: Test oh-cloud-review automation trigger software-agent-sdk#3205
  • Label: oh-cloud-review

Original trigger:

{
  "type": "event",
  "source": "github",
  "on": "pull_request.labeled",
  "filter": "repository.full_name == 'OpenHands/software-agent-sdk' && label.name == 'oh-cloud-review'"
}

After debugging, the trigger was broadened to include issues.labeled as well, in case PR label events were normalized that way:

{
  "type": "event",
  "source": "github",
  "on": ["pull_request.labeled", "issues.labeled"],
  "filter": "repository.full_name == 'OpenHands/software-agent-sdk' && label.name == 'oh-cloud-review' && (pull_request.number != null || issue.pull_request.url != null)"
}

What happened

  1. Created a temporary PR in OpenHands/software-agent-sdk:
  2. Added the label oh-cloud-review.
  3. Re-applied the label multiple times to emit fresh label events.
  4. Polled the automation runs endpoint repeatedly:
GET /api/automation/v1/5938f464-b585-429f-a95a-8f0e12a3a02c/runs?limit=10

Response remained:

{
  "runs": [],
  "total": 0
}

The automation detail also still showed no visible run activity.

Evidence that GitHub emitted the label event

GitHub issue events for PR #3205 showed label activity, including:

labeled    2026-05-11T15:24:55Z    oh-cloud-review    all-hands-bot
unlabeled  2026-05-11T15:30:18Z    oh-cloud-review    all-hands-bot
labeled    2026-05-11T15:30:22Z    oh-cloud-review    all-hands-bot

GitHub repo events also showed PullRequestEvent entries for PR #3205 with action=labeled and payload keys similar to:

['action', 'number', 'pull_request', 'label', 'labels']

So this does not look like a GitHub-side label operation failure.

Evidence that trigger matching should work

I cloned OpenHands/automation and inspected:

  • openhands/automation/event_router.py
  • openhands/automation/event_schemas/github.py
  • openhands/automation/trigger_matcher.py
  • openhands/automation/filter_eval.py
  • openhands/automation/utils/webhook.py

A representative payload for the observed event parses as:

event_key = pull_request.labeled

and matches both the original trigger and the broadened trigger locally:

from openhands.automation.event_schemas import parse_event
from openhands.automation.trigger_matcher import matches_trigger
from openhands.automation.schemas import EventTrigger

payload = {
    "action": "labeled",
    "number": 3205,
    "label": {"name": "oh-cloud-review"},
    "pull_request": {
        "number": 3205,
        "title": "Test PR",
        "state": "open",
        "draft": False,
        "merged": False,
        "base": {"ref": "main", "sha": "a"},
        "head": {"ref": "test", "sha": "b"},
        "labels": [{"name": "oh-cloud-review"}],
        "user": {"id": 1, "login": "u", "type": "User"},
    },
    "repository": {
        "id": 1,
        "name": "software-agent-sdk",
        "full_name": "OpenHands/software-agent-sdk",
        "private": False,
        "owner": {"login": "OpenHands", "type": "Organization", "id": 2},
    },
    "sender": {"id": 182006032, "login": "all-hands-bot", "type": "User"},
}

event = parse_event("github", payload)
assert event.event_key == "pull_request.labeled"

trigger = EventTrigger.model_validate({
    "type": "event",
    "source": "github",
    "on": "pull_request.labeled",
    "filter": "repository.full_name == 'OpenHands/software-agent-sdk' && label.name == 'oh-cloud-review'",
})

assert matches_trigger(trigger, "github", event.event_key, payload) is True

Therefore the most likely failure is upstream of matches_trigger().

Relevant implementation path

From OpenHands/OpenHands, GitHub webhooks are received at:

enterprise/server/routes/integration/github.py

The route only forwards to the automation service when:

if AUTOMATION_EVENT_FORWARDING_ENABLED:
    background_tasks.add_task(
        automation_event_service.forward_event,
        provider=ProviderType.GITHUB,
        payload=payload_data,
        installation_id=installation_id,
    )

The forwarding service is:

enterprise/server/services/automation_event_service.py

The forwarding path:

  1. Extracts owner info from payload.repository.owner.login.
  2. Resolves the GitHub owner to an OpenHands org via OrgGitClaim.
  3. For org repos, if the GitHub org is not claimed, it skips forwarding.
  4. If resolved, it POSTs to:
{AUTOMATION_SERVICE_URL}/v1/events/{org_id}/{provider}

with an internal HMAC signature using AUTOMATION_WEBHOOK_SECRET.

In OpenHands/automation, the event is then received at:

/api/automation/v1/events/{org_id}/github

Implemented in:

openhands/automation/event_router.py

Suspected causes

1. Event forwarding may be disabled or misconfigured in the OpenHands server

The server-side route only forwards if:

AUTOMATION_EVENT_FORWARDING_ENABLED=true
AUTOMATION_SERVICE_URL is configured
AUTOMATION_WEBHOOK_SECRET is configured

The chart defaults appear to have forwarding disabled:

automationService:
  url: ""
  eventForwardingEnabled: false

If production has not overridden these, GitHub webhooks can still be processed by the normal GitHub integration, but automations will never see them.

2. github/openhands may not be claimed by the OpenHands org that owns the automation

The automation belongs to OpenHands org:

8e0a0d06-afbe-41b0-ac49-ebfbc774580e

For org-owned repos, forwarding requires an OrgGitClaim mapping roughly equivalent to:

provider = github
git_organization = openhands
org_id = 8e0a0d06-afbe-41b0-ac49-ebfbc774580e

If the claim is missing, the forwarding code skips the event.

If the claim exists but points to another OpenHands org, the event will be forwarded to that org and the automation above will not see it.

I tried to query:

GET /api/organizations/8e0a0d06-afbe-41b0-ac49-ebfbc774580e/git-claims

but my token received:

403 Requires manage_org_claims permission

so I could not verify the claim.

3. Stale negative Redis cache could cause forwarding to continue skipping events

The forwarding code caches negative org-claim resolution results for one hour:

automation:org_claim:github:openhands = none
TTL = 3600 seconds

If the first test happened before github/openhands was claimed, subsequent tests may continue to skip forwarding until the cache expires or is cleared.

4. GitHub App delivery/subscription issue

The GitHub App should be checked for a pull_request webhook delivery for PR #3205, action labeled, and whether /integration/github/events returned 200.

The GitHub App manifest in OpenHands-Cloud appears to subscribe to:

[
  "issue_comment",
  "pull_request",
  "pull_request_review_comment"
]

so pull_request.labeled should be included, but the actual installed app delivery logs are the source of truth.

5. Background task may not run if normal GitHub handling raises before response

The GitHub route adds forwarding as a FastAPI background task, then awaits normal resolver handling:

background_tasks.add_task(...)
await github_manager.receive_message(message)

If github_manager.receive_message() raises, the route returns 400 and the background task may not execute. This seems less likely for a plain pull_request.labeled event, but logs should confirm.

Small implementation observation

last_triggered_at may not be updated for event-triggered automations.

Manual/cron dispatch uses create_pending_run(), which updates Automation.last_triggered_at.

Event dispatch uses create_automation_run() in:

openhands/automation/utils/webhook.py

That creates an AutomationRun, but does not update Automation.last_triggered_at.

So last_triggered_at: null alone is not proof of no event match. In this case, however, runs: [] confirms no run was created.

Suggested debugging steps

Could someone with production access check the following around the label timestamps for PR #3205?

  1. OpenHands server env:
AUTOMATION_EVENT_FORWARDING_ENABLED
AUTOMATION_SERVICE_URL
AUTOMATION_WEBHOOK_SECRET
  1. Org claim:
github / openhands -> 8e0a0d06-afbe-41b0-ac49-ebfbc774580e
  1. Redis cache key:
automation:org_claim:github:openhands
  1. GitHub App delivery logs for:
repo: OpenHands/software-agent-sdk
PR: #3205
event: pull_request
action: labeled
label: oh-cloud-review
  1. OpenHands server logs for:
[AutomationEventService] Forwarded github event to org ...
[AutomationEventService] github org OpenHands not claimed ...
[AutomationEventService] Automation service returned ...
Error processing GitHub event
  1. Automation service logs for:
Received github event: key=pull_request.labeled
Event matched 1/... automations

Expected behavior

Adding oh-cloud-review to a PR in OpenHands/software-agent-sdk should create a pending automation run for the configured automation.

Actual behavior

No run was created:

{
  "runs": [],
  "total": 0
}

Impact

GitHub-event-triggered automations may silently fail for org-owned repositories if forwarding is not enabled/configured, org claims are missing/misrouted, or negative claim results are cached.


This issue was created by an AI agent (OpenHands) on behalf of the user.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions