### Why / What / How **Why:** We have GitHub trigger and repo/issue/PR blocks, but no way for agents to work with the user's GitHub notification inbox — e.g. inbox-zero automations, notification triage, or surfacing review requests. GitHub's Notifications API is poll-only (no webhook events exist for it), so inbox automations run as scheduled graphs using regular blocks. **What:** Adds six blocks covering the [GitHub Notifications REST API](https://docs.github.com/en/rest/activity/notifications): listing notifications and getting / marking read / marking done / unsubscribing from notification threads, plus mark-all-as-read. Also adds a `GithubGetUserInfoBlock` and extends `GithubListPRReviewersBlock` with review status info, enabling agents to determine whether the account's user is (still) involved in a PR (example use case: auto-archiving stale review-request notifications). **How:** New `notifications.py` in the GitHub blocks package, following the existing block conventions there. Notification endpoints live under `/notifications` rather than `/repos/...`, so the blocks use `get_api(credentials, convert_urls=False)` with absolute URLs. API responses are normalized into a shared `NotificationItem` shape whose `thread_id` chains into the per-thread blocks and whose `subject_url` is converted best-effort from the API URL to the corresponding github.com page URL. Notification blocks use the minimal `notifications` OAuth scope. ### Changes 🏗️ - Add `GithubListNotificationsBlock`: lists the inbox with include-read / participating-only / `since` / `before` filters and optional repo scoping; yields the full list plus each notification individually - Add `GithubGetNotificationThreadBlock`: fetches one thread and exposes title, reason, unread, subject type/URL, and repository as separate outputs - Add `GithubMarkNotificationsAsReadBlock`: marks all notifications as read, optionally repo-scoped, with optional `last_read_at` cutoff - Add `GithubMarkNotificationThreadAsReadBlock` and `GithubMarkNotificationThreadAsDoneBlock`: per-thread read / done - Add `GithubUnsubscribeNotificationThreadBlock`: mutes a thread - Add `GithubGetUserInfoBlock`: fetches info on a given user, or the authenticated user if no username is given - Extend `GithubListPRReviewersBlock`: new `include_past_reviewers` toggle (default off) to also list users who already submitted a review, plus `review_requested` / `has_reviewed` / `review_state` fields on each reviewer item; the extra API call is gated behind the toggle so existing graphs are unaffected - Refactor: hoist `GITHUB_API_URL` constant into `_api.py` and reuse it ### Checklist 📋 #### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: - [x] `poetry run pytest backend/blocks/test/test_block.py` — full block suite passes, including schema validation + mocked execution of all new/changed blocks - [x] `poetry run pytest backend/blocks/github/test_github_blocks.py` — passes - [ ] Live-run the List / Mark as read blocks against a real GitHub account (not done — mocked execution only) <details> <summary>Example test plan</summary> - [ ] Create from scratch and execute an agent with at least 3 blocks - [ ] Import an agent from file upload, and confirm it executes correctly - [ ] Upload agent to marketplace - [ ] Import an agent from marketplace and confirm it executes correctly - [ ] Edit an agent from monitor, and confirm it executes correctly </details> #### For configuration changes: - [x] `.env.default` is updated or already compatible with my changes - [x] `docker-compose.yml` is updated or already compatible with my changes - [x] I have included a list of my configuration changes in the PR description (under **Changes**) <details> <summary>Examples of configuration changes</summary> - Changing ports - Adding new services that need to communicate with each other - Secrets or environment variable changes - New or infrastructure changes such as databases </details> --------- Co-authored-by: Claude Fable 5 <[email protected]>
9.6 KiB
GitHub Notifications
Blocks for reading and clearing the GitHub notification inbox — the same feed as the bell icon on github.com — so an agent can triage what it is being asked to look at and then clear those threads behind itself.
Github Get Notification Thread
What it is
This block fetches a single GitHub notification thread.
How it works
Fetches one thread from /notifications/threads/{thread_id} and normalises it into the same NotificationItem shape the list block emits, so both can feed the same downstream nodes. The subject URL GitHub returns is an API URL, and the block rewrites it per path segment into its github.com equivalent: /pulls/{n} becomes /pull/{n}, /commits/{sha} becomes /commit/{sha}, and a release — which the API addresses by numeric id but the web addresses by tag — degrades to the repository's releases index. Anything that is not a repo-scoped API URL is passed through untouched. Note that a thread id is the notification's own id, not the issue or pull request number.
Inputs
| Input | Description | Type | Required |
|---|---|---|---|
| thread_id | ID of the notification thread | str | Yes |
Outputs
| Output | Description | Type |
|---|---|---|
| error | Error message if fetching the notification thread failed | str |
| notification | The notification thread | NotificationItem |
| title | Title of the notification subject | str |
| reason | Reason you received the notification (e.g. 'mention', 'review_requested', 'subscribed') | str |
| unread | Whether the notification is unread | bool |
| subject_type | Type of the notification subject (e.g. 'Issue', 'PullRequest', 'Release') | str |
| subject_url | URL of the notification subject on GitHub | str |
| repository | Full name of the repository (owner/repo) | str |
| updated_at | ISO 8601 timestamp of the last update to the thread | str |
Possible use case
A triage agent walks an inbox listing and re-fetches each thread before acting on it. A notification may have been read, resolved or closed elsewhere since the listing was taken, and acting on stale state means replying to something a colleague already handled.
Github List Notifications
What it is
This block lists GitHub notifications for the authenticated user, e.g. mentions, review requests, and updates on subscribed threads.
How it works
Reads the notification inbox, either globally or scoped to a single repository, and follows pagination until limit items are collected rather than returning only the first page. The two endpoints differ in page size — the global /notifications caps a page at 50 while the repo-scoped one allows the usual 100 — and the block uses whichever applies. repo accepts either {owner}/{repo} or a full repository URL. By default only unread threads come back; include_read sends all=true, and participating_only narrows to threads where you are directly involved rather than merely watching. since and before bound the results by last-update time. Each item is flattened to a NotificationItem whose subject_url is a browsable github.com link, not the API URL.
Inputs
| Input | Description | Type | Required |
|---|---|---|---|
| include_read | Whether to include notifications that are already marked as read | bool | No |
| participating_only | Whether to only include notifications in which you are directly participating or mentioned | bool | No |
| limit | Maximum number of notifications to fetch | int | No |
| repo | Repository to list notifications for, as '{owner}/{repo}' or a full repository URL. Leave empty to list notifications for all repositories. | str | No |
| since | Only show notifications updated after the given ISO 8601 timestamp | str | No |
| before | Only show notifications updated before the given ISO 8601 timestamp | str | No |
Outputs
| Output | Description | Type |
|---|---|---|
| error | Error message if listing notifications failed | str |
| notification | Each notification thread | Notification |
| notifications | List of notification threads | List[NotificationItem] |
Possible use case
A morning triage agent lists notifications with participating_only enabled, groups them by reason — review_requested, mention, assign — and posts one ranked digest to Slack, so a maintainer sees what actually needs them instead of scrolling the bell menu.
Github Mark Notification Thread As Done
What it is
This block marks a GitHub notification thread as done, removing it from the notification inbox.
How it works
Sends DELETE to /notifications/threads/{thread_id}. Despite the verb, nothing is deleted: GitHub's "done" state removes the thread from your inbox and marks it read, while the underlying issue, pull request or discussion is untouched, and new activity on that subject can surface it again. This is distinct from unsubscribing, which stops future notifications for the subject entirely.
Inputs
| Input | Description | Type | Required |
|---|---|---|---|
| thread_id | ID of the notification thread | str | Yes |
Outputs
| Output | Description | Type |
|---|---|---|
| error | Error message if marking the thread as done failed | str |
| success | Whether the notification thread was marked as done | bool |
Possible use case
Once a triage agent has summarised and filed a batch of notifications, it marks each one done so the next run starts from a clean inbox instead of re-reporting the same threads.
Github Mark Notification Thread As Read
What it is
This block marks a single GitHub notification thread as read.
How it works
Sends PATCH to /notifications/threads/{thread_id}. The thread keeps its place in the inbox but loses its unread flag, so a later listing without include_read skips it. Use this rather than marking the thread done when it should stay visible.
Inputs
| Input | Description | Type | Required |
|---|---|---|---|
| thread_id | ID of the notification thread | str | Yes |
Outputs
| Output | Description | Type |
|---|---|---|
| error | Error message if marking the thread as read failed | str |
| success | Whether the notification thread was marked as read | bool |
Possible use case
An agent that auto-answers a known subset of mentions marks only those threads read, leaving everything it could not handle unread and still in the inbox for a human.
Github Mark Notifications As Read
What it is
This block marks all GitHub notifications as read, optionally scoped to a single repository.
How it works
Sends PUT to the notifications endpoint, either globally or for one repository; repo accepts {owner}/{repo} or a full repository URL, and leaving it empty clears the whole inbox. last_read_at restricts the sweep to threads updated before that timestamp and defaults to now, which is what makes this safe to run against a busy inbox: anything arriving while the request is in flight keeps its unread state rather than being silently cleared.
Inputs
| Input | Description | Type | Required |
|---|---|---|---|
| repo | Repository to mark notifications as read for, as '{owner}/{repo}' or a full repository URL. Leave empty to mark notifications for all repositories. | str | No |
| last_read_at | Only mark notifications updated before the given ISO 8601 timestamp as read. Defaults to the current time. | str | No |
Outputs
| Output | Description | Type |
|---|---|---|
| error | Error message if marking notifications as read failed | str |
| success | Whether the notifications were marked as read | bool |
Possible use case
A weekly hygiene agent passes the start of the week as last_read_at, clearing a backlog of stale notifications in one call while leaving the last few days' worth untouched.
Github Unsubscribe Notification Thread
What it is
This block unsubscribes you from a GitHub notification thread, muting future notifications unless you are mentioned again.
How it works
Sends DELETE to /notifications/threads/{thread_id}/subscription, a different endpoint from the one that marks a thread done. This ends your subscription to the subject, so further activity on that issue or pull request produces no new notifications at all. The effect persists until you subscribe again or someone mentions you directly.
Inputs
| Input | Description | Type | Required |
|---|---|---|---|
| thread_id | ID of the notification thread | str | Yes |
Outputs
| Output | Description | Type |
|---|---|---|
| error | Error message if unsubscribing from the thread failed | str |
| success | Whether you were unsubscribed from the notification thread | bool |
Possible use case
A long-running, high-traffic issue that an agent was added to but has no stake in gets unsubscribed after a single triage pass, so its every comment stops re-entering the inbox.