Anthropic's Claude models natively parse and execute client-side tools. Supplying an ODEN web search tool equips Claude with verified live internet knowledge and attributed citations, hosted within the EU.
Define the Claude tool schema#
tools = [{
"name": "fetch_live_web_context",
"description": "Retrieve grounded factual web information and source metadata from the live European search index.",
"input_schema": {
"type": "object",
"properties": {
"search_query": {"type": "string", "description": "The specific question or topical phrase"}
},
"required": ["search_query"],
},
}]
Handle the tool_use block with XML tags#
Claude excels at parsing structured XML containers. Format the retrieved ODEN answer and citation metadata inside semantic XML tags:
import os, requests
from anthropic import Anthropic
client = Anthropic()
def search_oden_knowledge(topic: str) -> str:
res = requests.post(
"https://api.oden-api.com/search",
headers={"Authorization": f"Bearer {os.environ['ODEN_KEY']}"},
json={"query": topic, "include_snippets": True, "depth": "advanced"},
timeout=25,
)
res.raise_for_status()
payload = res.json()["results"]
ref_list = "\n".join(
f"[{i+1}] {c['title']} <{c['url']}>"
for i, c in enumerate(payload["citations"])
)
return (
f"<web_context>\n"
f"<summary>{payload.get('answer', '')}</summary>\n"
f"<citations>\n{ref_list}\n</citations>\n"
f"</web_context>"
)
messages = [{"role": "user", "content": "What are the latest 2026 corporate sustainability reporting deadlines in Sweden?"}]
resp = client.messages.create(model="claude-sonnet-5", max_tokens=1024, tools=tools, messages=messages)
if resp.stop_reason == "tool_use":
tool_use = next(b for b in resp.content if b.type == "tool_use")
result_context = search_oden_knowledge(tool_use.input["search_query"])
messages.append({"role": "assistant", "content": resp.content})
messages.append({"role": "user", "content": [{
"type": "tool_result",
"tool_use_id": tool_use.id,
"content": result_context,
}]})
final = client.messages.create(model="claude-sonnet-5", max_tokens=1024, tools=tools, messages=messages)
print("".join(b.text for b in final.content if b.type == "text"))
Claude thinking mode & reasoning token coordination#
When invoking Claude with extended thinking mode enabled, Claude can reason through complex search requirements, formulate multi-hop queries, and analyze contradictory web sources:
# Example configuring Anthropic client with thinking budget and tool use
response = client.messages.create(
model="claude-3-7-sonnet-20250219",
max_tokens=4096,
thinking={
"type": "enabled",
"budget_tokens": 2048
},
tools=tools,
messages=[{
"role": "user",
"content": "Synthesize recent legal interpretations of EU AI Act open source model exemptions."
}]
)
Forcing tool execution with tool_choice#
If your workflow requires guaranteed factual retrieval before Claude generates an answer, enforce tool execution using the tool_choice parameter:
# Enforce that Claude MUST execute the web_search tool
resp = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
tools=tools,
tool_choice={"type": "tool", "name": "web_search"},
messages=messages
)
System prompt recommendations for citation quality#
Instruct Claude explicitly to format and ground responses:
system_prompt = (
"You are a factual research assistant. When web search results are provided, "
"synthesize the findings concisely and attribute key facts with inline brackets [1], [2]. "
"If candidate search sources contain conflicting assertions, explicitly report the discrepancy."
)
Notes#
- Append the assistant's
tool_useturn and yourtool_resultbefore the follow-up call — Claude needs both to continue. - Ask Claude in the system prompt to cite the returned sources inline.
- ODEN answers in the query's language, which pairs well with Claude's multilingual output.
FAQ#
Does ODEN work with Claude's own web search tool?#
They are alternatives. Claude's built-in web tools are one option; ODEN is a dedicated, EU-hosted European alternative you control and meter yourself.
Can I stream Claude's final answer?#
Yes. Stream the final messages.create call as usual — ODEN's result is already in the message history by then. ODEN itself returns a complete response rather than streaming.
Which Claude models support tool use?#
The current Claude models all support tool use with the tools parameter shown above.