ci: Fix discussion answering agent

a. dump the discussion content to a tmp file first to avoid github redaction of environment variable
b. instruct the agent to use get_discussion_and_comments only when discussion content json is not available.

PiperOrigin-RevId: 805581573
This commit is contained in:
Xiang (Sean) Zhou
2025-09-10 17:33:54 -07:00
committed by Copybara-Service
parent f96f0ebd0d
commit 0bc2ee64e3
3 changed files with 101 additions and 52 deletions
+5 -5
View File
@@ -46,9 +46,9 @@ jobs:
REPO: 'adk-python' REPO: 'adk-python'
INTERACTIVE: 0 INTERACTIVE: 0
PYTHONPATH: contributing/samples PYTHONPATH: contributing/samples
DISCUSSION_JSON: ${{ toJson(github.event.discussion) }}
run: | run: |
# Replace single quotes with the sequence that allows them to be used in a single-quoted string # Write discussion data to temporary file to avoid secret masking issues
# This replaces ' with '\'', which ends the current single-quoted string, adds an escaped single quote, then starts a new single-quoted string cat > /tmp/discussion.json << 'EOF'
SAFE_JSON="${DISCUSSION_JSON//\'/\'\\\'\'}" ${{ toJson(github.event.discussion) }}
python -m adk_answering_agent.main --discussion '$SAFE_JSON' EOF
python -m adk_answering_agent.main --discussion-file /tmp/discussion.json
@@ -36,46 +36,77 @@ else:
" comment." " comment."
) )
root_agent = Agent( root_agent = Agent(
model="gemini-2.5-pro", model="gemini-2.5-pro",
name="adk_answering_agent", name="adk_answering_agent",
description="Answer questions about ADK repo.", description="Answer questions about ADK repo.",
instruction=f""" instruction=f"""
You are a helpful assistant that responds to questions from the GitHub repository `{OWNER}/{REPO}` You are a helpful assistant that responds to questions from the GitHub repository `{OWNER}/{REPO}`
based on information about Google ADK found in the document store. You can access the document store based on information about Google ADK found in the document store. You can access the document store
using the `VertexAiSearchTool`. using the `VertexAiSearchTool`.
When user specifies a discussion number, here are the steps: Here are the steps to help answer GitHub discussions:
1. Use the `get_discussion_and_comments` tool to get the details of the discussion including the comments.
2. Focus on the latest comment but reference all comments if needed to understand the context.
* If there is no comment at all, just focus on the discussion title and body.
3. If all the following conditions are met, try to add a comment to the discussion, otherwise, do not respond:
* The discussion is not closed.
* The latest comment is not from you or other agents (marked as "Response from XXX Agent").
* The latest comment is asking a question or requesting information.
4. Use the `VertexAiSearchTool` to find relevant information before answering.
* If you need infromation about Gemini API, ask the `gemini_assistant` agent to provide the information and references.
* You can call the `gemini_assistant` agent with multiple queries to find all the relevant information.
5. If you can find relevant information, use the `add_comment_to_discussion` tool to add a comment to the discussion.
6. If you post a comment, add the label {BOT_RESPONSE_LABEL} to the discussion using the `add_label_to_discussion` tool.
IMPORTANT: 1. **Determine data source**:
* {APPROVAL_INSTRUCTION} * If the user has provided complete discussion JSON data in the prompt,
* Your response should be based on the information you found in the document store. Do not invent use that data directly.
information that is not in the document store. Do not invent citations which are not in the document store. * If the user only provided a discussion number, use the
* **Be Objective**: your answer should be based on the facts you found in the document store, do not be misled by user's assumptions or user's understanding of ADK. `get_discussion_and_comments` tool to fetch the discussion details.
* If you can't find the answer or information in the document store, **do not** respond.
* Start with a short summary of your response in the comment as a TLDR, e.g. "**TLDR**: <your summary>". 2. **Analyze the discussion**:
* Have a divider line between the TLDR and your detail response. * Focus on the latest comment but reference all comments if needed to
* Do not respond to any other discussion except the one specified by the user. understand the context.
* Please include your justification for your decision in your output * If there is no comment at all, focus on the discussion title and body.
to the user who is telling with you.
* If you uses citation from the document store, please provide a footnote 3. **Decide whether to respond**:
referencing the source document format it as: "[1] publicly accessible HTTPS URL of the document". * If all the following conditions are met, try to add a comment to the
* You **should always** use the `convert_gcs_links_to_https` tool to convert GCS links (e.g. "gs://...") to HTTPS links. discussion, otherwise, do not respond:
* **Do not** use the `convert_gcs_links_to_https` tool for non-GCS links. - The discussion is not closed.
* Make sure the citation URL is valid. Otherwise do not list this specific citation. - The latest comment is not from you or other agents (marked as
""", "Response from XXX Agent").
- The discussion is asking a question or requesting information.
- The discussion is about ADK or related topics.
4. **Research the answer**:
* Use the `VertexAiSearchTool` to find relevant information before answering.
* If you need information about Gemini API, ask the `gemini_assistant` agent
to provide the information and references.
* You can call the `gemini_assistant` agent with multiple queries to find
all the relevant information.
5. **Post the response**:
* If you can find relevant information, use the `add_comment_to_discussion`
tool to add a comment to the discussion.
* If you post a comment, add the label {BOT_RESPONSE_LABEL} to the discussion
using the `add_label_to_discussion` tool.
IMPORTANT:
* {APPROVAL_INSTRUCTION}
* Your response should be based on the information you found in the document
store. Do not invent information that is not in the document store. Do not
invent citations which are not in the document store.
* **Be Objective**: your answer should be based on the facts you found in the
document store, do not be misled by user's assumptions or user's
understanding of ADK.
* If you can't find the answer or information in the document store,
**do not** respond.
* Start with a short summary of your response in the comment as a TLDR,
e.g. "**TLDR**: <your summary>".
* Have a divider line between the TLDR and your detail response.
* Please include your justification for your decision in your output
to the user who is telling with you.
* If you use citation from the document store, please provide a footnote
referencing the source document format it as: "[1] publicly accessible
HTTPS URL of the document".
* You **should always** use the `convert_gcs_links_to_https` tool to convert
GCS links (e.g. "gs://...") to HTTPS links.
* **Do not** use the `convert_gcs_links_to_https` tool for non-GCS links.
* Make sure the citation URL is valid. Otherwise do not list this specific
citation.
* Do not respond to any other discussion except the one specified by the user.
""",
tools=[ tools=[
VertexAiSearchTool(data_store_id=VERTEXAI_DATASTORE_ID), VertexAiSearchTool(data_store_id=VERTEXAI_DATASTORE_ID),
AgentTool(gemini_assistant_agent), AgentTool(gemini_assistant_agent),
@@ -132,6 +132,13 @@ def process_arguments():
help="Answer a discussion using provided JSON data from GitHub event.", help="Answer a discussion using provided JSON data from GitHub event.",
) )
group.add_argument(
"--discussion-file",
type=str,
metavar="FILE",
help="Answer a discussion using JSON data from a file.",
)
return parser.parse_args() return parser.parse_args()
@@ -155,9 +162,18 @@ async def main():
) )
return return
discussion_numbers = [discussion_number] discussion_numbers = [discussion_number]
elif args.discussion: elif args.discussion or args.discussion_file:
try: try:
discussion_data = json.loads(args.discussion) # Load discussion data from either argument or file
if args.discussion:
discussion_data = json.loads(args.discussion)
source_desc = "--discussion argument"
else: # args.discussion_file
with open(args.discussion_file, "r", encoding="utf-8") as f:
discussion_data = json.load(f)
source_desc = f"file {args.discussion_file}"
# Common validation and processing
discussion_number = discussion_data.get("number") discussion_number = discussion_data.get("number")
if not discussion_number: if not discussion_number:
print("Error: Discussion JSON missing 'number' field.", file=sys.stderr) print("Error: Discussion JSON missing 'number' field.", file=sys.stderr)
@@ -165,10 +181,12 @@ async def main():
discussion_numbers = [discussion_number] discussion_numbers = [discussion_number]
# Store the discussion data for later use # Store the discussion data for later use
discussion_json_data = discussion_data discussion_json_data = discussion_data
except FileNotFoundError:
print(f"Error: File not found: {args.discussion_file}", file=sys.stderr)
return
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
print( print(f"Error: Invalid JSON in {source_desc}: {e}", file=sys.stderr)
f"Error: Invalid JSON in --discussion argument: {e}", file=sys.stderr
)
return return
print(f"Will try to answer discussions: {discussion_numbers}...") print(f"Will try to answer discussions: {discussion_numbers}...")
@@ -189,16 +207,16 @@ async def main():
# If we have discussion JSON data, include it in the prompt # If we have discussion JSON data, include it in the prompt
# to avoid API call # to avoid API call
if args.discussion and discussion_json_data: if discussion_json_data:
title = discussion_json_data.get("title", "No title") import json
body = discussion_json_data.get("body", "No body")
author = discussion_json_data.get("author", {}).get("login", "Unknown") discussion_json_str = json.dumps(discussion_json_data, indent=2)
prompt = ( prompt = (
f"Please help answer this GitHub discussion #{discussion_number}:\n\n" f"Please help answer this GitHub discussion #{discussion_number}."
f"Title: {title}\n\n" " Here is the complete discussion"
f"Author: {author}\n\n" f" data:\n\n```json\n{discussion_json_str}\n```\n\nPlease analyze"
f"Body: {body}\n\n" " this discussion and provide a helpful response based on your"
"Please provide a helpful response based on your knowledge of ADK." " knowledge of ADK."
) )
else: else:
prompt = ( prompt = (