Implementation:OpenHands OpenHands GithubManager Receive Message
| Knowledge Sources | |
|---|---|
| Domains | Platform_Integration, GitHub_API |
| Last Updated | 2026-02-11 21:00 GMT |
Overview
Concrete tool for receiving and processing incoming GitHub webhook payloads provided by the OpenHands enterprise integration layer.
Description
GithubManager.receive_message is the primary entry point for handling GitHub webhook events within the OpenHands platform. When a GitHub webhook fires (e.g., a new issue comment mentioning the bot), this method orchestrates the full reception pipeline: it triggers data collection on the payload, checks whether the sender has permission and whether a resolver job is warranted, creates a typed view object from the raw payload, sends an acknowledgment reaction back to GitHub, and starts the resolver job.
The method belongs to the GithubManager class, which inherits from the base Manager interface and is responsible for all GitHub-specific integration logic. It uses a TokenManager to handle GitHub App installation tokens and a GitHubDataCollector for telemetry and analytics.
Usage
This method is invoked by the webhook routing layer whenever an incoming HTTP request from GitHub is validated and deserialized into a Message object. It should not be called directly by application code outside the integration layer.
Typical invocation flow:
- The webhook HTTP handler receives a POST request from GitHub.
- The request is validated (signature check) and deserialized into a Message object.
- receive_message is called with this Message.
- The method orchestrates permission checks, view creation, acknowledgment, and job dispatch.
Code Reference
Source Location
- Repository: OpenHands
- File:
enterprise/integrations/github/github_manager.py - Lines: L165-197
Signature
async def receive_message(self, message: Message) -> None:
Import
from integrations.github.github_manager import GithubManager
Class Context
class GithubManager(Manager):
def __init__(
self,
token_manager: TokenManager,
data_collector: GitHubDataCollector,
) -> None:
...
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| message | Message |
Yes | dict (the raw payload body), and ephemeral: bool (whether the message should be treated as transient).
|
Outputs
| Name | Type | Description |
|---|---|---|
| (none) | None |
The method returns nothing. It produces side effects: triggers data collection, performs a permission check via is_job_requested, creates a ResolverViewInterface via the factory, adds an "eyes" reaction as acknowledgment, and starts the resolver job.
|
Side Effects
The method produces the following ordered side effects:
- Data collection -- Telemetry and analytics data are recorded for the incoming event.
- Permission check -- Calls
is_job_requested(message)to verify the sender has write access and the event qualifies for processing. If this returnsFalse, execution stops. - View creation -- Calls the factory to produce a typed
ResolverViewInterface(e.g.,GithubIssue,GithubPRComment) from the raw payload. - Acknowledgment -- Calls
_add_reaction(github_view, "eyes", installation_token)to add an eyes emoji to the originating issue or comment. - Job start -- Dispatches the resolver job to the async processing pipeline.
Usage Examples
Basic Usage
from integrations.github.github_manager import GithubManager
from integrations.models import Message, SourceType
# Construct the manager (typically done at application startup)
manager = GithubManager(
token_manager=token_manager,
data_collector=data_collector,
)
# Create a Message from a webhook payload
message = Message(
source=SourceType.GITHUB,
message=webhook_payload_dict,
ephemeral=False,
)
# Process the webhook event
await manager.receive_message(message)
Integration with Webhook Handler
from fastapi import Request
@app.post("/webhooks/github")
async def handle_github_webhook(request: Request):
payload = await request.json()
message = Message(
source=SourceType.GITHUB,
message=payload,
ephemeral=False,
)
await github_manager.receive_message(message)
return {"status": "accepted"}