import json
from openai import OpenAI
from exa_py import Exa
openai = OpenAI()
exa = Exa()
tools = [{"type":"function","function":{"name":"exa_search","description":"Search the web for current information.","parameters":{"type":"object","properties":{"query":{"type":"string","description":"Search query"}},"required":["query"]}}},
{"def exa_search(query:str)->str:
results = exa.search_and_contents(query,type="auto", num_results=10, text={"max_characters":20000})
return "\n".join([f"{r.title}: {r.url}" for r in results.results])
messages = [{"role":"user","content":"What's the latest in AI safety?"}]
response = openai.chat.completions.create(model="gpt-4o", messages=messages, tools=tools)
if response.choices[0].message.tool_calls:
tool_call = response.choices[0].message.tool_calls[0]
search_results = exa_search(json.loads(tool_call.function.arguments)["query"])
messages.append(response.choices[0].message)
messages.append({"role":"tool","tool_call_id": tool_call.id,"content": search_results})
final = openai.chat.completions.create(model="gpt-4o", messages=messages)
print(final.choices[0].message.content)
Anthropic Tool Use:
import anthropic
from exa_py import Exa
client = anthropic.Anthropic()
exa = Exa()
tools = [{"name":"exa_search","description":"Search the web for current information.","input_schema":{"type":"object","properties":{"query":{"type":"string","description":"Search query"}},"required":["query"]}}]
defexa_search(query:str)->str:
results = exa.search_and_contents(query,type="auto", num_results=10, text={"max_characters":20000})
return"\n".join([f"{r.title}: {r.url}"for r in results.results])
messages = [{"role":"user","content":"Latest quantum computing developments?"}]
response = client.messages.create(model="claude-sonnet-4-20250514", max_tokens=4096, tools=tools, messages=messages)
if response.stop_reason == "tool_use":
tool_use = next(b for b in response.content if b.type=="tool_use")
tool_result = exa_search(tool_use.input["query"])
messages.append({"role":"assistant","content": response.content})
messages.append({"role":"user","content":[{"type":"tool_result","tool_use_id": tool_use.id,"content": tool_result}]})
final = client.messages.create(model="claude-sonnet-4-20250514", max_tokens=4096, tools=tools, messages=messages)
print(final.content[0].text)
Search Type Reference
Type
Best For
Speed
Depth
fast
Real-time apps, autocomplete, quick lookups
Fastest
Basic
auto
Most queries - balanced relevance & speed
Medium
Smart
deep
Research, enrichment, thorough results
Slow
Deep
deep-reasoning
Complex research, multi-step reasoning
Slowest
Deepest
Tip: type="auto" works well for most queries. Use type="deep" when you need thorough research results.
Content Configuration
Choose ONE content type per request:
Type
Config
Best For
Text
"text": {"max_characters": 20000}
Full content extraction, RAG
Highlights
"highlights": {"max_characters": 4000}
Snippets, summaries, lower cost
Warning: Using text: true can significantly increase token count. Add max_characters limit or use highlights.