Skip to content

Commit 17893aa

Browse files
committed
inject prompt if jira tool is detected
1 parent 3a07dcd commit 17893aa

File tree

3 files changed

+81
-40
lines changed

3 files changed

+81
-40
lines changed

bugzooka/analysis/prompts.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,20 @@
5151
),
5252
"assistant": "Here is a context-aware analysis of the most relevant failures:",
5353
}
54+
55+
# Jira tool prompt - used when Jira MCP tools are available
56+
JIRA_TOOL_PROMPT = {
57+
"system_suffix": (
58+
"\n\nIMPORTANT: You have access to JIRA search tools. After analyzing the error, "
59+
"ALWAYS search for related issues in JIRA using the search_jira_issues tool with the OCPBUGS project. "
60+
"Extract key error terms, component names, or operators from the log summary to search for similar issues. "
61+
"Include the top 3 most relevant JIRA issues in your final response under a 'Related JIRA Issues' section."
62+
),
63+
"user_suffix": (
64+
"\n- Related JIRA issues (search using search_jira_issues tool with OCPBUGS project "
65+
"and include the top 3 most relevant issues)"
66+
),
67+
"assistant_suffix": (
68+
"\n\n**Related JIRA Issues:**\n- <Top 3 relevant issues from JIRA search>"
69+
),
70+
}

bugzooka/integrations/gemini_client.py

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import ssl
44
import httpx
55
import json
6-
import asyncio
76

87
from openai import OpenAI
98
from langchain_core.utils.function_calling import convert_to_openai_tool
@@ -13,6 +12,7 @@
1312
INFERENCE_MAX_TOOL_ITERATIONS,
1413
)
1514
from bugzooka.integrations.inference import InferenceAPIUnavailableError
15+
from bugzooka.analysis.prompts import JIRA_TOOL_PROMPT
1616

1717

1818
logger = logging.getLogger(__name__)
@@ -127,10 +127,10 @@ async def execute_tool_call(tool_name, tool_args, available_tools):
127127
logger.info("Executing tool: %s with args: %s", tool_name, tool_args)
128128

129129
# Check if the tool is async (has coroutine attribute or ainvoke method)
130-
if hasattr(tool, 'coroutine') and tool.coroutine:
130+
if hasattr(tool, "coroutine") and tool.coroutine:
131131
# MCP tools have a coroutine attribute
132132
result = await tool.ainvoke(tool_args)
133-
elif hasattr(tool, 'ainvoke'):
133+
elif hasattr(tool, "ainvoke"):
134134
# Some tools have ainvoke method
135135
result = await tool.ainvoke(tool_args)
136136
else:
@@ -151,7 +151,7 @@ async def analyze_log_with_gemini(
151151
error_summary: str,
152152
model="gemini-2.0-flash",
153153
tools=None,
154-
max_iterations=None
154+
max_iterations=None,
155155
):
156156
"""
157157
Analyzes log summaries using Gemini API with product-specific prompts and optional tool calling.
@@ -171,26 +171,48 @@ async def analyze_log_with_gemini(
171171
gemini_client = GeminiClient()
172172

173173
prompt_config = product_config["prompt"][product]
174+
175+
# Check if Jira MCP tools are available and inject Jira prompt
176+
has_jira = tools and any(
177+
hasattr(t, "name") and t.name == "search_jira_issues" for t in tools
178+
)
179+
if has_jira:
180+
logger.info("Jira MCP tools detected - injecting Jira prompt")
181+
system_prompt = prompt_config["system"] + JIRA_TOOL_PROMPT["system_suffix"]
182+
user_suffix = JIRA_TOOL_PROMPT["user_suffix"]
183+
assistant_suffix = JIRA_TOOL_PROMPT["assistant_suffix"]
184+
else:
185+
system_prompt = prompt_config["system"]
186+
user_suffix = ""
187+
assistant_suffix = ""
188+
174189
try:
175-
formatted_content = prompt_config["user"].format(
176-
error_summary=error_summary
190+
formatted_content = (
191+
prompt_config["user"].format(error_summary=error_summary) + user_suffix
177192
)
178193
except KeyError:
179-
formatted_content = prompt_config["user"].format(summary=error_summary)
194+
formatted_content = (
195+
prompt_config["user"].format(summary=error_summary) + user_suffix
196+
)
180197

181198
messages = [
182-
{"role": "system", "content": prompt_config["system"]},
199+
{"role": "system", "content": system_prompt},
183200
{"role": "user", "content": formatted_content},
184-
{"role": "assistant", "content": prompt_config["assistant"]},
201+
{
202+
"role": "assistant",
203+
"content": prompt_config["assistant"] + assistant_suffix,
204+
},
185205
]
186206

187207
# Convert LangChain tools to OpenAI format if provided
188208
openai_tools = None
189209
if tools:
190210
openai_tools = convert_langchain_tools_to_openai_format(tools)
191-
logger.info("Enabled %d tools for Gemini: %s",
192-
len(openai_tools),
193-
[t["function"]["name"] for t in openai_tools])
211+
logger.info(
212+
"Enabled %d tools for Gemini: %s",
213+
len(openai_tools),
214+
[t["function"]["name"] for t in openai_tools],
215+
)
194216

195217
# Tool calling loop - iterate until we get a final answer or hit max iterations
196218
iteration = 0
@@ -214,7 +236,7 @@ async def analyze_log_with_gemini(
214236
response_message = response.choices[0].message
215237

216238
# Check if Gemini wants to call tools
217-
tool_calls = getattr(response_message, 'tool_calls', None)
239+
tool_calls = getattr(response_message, "tool_calls", None)
218240

219241
if not tool_calls:
220242
# No tool calls - we have the final answer
@@ -229,21 +251,23 @@ async def analyze_log_with_gemini(
229251
logger.info("Gemini requested %d tool call(s)", len(tool_calls))
230252

231253
# Add the assistant's message with tool calls to conversation
232-
messages.append({
233-
"role": "assistant",
234-
"content": response_message.content or "",
235-
"tool_calls": [
236-
{
237-
"id": tc.id,
238-
"type": "function",
239-
"function": {
240-
"name": tc.function.name,
241-
"arguments": tc.function.arguments
254+
messages.append(
255+
{
256+
"role": "assistant",
257+
"content": response_message.content or "",
258+
"tool_calls": [
259+
{
260+
"id": tc.id,
261+
"type": "function",
262+
"function": {
263+
"name": tc.function.name,
264+
"arguments": tc.function.arguments,
265+
},
242266
}
243-
}
244-
for tc in tool_calls
245-
]
246-
})
267+
for tc in tool_calls
268+
],
269+
}
270+
)
247271

248272
# Execute each tool call and add results to messages
249273
for tool_call in tool_calls:
@@ -256,25 +280,25 @@ async def analyze_log_with_gemini(
256280
else:
257281
# Execute the tool (await since it's now async)
258282
function_result = await execute_tool_call(
259-
function_name,
260-
function_args,
261-
tools
283+
function_name, function_args, tools
262284
)
263285

264286
# Add tool result to messages
265-
messages.append({
266-
"role": "tool",
267-
"tool_call_id": tool_call.id,
268-
"name": function_name,
269-
"content": function_result
270-
})
287+
messages.append(
288+
{
289+
"role": "tool",
290+
"tool_call_id": tool_call.id,
291+
"name": function_name,
292+
"content": function_result,
293+
}
294+
)
271295

272296
# Continue loop to let Gemini process tool results
273297

274298
# If we hit max iterations without a final answer
275299
logger.warning(
276300
"Reached maximum tool calling iterations (%d) without final answer",
277-
max_iterations
301+
max_iterations,
278302
)
279303
return "Analysis incomplete: Maximum tool calling iterations reached. Please try again with a simpler query."
280304

prompts.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"OPENSHIFT_PROMPT": {
3-
"system": "You are an expert in OpenShift, Kubernetes, and cloud infrastructure. Your task is to analyze logs and summaries related to OpenShift environments. Given a log summary, identify the root cause, potential fixes, and affected components. Be as consise as possible (under 5000 characters), but precise and avoid generic troubleshooting steps. Prioritize OpenShift-specific debugging techniques. Keep in mind that the cluster is ephemeral and is destroyed after the build is complete, but all relevant logs and metrics are available. Use markdown formatting for the output with only one level of bullet points, do not use bold text except for the headers.\n\nIMPORTANT: You have access to JIRA search tools. After analyzing the error, ALWAYS search for related issues in JIRA using the search_jira_issues tool with the OCPBUGS project. Extract key error terms, component names, or operators from the log summary to search for similar issues. Include the top 3 most relevant JIRA issues in your final response under a 'Related JIRA Issues' section.",
4-
"user": "Here is the log summary from an OpenShift environment:\n\n{summary}\n\nBased on this summary, provide a structured breakdown of:\n- The OpenShift component likely affected (e.g., etcd, kube-apiserver, ingress, SDN, Machine API)\n- The probable root cause\n- Steps to verify the issue further\n- Suggested resolution, including OpenShift-specific commands or configurations\n- Related JIRA issues (search using search_jira_issues tool with OCPBUGS project and include the top 3 most relevant issues)",
5-
"assistant": "**Affected Component:** <Identified component>\n\n**Probable Root Cause:** <Describe why this issue might be occurring>\n\n**Verification Steps:**\n- <Step 1>\n- <Step 2>\n- <Step 3>\n\n**Suggested Resolution:**\n- <OpenShift CLI commands>\n- <Relevant OpenShift configurations>\n\n**Related JIRA Issues:**\n- <Top 3 relevant issues from JIRA search>"
3+
"system": "You are an expert in OpenShift, Kubernetes, and cloud infrastructure. Your task is to analyze logs and summaries related to OpenShift environments. Given a log summary, identify the root cause, potential fixes, and affected components. Be as consise as possible (under 5000 characters), but precise and avoid generic troubleshooting steps. Prioritize OpenShift-specific debugging techniques. Keep in mind that the cluster is ephemeral and is destroyed after the build is complete, but all relevant logs and metrics are available. Use markdown formatting for the output with only one level of bullet points, do not use bold text except for the headers.",
4+
"user": "Here is the log summary from an OpenShift environment:\n\n{summary}\n\nBased on this summary, provide a structured breakdown of:\n- The OpenShift component likely affected (e.g., etcd, kube-apiserver, ingress, SDN, Machine API)\n- The probable root cause\n- Steps to verify the issue further\n- Suggested resolution, including OpenShift-specific commands or configurations",
5+
"assistant": "**Affected Component:** <Identified component>\n\n**Probable Root Cause:** <Describe why this issue might be occurring>\n\n**Verification Steps:**\n- <Step 1>\n- <Step 2>\n- <Step 3>\n\n**Suggested Resolution:**\n- <OpenShift CLI commands>\n- <Relevant OpenShift configurations>"
66
},
77
"ANSIBLE_PROMPT": {
88
"system": "You are an expert in Ansible automation, playbook debugging, and infrastructure as code (IaC). Your task is to analyze log summaries related to Ansible execution, playbook failures, and task errors. Given a log summary, identify the root cause, affected tasks, and potential fixes. Prioritize Ansible-specific debugging techniques over generic troubleshooting.",

0 commit comments

Comments
 (0)