feat(agents): add autonomous web search and research agent - #136
feat(agents): add autonomous web search and research agent#136SurajsinghBayas wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a new a2a-search-agent under agents/ to act as an autonomous research assistant, providing web search and webpage-reading capabilities to an A2A/OpenAI-based agent runtime.
Changes:
- Introduces
SearchToolsetimplementingsearch_web(DuckDuckGo) andread_webpage(requests + BeautifulSoup extraction). - Adds an OpenAI agent definition (system prompt + tool wiring) and an
OpenAIAgentExecutorto orchestrate tool-calling loops. - Adds packaging and runtime assets (AgentCard, Dockerfile, docker-compose, pyproject, scripts, README).
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| agents/a2a-search-agent/src/search_toolset.py | Implements DuckDuckGo search and webpage text extraction tools. |
| agents/a2a-search-agent/src/openai_agent.py | Defines system prompt and exposes tools to the executor. |
| agents/a2a-search-agent/src/openai_agent_executor.py | Executes OpenAI chat loop with tool calling and A2A task updates. |
| agents/a2a-search-agent/src/main.py | CLI entrypoint wiring A2A server, agent card, and executor. |
| agents/a2a-search-agent/run_with_phoenix.sh | Convenience script to run the agent with Phoenix env vars. |
| agents/a2a-search-agent/README.md | Documentation for the agent (currently inconsistent with this agent’s purpose). |
| agents/a2a-search-agent/pyproject.toml | Python project metadata and dependencies for the agent. |
| agents/a2a-search-agent/Dockerfile | Container build/run configuration for the agent. |
| agents/a2a-search-agent/docker-compose.yml | Compose service definition for running the agent container. |
| agents/a2a-search-agent/AgentCard.json | A2A AgentCard metadata describing skills and capabilities. |
| agents/a2a-search-agent/.gitignore | Agent-local gitignore for Python build artifacts and environments. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| logger.info(f"Reading webpage URL: {url}") | ||
| try: | ||
| response = self.session.get(url, timeout=10) | ||
| response.raise_for_status() |
| # A2A Translator Agent | ||
|
|
||
| An intelligent translation agent built with A2A (Agent2Agent) SDK that can translate text and web page content using natural language. | ||
|
|
||
| ## Features | ||
|
|
||
| - **Text Translation**: Translate plain text between different languages | ||
| - **URL Content Translation**: Extract and translate content from web pages | ||
| - **Language Detection**: Automatically detect the language of text or web content | ||
| - **Multi-language Support**: Supports translation between multiple languages using Google Translate | ||
| - **Clean Web Content**: Extracts readable text from HTML pages, removing scripts and styling | ||
|
|
| #!/bin/bash | ||
|
|
||
| # Set environment variables for observability | ||
| export PHOENIX_PROJECT_NAME="a2a-search-agent" | ||
| export PHOENIX_API_KEY="your_phoenix_api_key_here" | ||
|
|
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 12 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (3)
agents/a2a-search-agent/src/search_toolset.py:46
read_webpagefetches arbitrary URLs without validating scheme/host, which enables SSRF (e.g., hitting localhost services) and non-HTTP schemes. Add basic URL validation (http/https only) and block localhost at minimum before issuing the request.
logger.info(f"Reading webpage URL: {url}")
try:
import socket
import ipaddress
agents/a2a-search-agent/README.md:5
- This README appears to be copied from the translator agent (title, description, feature list, and dependencies mention translation/Google Translate) and does not document the new web search agent. Update it to describe web search + webpage reading behavior, tools/skills, and correct dependencies.
# Web Search Agent
An autonomous research and web search agent for the Nasiko platform built using the A2A SDK.
## Capabilities
agents/a2a-search-agent/run_with_phoenix.sh:6
- The script exports a placeholder
PHOENIX_API_KEYvalue. This can lead to confusing behavior (sending invalid credentials) and encourages hardcoding secrets. Prefer readingPHOENIX_API_KEYfrom the environment and warning if it is unset.
# Ensure we run from the agent directory
cd "$(dirname "$0")" || exit 1
# Set environment variables for observability
| method = getattr(tool_instance, function_name) | ||
| result = method(**function_args) | ||
| # Check if the result is a coroutine and await it | ||
| if inspect.iscoroutine(result): | ||
| result = await result |
| # Add assistant's response to messages | ||
| messages.append( | ||
| { | ||
| "role": "assistant", | ||
| "content": message.content, | ||
| "tool_calls": message.tool_calls, | ||
| } | ||
| ) |
| function_name = tool_call.function.name | ||
| function_args = json.loads(tool_call.function.arguments) | ||
|
|
| skill = AgentSkill( | ||
| id="search_web", | ||
| name="Search Web", | ||
| description="Search the internet and read web pages to answer queries", | ||
| tags=["search", "web", "research", "url"], | ||
| examples=[ | ||
| "Search the web for the latest news on AI", | ||
| "Who won the Superbowl in 2024?", | ||
| ], | ||
| ) | ||
|
|
||
| # AgentCard for OpenAI-based agent | ||
| agent_card = AgentCard( | ||
| name="Web Search Agent", | ||
| description="An agent that can autonomously search the internet and read web pages to answer queries", | ||
| url=f"http://{host}:{port}/", | ||
| version="1.0.0", | ||
| default_input_modes=["text"], | ||
| default_output_modes=["text"], | ||
| capabilities=AgentCapabilities(streaming=True), | ||
| skills=[skill], | ||
| ) |
| RUN pip install --no-cache-dir \ | ||
| "a2a-sdk[http-server]>=0.3.0,<1.0.0" \ | ||
| click>=8.1.8 \ | ||
| httpx>=0.28.1 \ | ||
| openai>=1.57.0 \ | ||
| pydantic>=2.11.4 \ | ||
| python-dotenv>=1.1.0 \ | ||
| uvicorn>=0.34.2 \ | ||
| requests>=2.31.0 \ | ||
| beautifulsoup4>=4.12.0 \ | ||
| duckduckgo-search>=6.0.0 |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 12 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
agents/a2a-search-agent/Dockerfile:17
- Unquoted package specifiers like
click>=8.1.8will be parsed by/bin/shas output redirections (>), which can break the image build and create stray files. Quote each requirement (or use a requirements file) sopipreceives the full specifier.
RUN pip install --no-cache-dir \
"a2a-sdk[http-server]>=0.3.0,<1.0.0" \
click>=8.1.8 \
httpx>=0.28.1 \
openai>=1.57.0 \
pydantic>=2.11.4 \
python-dotenv>=1.1.0 \
uvicorn>=0.34.2 \
requests>=2.31.0 \
beautifulsoup4>=4.12.0 \
duckduckgo-search>=6.0.0
| response = self.session.get(url, timeout=10) | ||
| response.raise_for_status() | ||
|
|
||
| soup = BeautifulSoup(response.content, 'html.parser') |
| parsed_url = urlparse(url) | ||
| if parsed_url.scheme not in ("http", "https"): | ||
| raise ValueError("Only http and https schemes are supported.") | ||
|
|
||
| # Resolve the hostname to an IP address | ||
| try: | ||
| ip = socket.gethostbyname(parsed_url.hostname) | ||
| ip_obj = ipaddress.ip_address(ip) | ||
| if ip_obj.is_private or ip_obj.is_loopback or ip_obj.is_link_local: | ||
| raise ValueError(f"Access to private/local IP ({ip}) is blocked for security reasons.") | ||
| except socket.gaierror: | ||
| raise ValueError("Could not resolve hostname.") |
| ports: | ||
| - "5000" | ||
| tty: true |
|
|
||
| 3. Alternatively, run the agent using Python: | ||
| ```bash | ||
| pip install -r pyproject.toml |
Description
This PR introduces a new Web Search Agent (
a2a-search-agent) to theagents/directory. It is built using the A2A SDK and serves as an autonomous research assistant capable of searching the web and parsing detailed webpage content to answer queries.Key Features & Changes
AgentCard.json): Configured the agent withsearch-webandread-webpageskills.search_toolset.py): Implemented the core logic usingduckduckgo-searchto query the web andbeautifulsoup4to scrape and extract text from URLs.openai_agent.py): Added a tailored system prompt that instructs the LLM on how to iteratively search the web and synthesize long-form content.Dockerfile,docker-compose.yml, andpyproject.tomlto include all necessary scraping dependencies.Verification
pip.(Note to maintainers: This agent uses free packages like
duckduckgo-searchto avoid needing paid API keys for web search functionality).