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'
INTERACTIVE: 0
PYTHONPATH: contributing/samples
DISCUSSION_JSON: ${{ toJson(github.event.discussion) }}
run: |
# Replace single quotes with the sequence that allows them to be used in a single-quoted string
# This replaces ' with '\'', which ends the current single-quoted string, adds an escaped single quote, then starts a new single-quoted string
SAFE_JSON="${DISCUSSION_JSON//\'/\'\\\'\'}"
python -m adk_answering_agent.main --discussion '$SAFE_JSON'
# Write discussion data to temporary file to avoid secret masking issues
cat > /tmp/discussion.json << 'EOF'
${{ toJson(github.event.discussion) }}
EOF
python -m adk_answering_agent.main --discussion-file /tmp/discussion.json
@@ -36,46 +36,77 @@ else:
" comment."
)
root_agent = Agent(
model="gemini-2.5-pro",
name="adk_answering_agent",
description="Answer questions about ADK repo.",
instruction=f"""
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
using the `VertexAiSearchTool`.
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
using the `VertexAiSearchTool`.
When user specifies a discussion number, here are the steps:
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.
Here are the steps to help answer GitHub discussions:
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.
* Do not respond to any other discussion except the one specified by the user.
* Please include your justification for your decision in your output
to the user who is telling with you.
* If you uses 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.
""",
1. **Determine data source**:
* If the user has provided complete discussion JSON data in the prompt,
use that data directly.
* If the user only provided a discussion number, use the
`get_discussion_and_comments` tool to fetch the discussion details.
2. **Analyze the discussion**:
* Focus on the latest comment but reference all comments if needed to
understand the context.
* If there is no comment at all, focus on the discussion title and body.
3. **Decide whether to respond**:
* 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 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=[
VertexAiSearchTool(data_store_id=VERTEXAI_DATASTORE_ID),
AgentTool(gemini_assistant_agent),
@@ -132,6 +132,13 @@ def process_arguments():
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()
@@ -155,9 +162,18 @@ async def main():
)
return
discussion_numbers = [discussion_number]
elif args.discussion:
elif args.discussion or args.discussion_file:
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")
if not discussion_number:
print("Error: Discussion JSON missing 'number' field.", file=sys.stderr)
@@ -165,10 +181,12 @@ async def main():
discussion_numbers = [discussion_number]
# Store the discussion data for later use
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:
print(
f"Error: Invalid JSON in --discussion argument: {e}", file=sys.stderr
)
print(f"Error: Invalid JSON in {source_desc}: {e}", file=sys.stderr)
return
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
# to avoid API call
if args.discussion and discussion_json_data:
title = discussion_json_data.get("title", "No title")
body = discussion_json_data.get("body", "No body")
author = discussion_json_data.get("author", {}).get("login", "Unknown")
if discussion_json_data:
import json
discussion_json_str = json.dumps(discussion_json_data, indent=2)
prompt = (
f"Please help answer this GitHub discussion #{discussion_number}:\n\n"
f"Title: {title}\n\n"
f"Author: {author}\n\n"
f"Body: {body}\n\n"
"Please provide a helpful response based on your knowledge of ADK."
f"Please help answer this GitHub discussion #{discussion_number}."
" Here is the complete discussion"
f" data:\n\n```json\n{discussion_json_str}\n```\n\nPlease analyze"
" this discussion and provide a helpful response based on your"
" knowledge of ADK."
)
else:
prompt = (