Skip to content

Commit d88eb83

Browse files
Add custom_instructions parameter to assign_copilot_to_issue tool
- Added optional custom_instructions parameter to tool schema - Updated implementation to pass custom instructions to agent assignment - Added test case to verify custom_instructions works correctly - Updated toolsnaps and documentation The custom_instructions parameter allows users to provide additional context, constraints, or guidance to the Copilot agent beyond what's in the issue body, addressing the issue where additional context would otherwise be lost. Co-authored-by: SamMorrowDrums <4811358+SamMorrowDrums@users.noreply.github.com>
1 parent 19beb33 commit d88eb83

File tree

4 files changed

+131
-4
lines changed

4 files changed

+131
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ The following sets of tools are available:
752752
- **assign_copilot_to_issue** - Assign Copilot to issue
753753
- **Required OAuth Scopes**: `repo`
754754
- `base_ref`: Git reference (e.g., branch) that the agent will start its work from. If not specified, defaults to the repository's default branch (string, optional)
755+
- `custom_instructions`: Optional custom instructions to guide the agent beyond the issue body. Use this to provide additional context, constraints, or guidance that is not captured in the issue description (string, optional)
755756
- `issue_number`: Issue number (number, required)
756757
- `owner`: Repository owner (string, required)
757758
- `repo`: Repository name (string, required)

pkg/github/__toolsnaps__/assign_copilot_to_issue.snap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
"description": "Git reference (e.g., branch) that the agent will start its work from. If not specified, defaults to the repository's default branch",
2323
"type": "string"
2424
},
25+
"custom_instructions": {
26+
"type": "string",
27+
"description": "Optional custom instructions to guide the agent beyond the issue body. Use this to provide additional context, constraints, or guidance that is not captured in the issue description"
28+
},
2529
"issue_number": {
2630
"description": "Issue number",
2731
"type": "number"

pkg/github/issues.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,17 +1650,22 @@ func AssignCopilotToIssue(t translations.TranslationHelperFunc) inventory.Server
16501650
Type: "string",
16511651
Description: "Git reference (e.g., branch) that the agent will start its work from. If not specified, defaults to the repository's default branch",
16521652
},
1653+
"custom_instructions": {
1654+
Type: "string",
1655+
Description: "Optional custom instructions to guide the agent beyond the issue body. Use this to provide additional context, constraints, or guidance that is not captured in the issue description",
1656+
},
16531657
},
16541658
Required: []string{"owner", "repo", "issue_number"},
16551659
},
16561660
},
16571661
[]scopes.Scope{scopes.Repo},
16581662
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
16591663
var params struct {
1660-
Owner string `mapstructure:"owner"`
1661-
Repo string `mapstructure:"repo"`
1662-
IssueNumber int32 `mapstructure:"issue_number"`
1663-
BaseRef string `mapstructure:"base_ref"`
1664+
Owner string `mapstructure:"owner"`
1665+
Repo string `mapstructure:"repo"`
1666+
IssueNumber int32 `mapstructure:"issue_number"`
1667+
BaseRef string `mapstructure:"base_ref"`
1668+
CustomInstructions string `mapstructure:"custom_instructions"`
16641669
}
16651670
if err := mapstructure.Decode(args, &params); err != nil {
16661671
return utils.NewToolResultError(err.Error()), nil, nil
@@ -1775,6 +1780,12 @@ func AssignCopilotToIssue(t translations.TranslationHelperFunc) inventory.Server
17751780
agentAssignment.BaseRef = &baseRef
17761781
}
17771782

1783+
// Add custom instructions if provided
1784+
if params.CustomInstructions != "" {
1785+
customInstructions := githubv4.String(params.CustomInstructions)
1786+
agentAssignment.CustomInstructions = &customInstructions
1787+
}
1788+
17781789
// Execute the updateIssue mutation with the GraphQL-Features header
17791790
// This header is required for the agent assignment API which is not GA yet
17801791
var updateIssueMutation struct {

pkg/github/issues_test.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,6 +2086,7 @@ func TestAssignCopilotToIssue(t *testing.T) {
20862086
assert.Contains(t, tool.InputSchema.(*jsonschema.Schema).Properties, "repo")
20872087
assert.Contains(t, tool.InputSchema.(*jsonschema.Schema).Properties, "issue_number")
20882088
assert.Contains(t, tool.InputSchema.(*jsonschema.Schema).Properties, "base_ref")
2089+
assert.Contains(t, tool.InputSchema.(*jsonschema.Schema).Properties, "custom_instructions")
20892090
assert.ElementsMatch(t, tool.InputSchema.(*jsonschema.Schema).Required, []string{"owner", "repo", "issue_number"})
20902091

20912092
// Helper function to create pointer to githubv4.String
@@ -2638,6 +2639,116 @@ func TestAssignCopilotToIssue(t *testing.T) {
26382639
),
26392640
),
26402641
},
2642+
{
2643+
name: "successful assignment with custom_instructions specified",
2644+
requestArgs: map[string]any{
2645+
"owner": "owner",
2646+
"repo": "repo",
2647+
"issue_number": float64(123),
2648+
"custom_instructions": "Please ensure all code follows PEP 8 style guidelines and includes comprehensive docstrings",
2649+
},
2650+
mockedClient: githubv4mock.NewMockedHTTPClient(
2651+
githubv4mock.NewQueryMatcher(
2652+
struct {
2653+
Repository struct {
2654+
SuggestedActors struct {
2655+
Nodes []struct {
2656+
Bot struct {
2657+
ID githubv4.ID
2658+
Login githubv4.String
2659+
TypeName string `graphql:"__typename"`
2660+
} `graphql:"... on Bot"`
2661+
}
2662+
PageInfo struct {
2663+
HasNextPage bool
2664+
EndCursor string
2665+
}
2666+
} `graphql:"suggestedActors(first: 100, after: $endCursor, capabilities: CAN_BE_ASSIGNED)"`
2667+
} `graphql:"repository(owner: $owner, name: $name)"`
2668+
}{},
2669+
map[string]any{
2670+
"owner": githubv4.String("owner"),
2671+
"name": githubv4.String("repo"),
2672+
"endCursor": (*githubv4.String)(nil),
2673+
},
2674+
githubv4mock.DataResponse(map[string]any{
2675+
"repository": map[string]any{
2676+
"suggestedActors": map[string]any{
2677+
"nodes": []any{
2678+
map[string]any{
2679+
"id": githubv4.ID("copilot-swe-agent-id"),
2680+
"login": githubv4.String("copilot-swe-agent"),
2681+
"__typename": "Bot",
2682+
},
2683+
},
2684+
},
2685+
},
2686+
}),
2687+
),
2688+
githubv4mock.NewQueryMatcher(
2689+
struct {
2690+
Repository struct {
2691+
ID githubv4.ID
2692+
Issue struct {
2693+
ID githubv4.ID
2694+
Assignees struct {
2695+
Nodes []struct {
2696+
ID githubv4.ID
2697+
}
2698+
} `graphql:"assignees(first: 100)"`
2699+
} `graphql:"issue(number: $number)"`
2700+
} `graphql:"repository(owner: $owner, name: $name)"`
2701+
}{},
2702+
map[string]any{
2703+
"owner": githubv4.String("owner"),
2704+
"name": githubv4.String("repo"),
2705+
"number": githubv4.Int(123),
2706+
},
2707+
githubv4mock.DataResponse(map[string]any{
2708+
"repository": map[string]any{
2709+
"id": githubv4.ID("test-repo-id"),
2710+
"issue": map[string]any{
2711+
"id": githubv4.ID("test-issue-id"),
2712+
"assignees": map[string]any{
2713+
"nodes": []any{},
2714+
},
2715+
},
2716+
},
2717+
}),
2718+
),
2719+
githubv4mock.NewMutationMatcher(
2720+
struct {
2721+
UpdateIssue struct {
2722+
Issue struct {
2723+
ID githubv4.ID
2724+
Number githubv4.Int
2725+
URL githubv4.String
2726+
}
2727+
} `graphql:"updateIssue(input: $input)"`
2728+
}{},
2729+
UpdateIssueInput{
2730+
ID: githubv4.ID("test-issue-id"),
2731+
AssigneeIDs: []githubv4.ID{githubv4.ID("copilot-swe-agent-id")},
2732+
AgentAssignment: &AgentAssignmentInput{
2733+
BaseRef: nil,
2734+
CustomAgent: ptrGitHubv4String(""),
2735+
CustomInstructions: ptrGitHubv4String("Please ensure all code follows PEP 8 style guidelines and includes comprehensive docstrings"),
2736+
TargetRepositoryID: githubv4.ID("test-repo-id"),
2737+
},
2738+
},
2739+
nil,
2740+
githubv4mock.DataResponse(map[string]any{
2741+
"updateIssue": map[string]any{
2742+
"issue": map[string]any{
2743+
"id": githubv4.ID("test-issue-id"),
2744+
"number": githubv4.Int(123),
2745+
"url": githubv4.String("https://github.com/owner/repo/issues/123"),
2746+
},
2747+
},
2748+
}),
2749+
),
2750+
),
2751+
},
26412752
}
26422753

26432754
for _, tc := range tests {

0 commit comments

Comments
 (0)