Conversation
…own kind
GitHub's issues API accepts pull request numbers, so issue tools such as
update_issue_labels could also modify pull requests. That makes it
impossible to allowlist issue-only capabilities for autonomous agents.
- Issue granular tools now verify the target is an issue (or an issue
comment) and reject pull requests before making any change.
- Add pull request counterparts: update_pull_request_{assignees,labels,
milestone}, {add,remove}_pull_request_reaction, add/update
pull_request_comment, and {add,remove}_pull_request_comment_reaction.
- When both granular flags are enabled, add_issue_comment and
update_issue_comment are served as issue-only variants.
- Export EnsureIssue, EnsurePullRequest, EnsureIssueComment and
EnsurePullRequestComment helpers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Error-response bodies leak, required arrays can be omitted to clear data, and variant snapshot coverage is incomplete.
Review effort: Balanced
Findings: 2
Open (6)
Require assignees presence while allowing empty arrays · New Require labels presence while allowing empty arrays · New Close response body on lookup errors · New Include matching companion tool in rejection errors · New Close response body before handling update errors · New Add snapshots for issue-only comment tool variants · New
What changed in this PR
Splits granular issue and pull-request operations to enforce kind-specific automation allowlists.
Changes:
- Adds issue/PR validation helpers and conditional comment-tool variants.
- Adds nine granular pull-request companion tools.
- Updates tests, schema snapshots, and feature-flag documentation.
| File | Description |
|---|---|
pkg/github/tools.go |
Registers new tool variants. |
pkg/github/pullrequests_granular.go |
Implements granular PR tools. |
pkg/github/issues.go |
Adds issue-only comment variants. |
pkg/github/issues_granular.go |
Enforces issue/PR kind checks. |
pkg/github/granular_tools_test.go |
Tests kind-specific behavior. |
pkg/github/feature_flags.go |
Defines combined-flag rules. |
pkg/github/feature_flags_test.go |
Tests flag combinations. |
pkg/github/__toolsnaps__/update_pull_request_milestone.snap |
Snapshots PR milestone tool. |
pkg/github/__toolsnaps__/update_pull_request_labels.snap |
Snapshots PR labels tool. |
pkg/github/__toolsnaps__/update_pull_request_comment.snap |
Snapshots PR comment update. |
pkg/github/__toolsnaps__/update_pull_request_assignees.snap |
Snapshots PR assignees tool. |
pkg/github/__toolsnaps__/update_issue_type.snap |
Updates issue-type description. |
pkg/github/__toolsnaps__/update_issue_title.snap |
Updates issue-title description. |
pkg/github/__toolsnaps__/update_issue_state.snap |
Updates issue-state description. |
pkg/github/__toolsnaps__/update_issue_milestone.snap |
Updates issue-milestone description. |
pkg/github/__toolsnaps__/update_issue_labels.snap |
Updates issue-label description. |
pkg/github/__toolsnaps__/update_issue_body.snap |
Updates issue-body description. |
pkg/github/__toolsnaps__/update_issue_assignees.snap |
Updates issue-assignees description. |
pkg/github/__toolsnaps__/remove_pull_request_reaction.snap |
Snapshots PR reaction removal. |
pkg/github/__toolsnaps__/remove_pull_request_comment_reaction.snap |
Snapshots PR comment-reaction removal. |
pkg/github/__toolsnaps__/remove_issue_reaction.snap |
Narrows issue-reaction removal schema. |
pkg/github/__toolsnaps__/remove_issue_comment_reaction.snap |
Narrows issue comment-reaction schema. |
pkg/github/__toolsnaps__/add_pull_request_reaction.snap |
Snapshots PR reaction addition. |
pkg/github/__toolsnaps__/add_pull_request_comment.snap |
Snapshots PR commenting. |
pkg/github/__toolsnaps__/add_pull_request_comment_reaction.snap |
Snapshots PR comment reactions. |
pkg/github/__toolsnaps__/add_issue_reaction.snap |
Narrows issue-reaction schema. |
pkg/github/__toolsnaps__/add_issue_comment_reaction.snap |
Narrows issue comment-reaction schema. |
docs/feature-flags.md |
Documents split tool behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+1087
to
+1093
| func(args map[string]any) (gogithub.UpdateIssueRequest, error) { | ||
| assignees, err := OptionalStringArrayParam(args, "assignees") | ||
| if err != nil { | ||
| return gogithub.UpdateIssueRequest{}, err | ||
| } | ||
| return gogithub.UpdateIssueRequest{Assignees: assignees}, nil | ||
| }, |
Comment on lines
+1111
to
+1117
| func(args map[string]any) (gogithub.UpdateIssueRequest, error) { | ||
| labels, err := OptionalStringArrayParam(args, "labels") | ||
| if err != nil { | ||
| return gogithub.UpdateIssueRequest{}, err | ||
| } | ||
| return gogithub.UpdateIssueRequest{Labels: labels}, nil | ||
| }, |
This comment was marked as outdated.
This comment was marked as outdated.
Co-authored-by: timrogers <116134+timrogers@users.noreply.github.com>
This comment was marked as outdated.
This comment was marked as outdated.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
This PR updates the
issues_granularandpull_requests_granularfeature flag behavior so that:update_issue_assigneesonly works with PRs)update_pull_request_assignees, rather than relying onupdate_issue_assignees)This does not affect the default base behavior used by normal customers - only opt in behavior used by Copilot Automations behind the
issues_granularandpull_requests_granularfeature flags.Why
The
issues_granularandpull_requests_granulartools are used in Copilot Automations, which are fully autonomous.We want to allow users to have full and maximally granular control of what their automations can do with an allowlist of tools. That promise only works if each tool does what its name says.
Today it doesn't. GitHub's issues REST API treats every pull request as an issue, so tools like
update_issue_labels,update_issue_state,update_issue_titleandadd_issue_commentalso work on PRs when given a PR number.Allowlisting a bunch of tools for triaging issues therefore also lets an automation relabel, retitle, close or comment on pull requests, and we couldn't grant one without the other.
After this change, issue tools refuse PRs and PR tools refuse issues. Each capability can be allowed on its own.
What changed
update_issue_{title,body,assignees,labels,milestone,type,state}and{add,remove}_issue_reactionlook up the number first and return an error, without changing anything, if it's a pull request. The error points to the matching PR tool.{add,remove}_issue_comment_reactiondo the same for comments, by checking which issue or PR the comment belongs to.pull_requests_granular). Each one checks that the target really is a PR (or a PR comment):update_pull_request_assignees,update_pull_request_labels,update_pull_request_milestoneadd_pull_request_reaction,remove_pull_request_reactionadd_pull_request_comment,update_pull_request_commentadd_pull_request_comment_reaction,remove_pull_request_comment_reaction(for conversation comments; the existing*_review_comment_reactiontools still handle review comments)add_issue_commentandupdate_issue_commentare shared by the default and granular tool sets. They become issue-only only when bothissues_granularandpull_requests_granularare enabled, so enabling one flag never takes away PR commenting. The version used by default is unchanged.EnsureIssue,EnsurePullRequest,EnsureIssueCommentandEnsurePullRequestComment, so the remote server can use the same checks.MCP impact
add_issue_reaction,remove_issue_reactionand the issue comment-reaction tools previously accepted both issues and PRs.Prompts tested (tool changes only)
Covered by unit tests only; I haven't run these prompts against a live server.
buglabel to issue Ensure we have an identifiable user agent #12":update_issue_labelssucceeds.buglabel to PR add support for the push_files tool #34" usingupdate_issue_labels: rejected, pointing toupdate_pull_request_labels.add_pull_request_commentsucceeds, and it rejects issue numbers.Security / limits
The checks add one extra GET per call (two for comment-ID tools). Checking before writing means a rejected call never changes anything.
Tool renaming
deprecated_tool_aliases.goLint & tests
./script/lint: rangofmt -sandgo vet. golangci-lint v2.9.0 couldn't type-check under the local Go 1.27, so CI's lint job covers it../script/testNew tests check that each restricted tool rejects the wrong kind without sending any write, that each new PR tool works on a PR, and which tool versions are active under all four flag combinations.
Docs
docs/feature-flags.mdand added a hand-written note on the behavior when both flags are on.