Day 8 of 10
Wire your agent to Wikipedia and live data. Tools that touch the actual world.
Yesterday your agent read files on your machine. That is powerful. But the machine is still a closed room.
Today you open the window. Your agent fetches from Wikipedia. It pulls live data and synthesizes everything it found into something you can use.
The internet becomes a tool. Your agent decides when and how to use it.
The rule for external tools: keep them focused, make failures explicit, and never let a timeout crash your agent.
The rule for tool arguments: keep them simple strings. When a tool requires the model to generate a URL or structured data as input, function calling breaks. Both tools here take plain topic strings — the tool handles the API call internally.
Start with the imports:
import urllib.request
import urllib.parse
import urllib.error
import json
import os
import time
from strands import Agent, tool
from strands.models.openai import OpenAIModel
Tool 1 — quick summary:
@tool
def search_wikipedia(query: str) -> str:
"""Search Wikipedia and return a summary for the given topic or query."""
try:
encoded = urllib.parse.quote(query)
url = f"https://en.wikipedia.org/api/rest_v1/page/summary/{encoded}"
req = urllib.request.Request(url, headers={"User-Agent": "CourseBot/1.0"})
with urllib.request.urlopen(req, timeout=8) as r:
data = json.loads(r.read().decode())
title = data.get("title", "Unknown")
extract = data.get("extract", "No summary available.")
return f"**{title}**\n\n{extract}"
except urllib.error.HTTPError as e:
return f"Wikipedia returned {e.code} for '{query}'. Try a different search term."
except Exception as e:
return f"Search failed: {e}"
Tool 2 — full article detail:
@tool
def get_wikipedia_details(topic: str) -> str:
"""Get a longer, more detailed Wikipedia extract for a specific topic."""
try:
params = urllib.parse.urlencode({
"action": "query",
"prop": "extracts",
"explaintext": 1,
"redirects": 1,
"titles": topic,
"format": "json",
"exsentences": 20,
})
url = f"https://en.wikipedia.org/w/api.php?{params}"
req = urllib.request.Request(url, headers={"User-Agent": "CourseBot/1.0"})
with urllib.request.urlopen(req, timeout=8) as r:
data = json.loads(r.read().decode())
pages = data.get("query", {}).get("pages", {})
for page in pages.values():
if page.get("pageid", -1) == -1:
return f"No Wikipedia article found for '{topic}'. Try search_wikipedia instead."
extract = page.get("extract", "")
if extract:
return extract[:3000]
return f"No content found for '{topic}'. Try search_wikipedia instead."
except Exception as e:
return f"Search failed: {e}"
Test both directly before wiring them into the agent:
print(search_wikipedia("Indian Space Research Organisation"))
print(get_wikipedia_details("Indian Space Research Organisation"))
Notice: every tool returns a string even on failure. The model reads the error message and decides what to do next. Never raise exceptions from tools. Return them as information.
model = OpenAIModel(
client_args={
"api_key": os.environ.get("GROQ_API_KEY"),
"base_url": "https://api.groq.com/openai/v1",
},
model_id="llama-3.3-70b-versatile",
params={"parallel_tool_calls": False, "temperature": 0},
)
research_agent = Agent(
model=model,
tools=[search_wikipedia, get_wikipedia_details],
system_prompt="You are a research assistant. You have two tools: search_wikipedia for quick summaries and get_wikipedia_details for in-depth content. Use them to answer questions accurately."
)
response = research_agent("What is ISRO and what were its major milestones?")
print(response)
Watch what happens. The agent calls search_wikipedia for the overview, then calls get_wikipedia_details to pull the full article when it needs more depth. Two tools, one answer, all from live data.
Two things matter for reliable tool calling. First, the system prompt: phrases like “Always search before answering” force the model to call a tool even when it is uncertain — it generates malformed JSON and the API throws an error. Guide the model toward tools, do not command it. Second, temperature: set it to 0 for tool-calling agents. Higher temperature introduces randomness into the structured JSON the model must generate for each function call. At temperature 0, that output is deterministic and correct every time.
Knowing what your agent is doing matters for debugging and for showing others how it works.
def run_and_log(agent, question):
print(f"Question: {question}\n")
print("Agent working...\n")
start = time.time()
result = agent(question)
elapsed = round(time.time() - start, 2)
print(f"\nAnswer:\n{result}")
print(f"\nCompleted in {elapsed}s")
run_and_log(
research_agent,
"What is Chandrayaan-3 and why was it significant?"
)
Build a research agent that answers a question you actually have. Something you have been meaning to look up properly. Ask it at least three different questions. Try topics it might struggle with — something obscure, something recent.
A good agent tells you when it cannot find reliable information rather than making something up. Test that too.
Four days ago your agent read a file on your machine. Today it reads the internet.
The tools are still just Python functions. The agent is still the same loop. But the surface it can reach has expanded from your laptop to every Wikipedia article on the web. And the key design rule: keep tool arguments as simple strings. Never ask the model to generate a URL or structured data as input — that is where function calling breaks.
Tomorrow you wire everything together.