github / github/github-mcp-server
assign_copilot_to_issue_with_intent assigns Copilot but the agent session never starts
- Dominant language
- Go
- Stars
- 33k
- Forks
- 5k
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 52
Description
## Summary
`assign_copilot_to_issue_with_intent` reports success and Copilot is genuinely assigned to the issue, but **no coding agent session is ever created**. The user sees:
> The agent encountered an error and was unable to start working on this issue: This may be caused by a repository ruleset violation. See granting bypass permissions for the agent, or please contact support if the issue persists.
Assigning Copilot manually to the same repository, moments later, works end to end.
That error text is misleading: I checked, and **no ruleset denial occurred** (details below). Granting bypass permissions will not help, so it is worth correcting expectations for anyone who hits this.
## Reproduction
Observed on `github/padawan-testing-staging-jedi-knight` (repo id `1042304088`), issue #1065, 2026-09-15 14:00 UTC.
Tool call, from the calling agent's log:
```json
{"owner":"github","repo":"padawan-testing-staging-jedi-knight","issue_number":1065,
"is_suggestion":false,"confidence":"HIGH",
"rationale":"Issue requests repository research and a report, ...",
"custom_instructions":"Continue the repository research requested in the issue ..."}
```
Result (`success=true`):
```json
{"is_suggestion":false,"issue_number":1065,"message":"successfully assigned copilot to issue - pull request pending", ...}
```
## Evidence
Comparing the failing tool-driven assignment (#1065) against a manual assignment on the same repo two minutes later (#1066), from request logs:
| Step | #1065 (tool) | #1066 (manual) |
|---|---|---|
| GraphQL `updateIssue` | 200 | 200 |
| `UpdateIssueOrchestration` | completed 14:00:11.679 | completed |
| `GET /repos/.../rules/branches/copilot/task-...` | never called | 200 at 14:01:27.9 |
| `GET /repos/.../agents/secrets` and `/agents/variables` | never called | 200 at 14:01:30 |
| "Copilot SWE agent job secret mint result" | **absent** | 3x at 14:02:38-42 |
So the assignment mutation succeeds and the orchestration completes, but nothing downstream ever runs.
On the ruleset claim: every `Repositories::RuleSuite` evaluation for this repo in the window was on `refs/heads/main` for the *other* PR's merge check (license compliance + required workflows). Nothing evaluated a `copilot/*` branch for #1065.
## Where the two paths diverge
The intent tool uses the object form, whereas the legacy tool and the UI use assignee IDs:
- `AssignCopilotToIssue` (`pkg/github/copilot.go`): `UpdateIssueInput{ AssigneeIDs: actorIDs, AgentAssignment: ... }`
- `AssignCopilotToIssueWithIntent`: `UpdateIssueInput{ Assignees: assignees }`, with `AgentAssignment` set only when `!IsSuggestion`
`github/github` declares these mutually exclusive and handles them on separate branches in `app/platform/mutations/update_issue.rb`. The object form routes through `process_intents_via_processor`, sets `agent_bots_prevalidated = true`, and takes a different validation branch (`validate_agent_assignment_authorization!` rather than `validate_agent_bot_assignments!`).
## Candidate mechanisms
I could not discriminate between these without stepping through the intent processor at runtime, so I am listing them rather than asserting one.
1. **The `writable_by?` strip.** `update_issue.rb:384-390` adds a `Forbidden` execution error and then **removes the new agent bots from `attributes.assignees` while continuing with the rest of the update**. `copilot_context` stays `nil`, so no token is minted and no session starts. Because the intent processor persists the assignment atomically via `trigger_assigned_event` (see the comment at `:255`), the issue can still show Copilot assigned. This matches the symptom most closely.
2. **The `copilot_context` gate.** `update_issue.rb:374-382` only builds `copilot_context` when `inputs.key?(:assignees) && present?` and a new agentic bot id is found. `inputs[:assignees]` is left unset when `applied_actors` is empty (`:268-270`).
3. **Empty-string `customAgent`.** Both assign tools send `CustomAgent: &emptyString`; `omitempty` on `*githubv4.String` only drops a nil pointer, so `"customAgent": ""` goes on the wire where the UI omits it. This is common to both tools, so it does not by itself explain why only the intent tool fails, but it is worth tightening regardless.
## Suggested next step
The cheapest discriminator is a direct GraphQL call: `updateIssue` with object-form `assignees` plus `agentAssignment`, against a repo where the caller is known to be writable, then check whether a job secret mint follows. If mechanism 1 is correct, the response will carry a `Forbidden` execution error alongside a successful-looking payload.
Independently of the root cause, two small hardening changes look worthwhile in this repo:
- Only populate `CustomAgent` / `CustomInstructions` when non-empty, rather than pointing at `""`.
- Surface GraphQL execution errors from the assignment mutation in the tool result, so the tool does not report `success` when the agent assignment half of the mutation was rejected.
Filed from an investigation into why automations that select this tool never produce a session. Happy to provide the full request-log trace.
Contributor guide
Research direction
Start in pkg/github/copilot.go and trace AssignCopilotToIssueWithIntent into app/platform/mutations/update_issue.rb, especially the cited assignee, copilot_context, and validation paths. Reproduce the object-form GraphQL update in a writable repository, compare execution errors and downstream job-secret requests with manual assignment, and verify that success is reported only when the agent session can start.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, graphql, ruby
- Domain
- api, backend-api-design, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100