Skip to content
  • Auto
  • Light
  • Dark
DiscordForumGitHubSign up
View as Markdown
Copy Markdown

Open in Claude
Open in ChatGPT

Web Search

The web_search and fetch_webpage tools enables Letta agents to search the internet for current information, research, and general knowledge using Exa’s AI-powered search engine.

from letta import Letta
client = Letta(token="LETTA_API_KEY")
agent = client.agents.create(
model="openai/gpt-4o",
embedding="openai/text-embedding-3-small",
tools=["web_search"],
memory_blocks=[
{
"label": "persona",
"value": "I'm a research assistant who uses web search to find current information and cite sources."
}
]
)
response = client.agents.messages.create(
agent_id=agent.id,
messages=[
{
"role": "user",
"content": "What are the latest developments in agent-based AI systems?"
}
]
)

Your agent can now choose to use web_search when it needs current information.

For self-hosted Letta servers, you’ll need an Exa API key.

  1. Sign up at dashboard.exa.ai
  2. Copy your API key
  3. See Exa pricing for rate limits and costs
Terminal window
docker run \
-v ~/.letta/.persist/pgdata:/var/lib/postgresql/data \
-p 8283:8283 \
-e OPENAI_API_KEY="your_openai_key" \
-e EXA_API_KEY="your_exa_api_key" \
letta/letta:latest

The web_search tool supports advanced filtering and search customization:

ParameterTypeDefaultDescription
querystrRequiredThe search query to find relevant web content
num_resultsint10Number of results to return (1-100)
categorystrNoneFocus search on specific content types (see below)
include_textboolFalseWhether to retrieve full page content (usually overflows context)
include_domainsList[str]NoneList of domains to include in search results
exclude_domainsList[str]NoneList of domains to exclude from search results
start_published_datestrNoneOnly return content published after this date (ISO format)
end_published_datestrNoneOnly return content published before this date (ISO format)
user_locationstrNoneTwo-letter country code for localized results (e.g., “US”)

Use the category parameter to focus your search on specific content types:

CategoryBest ForExample Query
companyCorporate information, company websites”Tesla energy storage solutions”
research paperAcademic papers, arXiv, research publications”transformer architecture improvements 2025”
newsNews articles, current events”latest AI policy developments”
pdfPDF documents, reports, whitepapers”climate change impact assessment”
githubGitHub repositories, open source projects”python async web scraping libraries”
tweetTwitter/X posts, social media discussions”reactions to new GPT release”
personal siteBlogs, personal websites, portfolios”machine learning tutorial blogs”
linkedin profileLinkedIn profiles, professional bios”AI research engineers at Google”
financial reportEarnings reports, financial statements”Apple Q4 2024 earnings”

The tool returns a JSON-encoded string containing:

{
"query": "search query",
"results": [
{
"title": "Page title",
"url": "https://example.com",
"published_date": "2025-01-15",
"author": "Author name",
"highlights": ["Key excerpt 1", "Key excerpt 2"],
"summary": "AI-generated summary of the content",
"text": "Full page content (only if include_text=true)"
}
]
}

Provide clear instructions to your agent about when web search is appropriate:

memory_blocks=[
{
"label": "persona",
"value": "I'm a helpful assistant. I use web_search for current events, recent news, and topics requiring up-to-date information. I cite my sources."
}
]

Use web search for external/current information, and archival memory for your organization’s internal data:

# Create agent with both web_search and archival memory tools
agent = client.agents.create(
model="openai/gpt-4o",
embedding="openai/text-embedding-3-small",
tools=["web_search", "archival_memory_search", "archival_memory_insert"],
memory_blocks=[
{
"label": "persona",
"value": "I use web_search for current events and external research. I use archival_memory_search for company-specific information and internal documents."
}
]
)

See the Archival Memory documentation for more information.

Exa uses neural search that understands semantic meaning. Your agent will generally form good queries naturally, but you can improve results by guiding it to:

  • Be descriptive and specific: “Latest research on RLHF techniques for language models” is better than “RLHF research”
  • Focus on topics, not keywords: “How companies are deploying AI agents in customer service” works better than “AI agents customer service deployment”
  • Use natural language: The search engine understands conversational queries like “What are the environmental impacts of Bitcoin mining?”
  • Specify time ranges when relevant: Guide your agent to use date filters for time-sensitive queries

Example instruction in memory:

memory_blocks=[
{
"label": "search_strategy",
"value": "When searching, I craft clear, descriptive queries that focus on topics rather than keywords. I use the category and date filters when appropriate to narrow results."
}
]

By default, include_text is False to avoid context overflow. The tool returns highlights and AI-generated summaries instead, which are more concise:

memory_blocks=[
{
"label": "search_guidelines",
"value": "I avoid setting include_text=true unless specifically needed, as full text usually overflows the context window. Highlights and summaries are usually sufficient."
}
]
agent = client.agents.create(
model="openai/gpt-4o",
tools=["web_search"],
memory_blocks=[
{
"label": "persona",
"value": "I'm a research assistant. I search for relevant information, synthesize findings from multiple sources, and provide citations."
}
]
)
agent = client.agents.create(
model="openai/gpt-4o-mini",
tools=["web_search"],
memory_blocks=[
{
"label": "persona",
"value": "I monitor news and provide briefings on AI industry developments."
},
{
"label": "topics",
"value": "Focus: AI/ML, agent systems, LLM advancements"
}
]
)
agent = client.agents.create(
model="openai/gpt-4o",
tools=["web_search"],
memory_blocks=[
{
"label": "persona",
"value": "I help customers by checking documentation, service status pages, and community discussions for solutions."
}
]
)

Check:

  1. Tool is attached: "web_search" in agent’s tools list
  2. Instructions are clear about when to search
  3. Model has good tool-calling capabilities (GPT-4, Claude 3+)
# Verify tools
agent = client.agents.retrieve(agent_id=agent.id)
print([tool.name for tool in agent.tools])

If you see errors about missing API keys on self-hosted deployments:

Terminal window
# Check if set
echo $EXA_API_KEY
# Set for session
export EXA_API_KEY="your_exa_api_key"
# Docker example
docker run -e EXA_API_KEY="your_exa_api_key" letta/letta:latest
Use CaseToolWhy
Current events, newsweb_searchReal-time information
External researchweb_searchBroad internet access
Internal documentsArchival memoryFast, static data
User preferencesMemory blocksIn-context, instant
General knowledgePre-trained modelNo search needed
from letta import Letta
client = Letta(token="LETTA_API_KEY")
agent = client.agents.create(
model="openai/gpt-4o",
tools=["fetch_webpage"],
memory_blocks=[{
"label": "persona",
"value": "I can fetch and read webpages to answer questions about online content."
}]
)
ParameterTypeDescription
urlstrThe URL of the webpage to fetch

The tool returns webpage content as text/markdown.

With Exa API (if configured):

{
"title": "Page title",
"published_date": "2025-01-15",
"author": "Author name",
"text": "Full page content in markdown"
}

Fallback (without Exa): Returns markdown-formatted text extracted from the HTML.

The tool uses a multi-tier approach:

  1. Exa API (if EXA_API_KEY is configured): Uses Exa’s content extraction
  2. Trafilatura (fallback): Open-source text extraction to markdown
  3. Readability + html2text (final fallback): HTML cleaning and conversion

For enhanced fetching on self-hosted servers, optionally configure an Exa API key. Without it, the tool still works using open-source extraction.

Terminal window
docker run \
-e EXA_API_KEY="your_exa_api_key" \
letta/letta:latest
agent = client.agents.create(
model="openai/gpt-4o",
tools=["fetch_webpage", "web_search"],
memory_blocks=[{
"label": "persona",
"value": "I search for documentation with web_search and read it with fetch_webpage."
}]
)
agent = client.agents.create(
model="openai/gpt-4o",
tools=["fetch_webpage", "archival_memory_insert"],
memory_blocks=[{
"label": "persona",
"value": "I fetch articles and store key insights in archival memory for later reference."
}]
)
agent = client.agents.create(
model="openai/gpt-4o",
tools=["fetch_webpage"],
memory_blocks=[{
"label": "persona",
"value": "I fetch webpages and provide summaries of their content."
}]
)
Use CaseToolWhy
Read specific webpagefetch_webpageDirect URL access
Find webpages to readweb_searchDiscovery first
Read + search in oneweb_search with include_text=trueCombined operation
Multiple pagesfetch_webpageIterate over URLs