Overview
Claude's tool use feature allows it to call external APIs when additional information is needed. By integrating WikiRest, you can give Claude access to Wikipedia's knowledge base for more accurate, citation-backed responses.
Tool Definition
Define the WikiRest tool for Claude:
import anthropic
import requests
# WikiRest tool definition for Claude
WIKI_SEARCH_TOOL = {
"name": "search_wikipedia",
"description": "Search Wikipedia for factual information about any topic. Returns relevant passages with source URLs. Use this when you need accurate, citable information about people, places, events, concepts, science, history, etc.",
"input_schema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query to find relevant Wikipedia content"
},
"limit": {
"type": "integer",
"description": "Number of passages to return (1-10)",
"default": 5
}
},
"required": ["query"]
}
}
WIKIREST_API_KEY = "your_wikirest_api_key"
WIKIREST_URL = "https://api.wikirest.com/v1" Implementing the Tool Handler
Create the function that executes the tool:
def search_wikipedia(query: str, limit: int = 5) -> str:
"""Execute Wikipedia search and format results for Claude."""
response = requests.get(
f"{WIKIREST_URL}/search",
params={"q": query, "limit": limit},
headers={"X-API-Key": WIKIREST_API_KEY}
)
if response.status_code != 200:
return f"Error: Could not search Wikipedia (status {response.status_code})"
data = response.json()
hits = data.get("hits", [])
if not hits:
return f"No Wikipedia results found for: {query}"
# Format for Claude
results = []
for hit in hits:
result = f"## {hit['title']}"
if hit.get('section'):
result += f" - {hit['section']}"
result += f"\n\n{hit['text']}\n\nSource: {hit['url']}"
results.append(result)
return "\n\n---\n\n".join(results)
def handle_tool_call(tool_name: str, tool_input: dict) -> str:
"""Route tool calls to the appropriate handler."""
if tool_name == "search_wikipedia":
return search_wikipedia(
query=tool_input["query"],
limit=tool_input.get("limit", 5)
)
return f"Unknown tool: {tool_name}" Complete Integration
Here's the full Claude integration with tool use:
import anthropic
client = anthropic.Anthropic(api_key="your_anthropic_key")
def chat_with_wikipedia(user_message: str) -> str:
"""
Have a conversation with Claude that can search Wikipedia.
"""
messages = [{"role": "user", "content": user_message}]
# Initial request with tools
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
system="""You are a helpful assistant with access to Wikipedia search.
When you need factual information, use the search_wikipedia tool.
Always cite sources when using information from Wikipedia.
Prefer searching Wikipedia over relying on your training data for factual claims.""",
tools=[WIKI_SEARCH_TOOL],
messages=messages
)
# Handle tool use in a loop
while response.stop_reason == "tool_use":
# Find tool use blocks
tool_use_blocks = [
block for block in response.content
if block.type == "tool_use"
]
# Process each tool call
tool_results = []
for tool_use in tool_use_blocks:
result = handle_tool_call(tool_use.name, tool_use.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": tool_use.id,
"content": result
})
# Continue conversation with tool results
messages = [
{"role": "user", "content": user_message},
{"role": "assistant", "content": response.content},
{"role": "user", "content": tool_results}
]
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
tools=[WIKI_SEARCH_TOOL],
messages=messages
)
# Extract text from final response
text_blocks = [
block.text for block in response.content
if hasattr(block, 'text')
]
return "\n".join(text_blocks)
# Example usage
if __name__ == "__main__":
answer = chat_with_wikipedia(
"What are the main theories about how the pyramids were built?"
)
print(answer) Multi-Turn Conversations
Maintain conversation context across multiple turns:
class WikipediaChatbot:
"""A chatbot that maintains conversation history with Wikipedia access."""
def __init__(self, anthropic_key: str, wikirest_key: str):
self.client = anthropic.Anthropic(api_key=anthropic_key)
self.wikirest_key = wikirest_key
self.messages = []
def chat(self, user_message: str) -> str:
"""Send a message and get a response."""
self.messages.append({"role": "user", "content": user_message})
response = self.client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
system="You have Wikipedia access via search_wikipedia tool.",
tools=[WIKI_SEARCH_TOOL],
messages=self.messages
)
# Handle tool use loop
while response.stop_reason == "tool_use":
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = self._handle_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result
})
self.messages.append({"role": "assistant", "content": response.content})
self.messages.append({"role": "user", "content": tool_results})
response = self.client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
tools=[WIKI_SEARCH_TOOL],
messages=self.messages
)
# Save assistant response
self.messages.append({"role": "assistant", "content": response.content})
return self._extract_text(response.content)
def _handle_tool(self, name: str, inputs: dict) -> str:
if name == "search_wikipedia":
return self._search_wiki(inputs["query"], inputs.get("limit", 5))
return "Unknown tool"
def _search_wiki(self, query: str, limit: int) -> str:
response = requests.get(
f"{WIKIREST_URL}/search",
params={"q": query, "limit": limit},
headers={"X-API-Key": self.wikirest_key}
)
hits = response.json().get("hits", [])
return "\n\n".join([
f"**{h['title']}**\n{h['text']}\nSource: {h['url']}"
for h in hits
])
def _extract_text(self, content) -> str:
return "\n".join(
block.text for block in content if hasattr(block, 'text')
)
def clear_history(self):
"""Start a fresh conversation."""
self.messages = []
# Usage
bot = WikipediaChatbot(
anthropic_key="your_key",
wikirest_key="your_wikirest_key"
)
print(bot.chat("Tell me about the James Webb Space Telescope"))
print(bot.chat("What has it discovered so far?")) # Follows up on context Streaming Responses
Stream Claude's responses for better UX:
def chat_with_wikipedia_stream(user_message: str):
"""Stream Claude responses with Wikipedia search."""
messages = [{"role": "user", "content": user_message}]
# First, check if tools are needed (non-streaming)
initial_response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
tools=[WIKI_SEARCH_TOOL],
messages=messages
)
# Handle tool calls if needed
if initial_response.stop_reason == "tool_use":
tool_results = []
for block in initial_response.content:
if block.type == "tool_use":
result = handle_tool_call(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result
})
messages = [
{"role": "user", "content": user_message},
{"role": "assistant", "content": initial_response.content},
{"role": "user", "content": tool_results}
]
# Stream the final response
with client.messages.stream(
model="claude-sonnet-4-20250514",
max_tokens=4096,
messages=messages
) as stream:
for text in stream.text_stream:
yield text
# Usage
for token in chat_with_wikipedia_stream("What is dark matter?"):
print(token, end="", flush=True) Best Practices
Tips for Claude + WikiRest
- Descriptive tool definitions - Claude uses the description to decide when to search
- Include source URLs - Claude will cite them in responses
- Handle tool use loops - Claude may make multiple searches
- System prompt guidance - Tell Claude when to prefer Wikipedia over training data