Skip to content

Commit 6d59e2e

Browse files
committed
multi agent web search using Haystack
1 parent 8832d77 commit 6d59e2e

2 files changed

Lines changed: 83 additions & 0 deletions

File tree

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
"""
2+
Haystack multi-agent web-search example, traced with Opik.
3+
4+
A coordinator agent delegates research questions to a scout agent, which in turn
5+
calls a SerperDev web-search tool. Opik traces the whole coordinator -> scout ->
6+
tool chain via `OpikConnector`.
7+
"""
8+
9+
import os
10+
from typing import Annotated
11+
12+
os.environ["HAYSTACK_CONTENT_TRACING_ENABLED"] = "true" # at top before importing Haystack modules
13+
14+
from haystack.components.agents import Agent
15+
from haystack.components.generators.chat import OpenAIChatGenerator
16+
from haystack.dataclasses import ChatMessage
17+
from haystack.tools import tool
18+
from opik.integrations.haystack import OpikConnector
19+
20+
import config
21+
from tool import build_web_search_tool
22+
23+
QUERY = "What was the final score and who won the FIFA World Cup 2026 championship?"
24+
25+
def build_coordinator() -> Agent:
26+
OpikConnector(name="haystack-multi-agent-scout", project_name=config.OPIK_PROJECT_NAME)
27+
28+
scout_agent = Agent(
29+
chat_generator=OpenAIChatGenerator(model=config.OPENAI_MODEL),
30+
tools=[build_web_search_tool()],
31+
system_prompt=(
32+
"You are a football scouting specialist covering the FIFA World Cup 2026. "
33+
"Search the web to find up-to-date information on teams, fixtures, venues, and knockout news"
34+
),
35+
)
36+
37+
@tool
38+
def scout(query: Annotated[str, "The World Cup 2026 research question to investigate"]) -> str:
39+
"""Research a FIFA World Cup 2026 topic and return a summary of findings."""
40+
try:
41+
result = scout_agent.run(messages=[ChatMessage.from_user(query)])
42+
return result["last_message"].text
43+
except Exception as e:
44+
return f"Scouting research failed: {e}"
45+
46+
return Agent(
47+
chat_generator=OpenAIChatGenerator(model=config.OPENAI_MODEL),
48+
tools=[scout],
49+
system_prompt=(
50+
"You are a World Cup 2026 coverage coordinator. Delegate research questions "
51+
"about teams, matches, venues, and players to the scout tool, then summarize the findings for a fan who wants the latest updates."
52+
),
53+
)
54+
55+
def run_agent(query: str) -> str:
56+
coordinator = build_coordinator()
57+
result = coordinator.run(messages=[ChatMessage.from_user(query)])
58+
return result["last_message"].text
59+
60+
def main() -> None:
61+
if config.DRY_RUN:
62+
print(
63+
"[DRY RUN] OpenAI / SerperDev / Opik credentials not set — would delegate this "
64+
f"query through the coordinator -> scout agent chain and trace it to Opik:\n {QUERY}"
65+
)
66+
return
67+
print(run_agent(QUERY))
68+
69+
if __name__ == "__main__":
70+
main()
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from haystack.tools import ComponentTool
2+
from haystack.utils import Secret
3+
from haystack_integrations.components.websearch.serperdev import SerperDevWebSearch
4+
5+
def build_web_search_tool(top_k: int = 4) -> ComponentTool:
6+
return ComponentTool(
7+
component=SerperDevWebSearch(
8+
api_key=Secret.from_env_var("SERPERDEV_API_KEY"),
9+
top_k=top_k,
10+
),
11+
name="web_search",
12+
description="Search the web for current information on any topic",
13+
)

0 commit comments

Comments
 (0)