mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 12:43:16 +00:00
fix: add Exa web search tool [closes: OPE-29] (#1133)
* fix: add Exa web search tool * chore: update uv.lock for exa-py dependency * linting * chore: remove web_search from system prompt * chore: drop search_type and category params from web_search
This commit is contained in:
parent
87968ab813
commit
7d1004ad66
6 changed files with 91 additions and 0 deletions
|
|
@ -343,6 +343,9 @@ SLACK_BOT_USER_ID=""
|
|||
SLACK_BOT_USERNAME=""
|
||||
SLACK_SIGNING_SECRET=""
|
||||
|
||||
# === Exa (optional — enables web search tool) ===
|
||||
EXA_API_KEY="" # From https://dashboard.exa.ai
|
||||
|
||||
# === Sandbox (optional) ===
|
||||
DEFAULT_SANDBOX_TEMPLATE_NAME="" # Custom sandbox template name (default: deepagents-cli)
|
||||
DEFAULT_SANDBOX_TEMPLATE_IMAGE="" # Custom Docker image (default: python:3)
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ from .tools import (
|
|||
slack_thread_reply,
|
||||
submit_pr_review,
|
||||
update_pr_review,
|
||||
web_search,
|
||||
)
|
||||
from .utils.auth import resolve_github_token
|
||||
from .utils.model import make_model
|
||||
|
|
@ -416,6 +417,7 @@ async def get_agent(config: RunnableConfig) -> Pregel: # noqa: PLR0915
|
|||
tools=[
|
||||
http_request,
|
||||
fetch_url,
|
||||
web_search,
|
||||
commit_and_open_pr,
|
||||
linear_comment,
|
||||
linear_create_issue,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ from .linear_get_issue_comments import linear_get_issue_comments
|
|||
from .linear_list_teams import linear_list_teams
|
||||
from .linear_update_issue import linear_update_issue
|
||||
from .slack_thread_reply import slack_thread_reply
|
||||
from .web_search import web_search
|
||||
|
||||
__all__ = [
|
||||
"commit_and_open_pr",
|
||||
|
|
@ -40,4 +41,5 @@ __all__ = [
|
|||
"slack_thread_reply",
|
||||
"submit_pr_review",
|
||||
"update_pr_review",
|
||||
"web_search",
|
||||
]
|
||||
|
|
|
|||
63
agent/tools/web_search.py
Normal file
63
agent/tools/web_search.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
from exa_py import Exa
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def web_search(
|
||||
query: str,
|
||||
num_results: int = 5,
|
||||
include_contents: bool = True,
|
||||
) -> dict[str, Any]:
|
||||
"""Search the web using Exa to find relevant information.
|
||||
|
||||
Use this tool when you need to find documentation, code examples, GitHub repos,
|
||||
news, or research papers to help complete a task.
|
||||
|
||||
Args:
|
||||
query: The search query
|
||||
num_results: Number of results to return (default: 5)
|
||||
include_contents: Whether to include full page contents (default: True)
|
||||
|
||||
Returns:
|
||||
Dictionary containing:
|
||||
- success: Whether the search succeeded
|
||||
- results: Search results from Exa
|
||||
- error: Error message if something failed
|
||||
"""
|
||||
api_key = os.environ.get("EXA_API_KEY")
|
||||
if not api_key:
|
||||
logger.warning("exa_api_key_missing")
|
||||
return {
|
||||
"success": False,
|
||||
"error": "EXA_API_KEY is not configured. Please add it to your environment variables.",
|
||||
}
|
||||
|
||||
async def _search() -> dict[str, Any]:
|
||||
client = Exa(api_key=api_key)
|
||||
if include_contents:
|
||||
result = await asyncio.to_thread(
|
||||
client.search_and_contents,
|
||||
query,
|
||||
text=True,
|
||||
num_results=num_results,
|
||||
type="auto",
|
||||
)
|
||||
else:
|
||||
result = await asyncio.to_thread(
|
||||
client.search,
|
||||
query,
|
||||
num_results=num_results,
|
||||
type="auto",
|
||||
)
|
||||
return {"success": True, "results": str(result), "error": None}
|
||||
|
||||
try:
|
||||
return asyncio.run(_search())
|
||||
except Exception as e:
|
||||
logger.exception("web_search failed")
|
||||
return {"success": False, "results": None, "error": f"{type(e).__name__}: {e}"}
|
||||
|
|
@ -23,6 +23,7 @@ dependencies = [
|
|||
"langchain-daytona>=0.0.3",
|
||||
"langchain-modal>=0.0.2",
|
||||
"langchain-runloop>=0.0.3",
|
||||
"exa-py>=2.10.1",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
|
|
|
|||
20
uv.lock
generated
20
uv.lock
generated
|
|
@ -686,6 +686,24 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/97/a8/c070e1340636acb38d4e6a7e45c46d168a462b48b9b3257e14ca0e5af79b/environs-14.6.0-py3-none-any.whl", hash = "sha256:f8fb3d6c6a55872b0c6db077a28f5a8c7b8984b7c32029613d44cef95cfc0812", size = 17205, upload-time = "2026-02-20T04:02:07.299Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "exa-py"
|
||||
version = "2.10.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "httpcore" },
|
||||
{ name = "httpx" },
|
||||
{ name = "openai" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "python-dotenv" },
|
||||
{ name = "requests" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fb/bb/23c9f78edbf0e0d656839be7346a2f77b9caaae8cc3cb301012c46fd7dc5/exa_py-2.10.1.tar.gz", hash = "sha256:731958c2befc5fc82f031c93cfe7b3d55dc3b0e1bf32f83ec34d32a65ee31ba1", size = 53826, upload-time = "2026-03-25T00:50:49.286Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/8d/0665263aa8d51ef8e2a3955e2b56496add4879730451961b09610bbc7036/exa_py-2.10.1-py3-none-any.whl", hash = "sha256:e2174c932764fff747e84e9e6d0637eaa4a6503556014df73a3427f42cc9d6a7", size = 72270, upload-time = "2026-03-25T00:50:47.721Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastapi"
|
||||
version = "0.128.3"
|
||||
|
|
@ -1765,6 +1783,7 @@ source = { editable = "." }
|
|||
dependencies = [
|
||||
{ name = "cryptography" },
|
||||
{ name = "deepagents" },
|
||||
{ name = "exa-py" },
|
||||
{ name = "fastapi" },
|
||||
{ name = "httpx" },
|
||||
{ name = "langchain" },
|
||||
|
|
@ -1793,6 +1812,7 @@ dev = [
|
|||
requires-dist = [
|
||||
{ name = "cryptography", specifier = ">=41.0.0" },
|
||||
{ name = "deepagents", specifier = ">=0.4.3" },
|
||||
{ name = "exa-py", specifier = ">=2.10.1" },
|
||||
{ name = "fastapi", specifier = ">=0.104.0" },
|
||||
{ name = "httpx", specifier = ">=0.25.0" },
|
||||
{ name = "langchain", specifier = ">=1.2.9" },
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue