Skip to content

Commit ccdc2bc

Browse files
committed
Improve tool calling prompts, modify pre-req agent behavior
Signed-off-by: Kelly Abuelsaad <kaymar@gmail.com>
1 parent 5489ffb commit ccdc2bc

5 files changed

Lines changed: 102 additions & 77 deletions

File tree

a2a/git_issue_agent/a2a_agent.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,14 @@ async def execute(self, context: RequestContext, event_queue: EventQueue):
158158
Returns:
159159
None
160160
"""
161-
if settings.JWKS_URI:
162-
user_token = context.call_context.user._user.access_token
163-
else:
164-
user_token = settings.GITHUB_TOKEN
161+
###
162+
# commenting this out for now since we have external github MCP.
163+
# in the future we need to figure out the token exchange story for this scenario
164+
#
165+
#if settings.JWKS_URI:
166+
# user_token = context.call_context.user._user.access_token
167+
#else:
168+
user_token = settings.GITHUB_TOKEN
165169
user_input = [context.get_user_input()]
166170
task = context.current_task
167171
if not task:

a2a/git_issue_agent/git_issue_agent/agents.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from crewai import Agent, Crew, Process, Task
22
from git_issue_agent.config import Settings
3-
from git_issue_agent.data_types import UserQueryJudgement
3+
from git_issue_agent.data_types import IssueSearchInfo
44
from git_issue_agent.llm import CrewLLM
5-
from git_issue_agent.prompts import REPO_ID_BACKSTORY, TOOL_CALL_PROMPT
5+
from git_issue_agent.prompts import TOOL_CALL_PROMPT, INFO_PARSER_PROMPT
66
class GitAgents():
77

88
def __init__(self, config: Settings, issue_tools):
@@ -12,21 +12,24 @@ def __init__(self, config: Settings, issue_tools):
1212
# Pre-requisitie validator
1313
# ##################
1414
self.prereq_identifier = Agent(
15-
role="Pre-requisite Judge",
16-
goal="To determine whether a user has supplied enough information to find Github issues.",
17-
backstory=REPO_ID_BACKSTORY,
15+
role="Pre-requisite Extractor",
16+
goal="To extract the information about github artifacts that a user is looking for",
17+
backstory=INFO_PARSER_PROMPT,
1818
verbose=True,
1919
llm=self.llm.llm
2020
)
2121

2222
self.prereq_identifier_task = Task(
2323
description=(
24-
"User query: {request}"
24+
"User query: {request}, \
25+
Identified repository: {repo} \
26+
Identified owner: {owner} \
27+
Identified issue numbers: {issues}"
2528
),
2629
agent=self.prereq_identifier,
27-
output_pydantic=UserQueryJudgement,
30+
output_pydantic=IssueSearchInfo,
2831
expected_output=(
29-
"A judgement on whether a request from a user successfully identifies an organization or user that owns issues."
32+
"A structured extraction of the relevant Github artifacts"
3033
),
3134
)
3235

a2a/git_issue_agent/git_issue_agent/data_types.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# Pydantic types for LLM response formats
66
############
77

8-
9-
class UserQueryJudgement(BaseModel):
10-
has_sufficient_information: bool = Field(False, description="Whether the user's query contains sufficient enough information to retrieve issues from github")
11-
explanation: str = Field(None, description="A detailed explanation as to why you made the judgement")
8+
class IssueSearchInfo(BaseModel):
9+
owner: str
10+
repo: str
11+
issue_numbers: list[int]

a2a/git_issue_agent/git_issue_agent/main.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def __init__(self, config: Settings,
2222

2323
self.agents = GitAgents(settings, mcp_toolkit)
2424
self.eventer = eventer
25+
self.logger = logger or logging.getLogger(__name__)
2526

2627
async def _send_event(self, message: str, final: bool = False):
2728
logger.info(message)
@@ -48,16 +49,19 @@ def extract_user_input(self, body):
4849
async def execute(self, user_input):
4950
query = self.extract_user_input(user_input)
5051
await self._send_event("🧐 Evaluating requirements...")
51-
await self.agents.prereq_id_crew.kickoff_async(inputs={"request": query})
52+
await self.agents.prereq_id_crew.kickoff_async(
53+
inputs={"request": query, "repo": "", "owner": "", "issues": []}
54+
)
5255
repo_id_task_output = self.agents.prereq_identifier_task.output.pydantic
5356

54-
if not repo_id_task_output.has_sufficient_information:
55-
return repo_id_task_output.explanation
57+
if repo_id_task_output.issue_numbers:
58+
if not repo_id_task_output.owner or not repo_id_task_output.repo:
59+
return "When supplying issue numbers, you must provide both a repository name and owner."
60+
if repo_id_task_output.repo:
61+
if not repo_id_task_output.owner:
62+
return "When supplying a repository name, you must also provide an owner of the repo."
5663

5764
await self._send_event("🔎 Searching for issues...")
58-
await self.agents.crew.kickoff_async(inputs={"request": query})
65+
await self.agents.crew.kickoff_async(inputs={"request": query, "owner": repo_id_task_output.owner, "repo": repo_id_task_output.repo, "issues": repo_id_task_output.issue_numbers})
5966
return self.agents.issue_query_task.output.raw
60-
6167

62-
63-
Lines changed: 68 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,101 @@
11
TOOL_CALL_PROMPT = """
2-
You are a GitHub issue analyst with access to MCP tools that can search and list GitHub issues. Use them to gather facts before answering the user.
2+
You are a GitHub issue analyst with access to MCP tools that can search and list GitHub issues.
33
44
YOUR JOB
5-
1) Decide whether the user’s request can be fulfilled with a tool from the catalog.
6-
2) When a tool is required, emit a tool call in the exact format below and nothing else.
7-
3) After tool results arrive, produce the final answer grounded strictly in those results.
8-
9-
──────────────────────────────────────────────────────────────────────────────
10-
TOOL CALL FORMAT (emit only this block when calling a tool)
11-
12-
<|tool_call|>
13-
[
5+
1. Decide whether the user’s request can be fulfilled with a tool from the catalog.
6+
2. When a tool is required, emit **only** a single tool call in the exact format below.
7+
3. After tool results arrive, produce the final answer grounded strictly in those results.
8+
9+
────────────────────────────────────────────────────────
10+
⚙️ TOOL CALL PHASE
11+
You are a GitHub issue analyst with access to MCP tools that can search and list GitHub issues.
12+
13+
MODES
14+
- If a tool is required, you MUST output EXACTLY the following four lines in this order:
15+
1) Thought: <one short sentence>
16+
2) Action: <one of [list_issue_types, list_issues, list_sub_issues, search_issues]>
17+
3) Action Input: <a single-line JSON object with only the schema's keys/values>
18+
4) Observation: <leave blank – this will be filled by the system>
19+
20+
- After the Observation is provided by the system, output:
21+
Thought: I now know the final answer
22+
Final Answer: <answer grounded ONLY in the tool output>
23+
24+
STRICT RULES FOR TOOL CALLS
25+
- Output NOTHING except those exact lines when calling a tool. No code fences, no XML, no extra braces.
26+
- The JSON after "Action Input:" MUST be valid and single-line. No trailing commas, no extra closing braces.
27+
- Use ONLY properties defined in the tool schema (required + optional). Exact key names and value types.
28+
- Use only one tool per call.
29+
30+
CORRECT EXAMPLE
31+
Thought: The user provided owner and repo; list_issues fits.
32+
Action: list_issues
33+
Action Input: {"owner":"kagenti","repo":"kagenti"}
34+
Observation:
35+
36+
INCORRECT EXAMPLES (do NOT do these)
37+
- <tool_call>{"name":"list_issues",...}</tool_call>
38+
- Action: {"name":"list_issues","arguments":{...}}
39+
- Action Input:
1440
{
15-
"name": "<tool_name>",
16-
"arguments": {
17-
... key: value pairs that match the tool's JSON Schema exactly ...
18-
}
41+
"owner":"kagenti",
42+
"repo":"kagenti",
1943
}
20-
]
21-
22-
Rules for arguments:
23-
- Use ONLY the properties defined in that tool’s schema (required + optional).
24-
- Use the exact key names and value types from the schema.
25-
- Do NOT wrap parameters in another "arguments" object.
26-
- Do NOT include extra keys or trailing commentary.
27-
- If a property has an enum, choose one value from the enum.
28-
- If required information is missing, do not call the tool—wait or respond `NO_TOOL`.
44+
- Action: list_issues
45+
Action Input: {"owner":"kagenti","repo":"kagenti"}}
2946
30-
──────────────────────────────────────────────────────────────────────────────
31-
FINAL ANSWER FORMAT (after you receive tool output)
47+
────────────────────────────────────────────────────────
48+
🧩 FINAL ANSWER PHASE
3249
33-
- Base your answer ONLY on tool output or supplied context.
34-
- Clearly cite the relevant tool results when explaining the outcome.
35-
- If a tool failed or could not be called because inputs were missing, say so.
50+
After tool results arrive:
51+
- Produce a human-readable answer grounded only in the tool output.
52+
- Clearly cite or reference the tool results.
53+
- If a tool failed or inputs were missing, say so explicitly. Don't attempt to guess the answer.
3654
37-
──────────────────────────────────────────────────────────────────────────────
55+
────────────────────────────────────────────────────────
3856
TOOL SELECTION GUIDELINES
3957
4058
- Do **not** guess repository owners, names, or issue numbers.
4159
- Choose the most specific tool that aligns with the user’s intent.
4260
- Respect each tool’s required and optional parameters; format them exactly as expected.
4361
- Use only one tool call at a time.
4462
63+
Here are some additional descriptions of the tools you will be provided, along with guidance on how to choose teh right one.
64+
65+
**Search Issues:** Use this tool to find issues when you do not have a repository name. Optionally scope by owner or repo if provided.
4566
**List Issue Types:** Use only to enumerate available issue types for a specific organization.
46-
**List Issues:** Use only when both repository owner and exact repository name are provided. Optional filters: state, label, date, etc.
47-
**List Sub-Issues:** Use only when owner, repo, and issue number are given.
48-
**Search Issues:** Use for broader queries or when owner/repo are unknown. Optionally scope by owner or repo if provided.
67+
**List Issues:** Use only when both repository owner AND exact repository name are provided. Do not use unless you have both pieces of information. Optional filters: state, label, date, etc.
68+
**List Sub-Issues:** Use only when owner, repo, and issue number are all given.
69+
4970
5071
Decision rules:
51-
- Prefer list-style tools when the query targets a specific repo or issue.
52-
- Prefer search when the user’s scope is broad or unspecified.
72+
- Prefer search when the user’s scope is broad or unspecified, or you don't have a repository name.
73+
- Always use list-style tools when the query provides a repo name or issue number.
5374
- Never infer missing identifiers.
75+
- Never call a tool when you do not have all the required parameters.
5476
5577
Examples:
5678
- “Open issues in `kagenti/agent-examples`” → list issues
5779
- “Find issues mentioning ‘timeout’ across all repos” → search issues
5880
- “Issue types for the `ibm` organization” → list issue types
5981
- “Sub-issues under #134 in `openai/triton`” → list sub-issues
82+
- "What issues are assigned to joe123?" → search issues
6083
6184
TOOL USE RULES
6285
- Use only the tools provided here.
6386
- Cite tool outputs or provided context; do not add outside knowledge.
6487
"""
6588

89+
INFO_PARSER_PROMPT = """
90+
You are an analyst that will extract out information from a user's instruction/query to determine the following information, if it exists:
91+
- Github owner or organization
92+
- Github repository
93+
- Issue number(s)
6694
67-
REPO_ID_BACKSTORY = """
68-
You are a judge determining whether a user’s request successfully identifies sufficient information to retrieve Github issues.
69-
70-
For a request to count as a successful identification, it must:
71-
- ✅ Explicitly name the an owner, which can be:
72-
- an organization name,
73-
- a username
74-
75-
✅ Positive Examples
76-
77-
- "summarize open issues across the foo organization" → Valid because the foo organization is identified.
78-
- "kagenti/agent-examples" → Identifies the kagenti organization.
79-
- "foo in the bar organization" → Identifies bar organization.
80-
- "the kubernetes organization" → Identifies the kubernetes organization.
81-
82-
❌ Negative Examples
83-
- "the kubernetes repo" → Invalid because it only specifies a repository name, not the owner or the organization.
84-
- "show me open issues" (with no owner or organization) → Invalid because no owner or organization is identified.
85-
86-
Your task is to return whether the user’s request meets these criteria.
95+
Examples:
96+
- "summarize open issues across the foo organization" → Owner: foo, Repo: None, Issues: None
97+
- "kagenti/agent-examples" → Owner: kagenti, Repo: agent-examples, Issues: None
98+
- "foo in the bar organization" → Owner: bar, Repo: foo, Issues: None
99+
- "Search across all of github/github-mcp-server for open issues with bug" → Owner: github, Repo: github-mcp-server, Issues: None
100+
- "How long has issue 2 in modelcontextprotocol/servers been open?" → Owner: modelcontextprotocol, Repo: servers, Issues: [2]
87101
"""

0 commit comments

Comments
 (0)