GitHub Integration
Connect GitHub repositories to Mopheus via webhooks. Receive push, PR, and issue events, sync git entities to tickets, and let agents work with your code.
GitHub Integration
The GitHub integration connects your GitHub repositories to Mopheus through webhooks. When events occur in GitHub (push, pull request, issue, workflow run, etc.), Mopheus receives the webhook payload and dispatches it to a job for processing. You can also register repositories so agents can clone and work with your code.
Prerequisites
- A Mopheus workspace with the Git feature flag enabled (Settings → Features)
- A GitHub repository with admin access to configure webhooks
- The Mopheus server URL must be publicly accessible (GitHub needs to reach your webhook endpoint)
- Git credentials configured on the host machine — either SSH keys (
~/.ssh/id_*) or an HTTPS credential helper, so the daemon can pull and push - Git commit identity configured in the user's Mopheus profile (Settings → Profile) — used as the commit author when agents push code
Setup
1. Enable the Git Feature
The Git integration is gated behind a feature flag. An admin must enable it:
- Go to Admin → Features
- Find the Git feature and set it to Enabled (or Selected to whitelist specific workspaces)
2. Register Your Repository
In your workspace's Settings → Repos, click Add Repository:
| Field | Description |
|---|---|
| URL | The HTTPS or SSH URL of your GitHub repository (e.g. https://github.com/owner/repo) |
| Project (optional) | Scope the repo to a specific project |
| Provider | Auto-detected from URL. Can be overridden to github, gitlab, or gitea |
| CLI Binary (optional) | Override the default CLI (gh for GitHub) |
3. Create a Job and Webhook Trigger
- Go to Jobs and click Create Job
- Give the job a name and configure its action (the processing logic)
- In the job detail page, go to the Webhook tab and click Add Trigger
- Optionally set a Signing Secret for HMAC-SHA256 signature verification
- Optionally add Event Filters to only receive specific events (e.g.
pull_requestwith actionsopened,closed) - Copy the Webhook URL displayed on the page
4. Configure the Webhook in GitHub
- Go to your GitHub repository → Settings → Webhooks → Add webhook
- Paste the Mopheus webhook URL in the Payload URL field
- Set Content type to
application/json - If you set a signing secret in Mopheus, enter the same value in the Secret field
- Select which events to send:
- Just the push event — for push-only triggers
- Let me select individual events — for fine-grained control (recommended)
- Send me everything — for broad automation
- Click Add webhook
How It Works
Webhook Processing Flow
GitHub sends webhook POST
│
▼
Mopheus receives at /api/v1/webhooks/jobs/{token}
│
├─ Rate limiting (IP + token)
├─ Token lookup → find trigger
├─ Trigger enabled check
├─ Body size check (10 MiB max)
├─ Signature verification (if secret configured)
├─ Deduplication (30s window)
│
▼
Event type extracted from X-GitHub-Event header
│
▼
Payload enriched with _eventType metadata
│
▼
Job dispatched → agent or action processes the eventEvent Normalization
GitHub events are normalized into a {provider}.{event}.{action} format:
| GitHub Header | Normalized Event |
|---|---|
X-GitHub-Event: push | github.push |
X-GitHub-Event: pull_request + action: opened | github.pull_request.opened |
X-GitHub-Event: workflow_run + action: completed | github.workflow_run.completed |
X-GitHub-Event: issues + action: closed | github.issues.closed |
Event Filters
When creating a webhook trigger, you can add up to 5 event filters. Each filter has:
- Event: The event name (e.g.
pull_request,push,issues) - Actions (optional): A list of actions to match (e.g.
opened,closed,synchronize)
If no filters are set, all events pass through. If filters are set, the incoming event must match at least one filter's event name, and if that filter has actions, the incoming action must match one of them.
Action candidates are extracted from both the event suffix and well-known payload fields (action, state, conclusion, status).
Signature Verification
Mopheus supports HMAC-SHA256 signature verification, compatible with GitHub's webhook signature scheme.
How It Works
- When you set a Signing Secret on a webhook trigger, Mopheus expects every request to include a signature header
- The signature is computed as:
sha256=<hex(hmac_sha256(body, secret))> - Mopheus checks these headers in order:
X-Webhook-Signature(generic)X-Hub-Signature-256(GitHub-specific)
- The verification status is recorded on each job run (
signature_status):valid,invalid,missing, ornot_required
Setting Up
- Generate a random secret string (e.g.
openssl rand -hex 32) - In Mopheus: job detail → Webhook tab → set the Signing Secret
- In GitHub: repository → Settings → Webhooks → set the same value in the Secret field
Deduplication
Mopheus deduplicates webhook events at two levels:
In-Memory (30-second window)
The first line of defense. Uses a provider-specific delivery ID when available:
| Provider | Dedup Key Source |
|---|---|
| GitHub | X-GitHub-Delivery header |
| Generic | Idempotency-Key header, then X-GitHub-Delivery, then SHA256(event|repo|action) |
To replay a suppressed event, set the X-Mopheus-Replay: true header on the request.
Database-Level
A unique index on (trigger_id, dedupe_key) prevents duplicate job runs from being recorded. The attempt_count column tracks how many times the same dedupe key has been received.
Rate Limiting
Webhook endpoints have two layers of rate limiting:
| Layer | Scope | Rate | Burst |
|---|---|---|---|
| IP-based | Per source IP | 10 req/s | 20 |
| Token-based | Per webhook token | 5 req/s | 10 |
When rate-limited, the endpoint returns 429 Too Many Requests with a Retry-After: 1 header.
Git Entity Sync
Mopheus can mirror GitHub pull requests and issues, and link them to tickets.
What Gets Synced
Pull Requests: number, title, state, head/base ref, author, merge status, closing keywords, additions/deletions/changed files.
Issues: number, title, state, author.
Ticket Linking
When a PR or issue is linked to a ticket, Mopheus tracks a close_intent flag. This enables automation like "when this PR merges, close the linked ticket."
Built-in Agent Skills
Mopheus ships two built-in skills that agents use to interact with GitHub. These skills are available to any agent running in a workspace where the Git feature is enabled.
Code Workflow (mopheus-github-repos)
Use when you need to write or modify code. Covers the full checkout → code → commit → push → PR → sync workflow.
# 1. Checkout — creates an isolated worktree
mopheus repo checkout <url> --output json
# 2. Work — cd into the returned path, make changes
# 3. Commit — conventional format
git add -A && git commit -m "fix: description"
# 4. Push
git push -u origin <branch-name>
# 5. Create PR
gh pr create -R <url> --title "..." --body "..." --base main
# 6. Sync PR to ticket (REQUIRED)
mopheus repo pr sync --repo <url> --number <N> --title "..." --state open --ticket <ticket-id> --auto-link --output jsonKey rules:
- Always use
mopheus repo checkout— nevergit worktree adddirectly. The daemon maintains a bare cache and creates an isolated worktree per agent task. - The worktree branch is
agent/<name>/<task-id>. Don't rename it. - Use
--ref <branch|sha>to checkout a non-default branch. - Existing worktrees with local changes or unpushed commits are protected. Use
--forceonly to discard them. - Always use
--output jsononmopheuscommands so results are machine-parseable. - Do NOT skip step 6. A pushed branch without a synced PR is invisible to the ticket.
Webhook Event Handler (mopheus-github-webhook)
Use when processing GitHub webhook events. Covers PR/Issue sync, ticket linking, auto-close, and auto-create flows.
Only three actions are handled for both issues and pull_request events: opened, closed, and reopened. All other actions (labeled, assigned, synchronize, etc.) are skipped.
Workflow:
- Identify the repo —
mopheus repo list --output json, match againstrepository.html_urlfrom the payload - Check if entity exists —
mopheus repo pr listormopheus repo issue list - Sync the entity —
mopheus repo pr syncormopheus repo issue syncwith--auto-link - Evaluate auto-close — when a PR merges with
--close-keywordor an issue closes, check if all linked PRs are done and the ticket is not already terminal → set ticket to done
Auto-link: The --auto-link flag matches ticket identifiers (e.g. MOPHEUS-42) in PR/Issue title and body. When matched, a link is created automatically.
Auto-create: When the workspace setting auto_create_tickets is enabled and no ticket identifier is matched, the skill creates a new ticket from the webhook payload and links it to the entity.
CLI Commands
Use the mopheus CLI to manage jobs and triggers from the terminal:
# Create a webhook job
mopheus job create --name "GitHub PR Handler" --trigger-type webhook --action-type agent
# Add a webhook trigger to an existing job
mopheus job trigger-add <job-id> --kind webhook
# List triggers for a job
mopheus job trigger-list <job-id>
# Rotate the webhook token (invalidate old URL)
mopheus job trigger-rotate-url <job-id> <trigger-id>
# Manually fire a job
mopheus job trigger <job-id>
# View run history
mopheus job runs <job-id>Repo Management CLI
# Register a repo (URL is positional; provider is auto-detected)
mopheus repo add https://github.com/owner/repo
# List registered repos
mopheus repo list
# Remove a repo
mopheus repo remove https://github.com/owner/repo
# Create an isolated worktree for an agent task
mopheus repo checkout https://github.com/owner/repo
# Link / unlink a PR or Issue to a ticket (entity linking, NOT repo registration)
mopheus repo link --ticket <ticket-id> --entity-type git_pull_request --entity <entity-uuid>
mopheus repo unlink --ticket <ticket-id> --entity-type git_pull_request --entity <entity-uuid>
repo add/repo removeregister repositories.repo link/repo unlinkassociate a synced PR or Issue entity with a ticket — these are different operations and must not be confused.
Troubleshooting
| Symptom | Check |
|---|---|
| Webhook returns 404 | Verify the webhook URL matches {server_url}/api/v1/webhooks/jobs/{token} |
Webhook returns 403 WEBHOOK_DISABLED | The trigger is disabled; enable it in the job detail page |
Webhook returns 401 SIGNATURE_INVALID | The signing secret in GitHub doesn't match the one in Mopheus |
| Webhook returns 429 | Rate limit hit; wait and retry, or check for retry loops in GitHub |
| Webhook returns 413 | Payload exceeds 10 MiB; reduce the event scope |
| Events are being suppressed | Check if dedup is active; use X-Mopheus-Replay: true header to bypass |
| Agent can't clone repo | Verify GH_TOKEN or GITHUB_TOKEN is set and the token has repo access |
| Git feature not visible | Admin must enable the git feature flag in Admin → Features |