How to Add Web Search to AutoGen Agents With the You.com MCP Server

TLDR: To add web search to an AutoGen agent, connect McpWorkbench to the You.com MCP server at https://api.you.com/mcp with a Bearer API key, pass the workbench to an AssistantAgent, and set reflect_on_tool_use=True so the agent writes an answer instead of echoing raw search output. AutoGen is in maintenance mode, but the server wiring works in any MCP client.
AutoGen is Microsoft's open source framework for multi-agent applications, and its autogen-ext package can hand an MCP server's tools to an agent. Check the project's status before you build on it. The AutoGen README says the project is in maintenance mode, will not receive new features or enhancements, and is community managed going forward. It tells new users to start with Microsoft Agent Framework, which it calls the successor and describes as interoperable over A2A and MCP, and it links a migration guide. The latest autogen-ext release on PyPI, 0.7.5, is dated September 30, 2025.
This guide fits teams already running AutoGen 0.7 that want live search in their agents. The MCP half, meaning the server URL, the key, and tool scoping, is the same in every client. Our You.com MCP server guide covers that setup, and What Is Model Context Protocol explains the protocol. One AutoGen default decides whether the first attempt works at all, so the examples set it explicitly, and every AutoGen class and parameter in them was checked against the 0.7.5 documentation and source.
What does the You.com MCP server give an AutoGen agent?
The server lives at https://api.you.com/mcp and exposes six tools: you-search, you-contents, you-research, you-finance, you-balance, and you-discover. There is no you-answer tool, so the Answer API is not reachable over MCP. A client sees a tool only when the path, the profile, and the allowlist all include it, per the You.com MCP server docs, and the bare URL lists four tools by default.
| Tool | What an AutoGen agent uses it for | Listed on the bare URL? |
|---|---|---|
you-search | Web and news search, with highlights or snippets for each result | Yes |
you-contents | Reads a URL the agent already chose, as markdown or HTML | Yes |
you-balance | Reports the account balance, which a research agent does not need | Yes |
you-discover | Searches for agents, MCP servers, and skills, and never installs or connects | Yes |
you-research | Runs the search, read, and synthesize loop itself and returns a cited answer | No: use /mcp/research or ?tools= |
you-finance | Runs finance research | No: use /mcp/finance or ?tools= |
For a research agent, ?tools=you-search,you-contents is the useful scope: search finds sources and contents reads the few worth citing. The docs note that this list leaves you-research off so the agent runs its own search-read-synthesize loop, which is the loop you are building in AutoGen, and it keeps unused tool definitions out of every model call. An X-Allowed-Tools header carries the same list and replaces the query parameter when both are set.
For keyed access, the remote server takes a Bearer API key or OAuth 2.1. AutoGen's StreamableHttpServerParams has fields for headers and timeouts but none for OAuth, so pass a key in the Authorization header. Without a key, ?profile=free exposes only you-search and you-discover at 100 queries per day, enough to check the wiring before you create a key on the You.com platform.
How do you install AutoGen with MCP support?
Pin the versions. Release 0.7.5 is the latest autogen-ext and autogen-agentchat on PyPI, both require Python 3.10 or later, and the mcp extra installs the MCP client library, version 1.11.0 or newer according to the package metadata.
pip install "autogen-agentchat==0.7.5" "autogen-ext[openai,mcp]==0.7.5"
export YDC_API_KEY="your-you-com-api-key"
export OPENAI_API_KEY="your-openai-api-key"
YDC_API_KEY is the variable name the You.com docs use for the API key in every sample. The examples use OpenAI's model client, as the AutoGen README does with gpt-4.1. Swap in another AutoGen model client if you prefer, as long as its model supports tool calling.
How do you connect an AssistantAgent to You.com search?
The README's MCP example uses McpWorkbench, so start there. The workbench opens one MCP session when the async with block starts and closes it when the block ends, and the agent receives it through workbench=.
import asyncio
import os
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_ext.tools.mcp import McpWorkbench, StreamableHttpServerParams
async def main() -> None:
server_params = StreamableHttpServerParams(
url="https://api.you.com/mcp?tools=you-search,you-contents",
headers={"Authorization": f"Bearer {os.environ['YDC_API_KEY']}"},
timeout=30.0,
sse_read_timeout=60.0,
)
model_client = OpenAIChatCompletionClient(model="gpt-4.1")
async with McpWorkbench(server_params) as workbench:
# Smoke test: fails here if the key is rejected or the tool list is wrong.
names = [tool["name"] for tool in await workbench.list_tools()]
if "you-search" not in names:
raise RuntimeError(f"you-search is not exposed; the server lists {names}")
agent = AssistantAgent(
"researcher",
model_client=model_client,
workbench=workbench,
system_message=(
"You are a research assistant. Search the web when a question needs "
"current facts, read a page only when a snippet is not enough, and "
"cite the URLs you used."
),
reflect_on_tool_use=True,
max_tool_iterations=4,
)
await Console(
agent.run_stream(
task="What does the microsoft/autogen README say about the project's status?"
)
)
await model_client.close()
if __name__ == "__main__":
asyncio.run(main())
Three settings do most of the work, and reflect_on_tool_use=True matters most. The AssistantAgent reference says the parameter is False unless you set an output type, and that when it is False the tool call results come back as the agent's final message. A search agent with the defaults would hand your user the raw tool output. With the flag set, the model makes a second pass over the results and writes the answer.
max_tool_iterations=4 raises the default of 1. With 1, the agent runs one round of tool calls and returns. Four lets it search, read a page with you-contents, and search again when the first pass missed. Raise it deliberately, because each iteration can issue another search. sse_read_timeout=60.0 replaces a 300-second default. The autogen-ext source passes it to the MCP client session as its read timeout, so a stalled request can otherwise wait five minutes.
The list_tools() call before the agent exists is a smoke test: it fails when the session cannot open and shows whether you-search is in the allowlist. The task is checkable on purpose, because the status of microsoft/autogen is on its README, so you can compare the agent's answer and citations with the source.
Workbench or tool adapters: which should you use?
The autogen-ext package offers three ways to hand MCP tools to an agent. They differ in how they hold sessions and where the tool list comes from.
| Approach | Session | Tool list | Choose it when |
|---|---|---|---|
McpWorkbench passed as workbench= | One session, open for the life of the async with block | Requested from the server before each model call | You want the pattern the README shows |
mcp_server_tools(params) passed as tools= | A new session for each tool call | Fixed when you call it | You want ordinary tool objects for every allowed tool, or want to mix them with local Python functions |
StreamableHttpMcpToolAdapter.from_server_params(params, "you-search") | A new session for each tool call | One tool, fixed at creation | You want exactly one named tool |
Both behaviors come from the 0.7.5 source. An adapter built without a session opens a new MCP session and runs initialize every time the tool runs, per the adapter base class. AssistantAgent asks each workbench for its tool list before every model call, per the agent source, and for McpWorkbench that is a tools/list request to the server, per the workbench source. Neither request is large next to a search, but you should accept them knowingly. You cannot mix the styles on one agent: passing both tools and workbench raises a ValueError.
The adapter route is still the shortest path to a single tool:
import os
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_ext.tools.mcp import StreamableHttpMcpToolAdapter, StreamableHttpServerParams
async def build_agent() -> AssistantAgent:
server_params = StreamableHttpServerParams(
url="https://api.you.com/mcp?tools=you-search",
headers={"Authorization": f"Bearer {os.environ['YDC_API_KEY']}"},
sse_read_timeout=60.0,
)
# Raises ValueError, listing the available tool names, if "you-search" is not exposed.
search_tool = await StreamableHttpMcpToolAdapter.from_server_params(
server_params, "you-search"
)
return AssistantAgent(
"researcher",
model_client=OpenAIChatCompletionClient(model="gpt-4.1"),
tools=[search_tool],
system_message="Search the web when a question needs current facts, and cite the URLs you used.",
reflect_on_tool_use=True,
max_tool_iterations=4,
)
If the allowlist does not contain the name, from_server_params raises ValueError and lists the tools it did find, so a typo fails at startup instead of mid-conversation. The You.com names are hyphenated, so you-search matches and you_search raises the same error.
How do you keep search results from flooding the context?
A tool result enters the conversation in full, so the size of a search response is your context budget. In a keyless probe of the free profile on October 6, 2026, one you-search call with no count returned 18 web results as a 46,047-character tool result. The tool's schema defaults count to 30 and lets the model change it, so by default the model decides how much text arrives.
The server can take that decision away from the model. The docs describe host-supplied overrides: X-Search-* headers apply to every call, win over model-supplied arguments, and map to fields such as count, extraction, and include_domains. In AutoGen they go in the headers dict of StreamableHttpServerParams. The same query, run three ways against the free profile, shows what they do:
| Setup (one query) | Web results | Tool result size |
|---|---|---|
| No overrides | 18 | 46,047 characters |
X-Search-Count: 3, model asks for count 20 | 3 | 38,122 characters |
X-Search-Count: 5 and X-Search-Extraction: none | 5 | 10,769 characters |
Two things follow. A host-side limit holds even when the model asks for more: the header won over a model-supplied count of 20. And count alone is not a size limit, because each result still carried highlights, 43 on the first result in the second probe. Setting extraction to none returns plain snippets and brought the third probe under a quarter of the first one's size, at the cost of the query-relevant passages that highlights provide. Start with highlights and a low count, and let the agent read the one or two pages that matter with you-contents. Sizes vary with the query, so treat the table as one measurement, not a budget.
The same mechanism can pin X-Search-Include-Domains, a field the model cannot set. In a probe with github.com,learn.microsoft.com, all eight results came from those two hosts. The docs add that include_domains cannot be combined with exclude_domains or boost_domains. These are search overrides, so if the agent must stay inside an allowlist, scope the tool list to you-search alone, as the snippet below does.
import os
from autogen_ext.tools.mcp import StreamableHttpServerParams
server_params = StreamableHttpServerParams(
url="https://api.you.com/mcp?tools=you-search",
headers={
"Authorization": f"Bearer {os.environ['YDC_API_KEY']}",
"X-Search-Count": "5",
"X-Search-Extraction": "none",
"X-Search-Include-Domains": "github.com,learn.microsoft.com",
},
sse_read_timeout=60.0,
)
How do you share search across several agents?
Search results are the heaviest content in a team's history, so decide who sees them. Giving every agent the tool multiplies searches and lets two agents answer the same question from different results. AutoGen's AgentTool keeps search in one place: a researcher agent owns the workbench, and a lead agent calls the researcher as a tool.
With return_value_as_last_message=True, the lead receives the researcher's final message as the tool result. The raw search results live in the researcher's tool-call events, which are not part of that return value, per the task runner source. The AgentTool reference also requires parallel tool calls to be off for the agent that calls an AgentTool, because agents keep internal state and cannot run concurrently, so the lead's model client sets parallel_tool_calls=False.
The researcher keeps its message history between delegations, because AssistantAgent maintains state across calls and AgentTool does not reset it. Left alone, every earlier search stays in its context. BufferedChatCompletionContext keeps the last N messages and drops a leading tool result so it never sends an orphaned one, which makes it a cheap bound. Size it to hold at least one full delegation: with four tool iterations that is about ten messages, which is why the example uses 10.
import asyncio
import os
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.tools import AgentTool
from autogen_agentchat.ui import Console
from autogen_core.model_context import BufferedChatCompletionContext
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_ext.tools.mcp import McpWorkbench, StreamableHttpServerParams
async def main() -> None:
server_params = StreamableHttpServerParams(
url="https://api.you.com/mcp?tools=you-search,you-contents",
headers={
"Authorization": f"Bearer {os.environ['YDC_API_KEY']}",
"X-Search-Count": "5",
},
sse_read_timeout=60.0,
)
researcher_client = OpenAIChatCompletionClient(model="gpt-4.1")
# AgentTool requires parallel tool calls to be off for the agent that calls it.
lead_client = OpenAIChatCompletionClient(model="gpt-4.1", parallel_tool_calls=False)
async with McpWorkbench(server_params) as workbench:
researcher = AssistantAgent(
"researcher",
description="Searches the live web and returns a short, sourced summary.",
model_client=researcher_client,
workbench=workbench,
system_message=(
"Answer the task in under 200 words. Search first, read a page only "
"when a snippet is not enough, and end with the source URLs."
),
reflect_on_tool_use=True,
max_tool_iterations=4,
model_context=BufferedChatCompletionContext(buffer_size=10),
)
lead = AssistantAgent(
"lead",
model_client=lead_client,
tools=[AgentTool(researcher, return_value_as_last_message=True)],
system_message=(
"You write the final answer. Delegate every question that needs "
"current web facts to the researcher, then answer in five sentences."
),
reflect_on_tool_use=True,
max_tool_iterations=3,
)
await Console(
lead.run_stream(
task="How do the AutoGen and Microsoft Agent Framework READMEs describe their own status?"
)
)
await researcher_client.close()
await lead_client.close()
if __name__ == "__main__":
asyncio.run(main())
The lead's reflect_on_tool_use=True and max_tool_iterations=3 follow the same logic as the single agent. With parallel calls off, the lead delegates one question per model response, so a multi-part task needs more than one iteration.
What fails, and where does the error show up?
Most search failures in AutoGen do not raise an exception in your code. They show up as text in the transcript or as a short tool list, so build the checks in.
- A missing key fails during the handshake. On October 6, 2026, a POST to the bare
/mcpendpoint with no Authorization header returned 401 with an OAuth Bearer challenge atinitialize, before any tool call. The workbench opens its session in a background task, so callawait workbench.list_tools()first, as the first example does, to surface that before the agent runs. - A wrong tool name or an empty tool list.
from_server_paramsraisesValueErrorand lists the tools it found. Scoping mistakes are quieter: the docs warn that/mcp/research?profile=freereturns no tools and no error. Reading the names fromlist_tools()catches both. - Tool errors arrive as conversation, not exceptions.
McpWorkbench.call_toolcatches exceptions and returns them as an error result, andAssistantAgentpasses that result to the model, which may retry or explain it away. A timeout, a rate limit, or a rejected argument looks like text unless you check for it. The helper below scans a run for failed tool calls. - The final message is raw JSON. That means
reflect_on_tool_useis False. Set it on every agent that calls a search tool. - Quotas and rate limits. The free profile stops at 100 queries per day, and the rate limits page documents 10 requests per second as the Web Search API default for self-serve accounts, with a 429 and a Retry-After header beyond it. Parallel tool calls can add up, so cap a researcher's concurrency.
- Untrusted content. What
you-searchreturns is the open web, so treat it as data, keep the tool list short, and pin domains where the task allows. Our guide to prompt injection and intent hijacking in AI agents covers what happens when an agent acts on what a page says.
The helper reads the is_error flag on the results inside each ToolCallExecutionEvent. Both run() and the result that Console returns carry those events in messages.
from autogen_agentchat.messages import ToolCallExecutionEvent
def failed_tool_calls(messages) -> list[str]:
"""Return the error text of every tool call that failed during a run."""
errors: list[str] = []
for message in messages:
if isinstance(message, ToolCallExecutionEvent):
errors.extend(item.content for item in message.content if item.is_error)
return errors
# After a run:
# result = await Console(agent.run_stream(task=task))
# errors = failed_tool_calls(result.messages)
# if errors:
# raise RuntimeError(f"Search failed: {errors[0][:200]}")
Call it after every run and alert on a non-empty list, so a quiet timeout does not become a confident answer built on nothing.
When should you skip MCP and call the API directly?
MCP suits an agent that decides when to search. If your pipeline needs the JSON itself, to store it, filter it, or score it, call the Web Search API directly. The REST endpoint takes the key in an X-API-Key header, not the Bearer header the MCP server uses, as the authentication docs show. The Web Search API guide covers the endpoint, pricing, and limits, the Python SDK guide covers a direct client, and agent tool calling with a search API shows how to wrap the API as a native tool without MCP.
Budget by search count. The billing page prices a Web Search API call at $5.00 per 1,000 as of October 2026, which is $0.005 per search, and adds $1.00 per 1,000 pages crawled live when you request full-page extraction. A question that triggers four searches costs about two cents in search calls before model tokens, which is the arithmetic behind keeping max_tool_iterations and count low. The billing page lists no separate MCP price, so check your usage in the platform against this estimate.
Related Guides
- How to Set Up the You.com MCP Server for Web Search in Any Client
- How to Build a CrewAI Web Search Tool With the You.com Web Search API
- How to Add Web Search to Agent Tool Calling With the You.com Web Search API
- What Is the You.com Web Search API? Endpoint, Pricing, and Limits
- What Is Model Context Protocol (MCP)?
Frequently Asked Questions
Yes. The autogen-ext package supports MCP over stdio, SSE, and Streamable HTTP through McpWorkbench, mcp_server_tools, and per-tool adapters, installed with the mcp extra. The hosted You.com server uses Streamable HTTP, so you connect with StreamableHttpServerParams. AutoGen itself is in maintenance mode, so read its README before you start a new project on it.
Use you-search, spelled with a hyphen. The bare https://api.you.com/mcp URL also lists you-contents, you-balance, and you-discover, so add ?tools=you-search,you-contents to expose only what a research agent needs. A wrong name passed to from_server_params raises a ValueError that lists the tools the server actually exposes.
For evaluation, yes. The keyless URL https://api.you.com/mcp?profile=free exposes you-search and you-discover at 100 queries per day, so you can check the wiring without an Authorization header. It does not include you-contents, and the You.com docs recommend an API key for anything beyond evaluation, so create one before you ship.
Only in maintenance mode. The AutoGen README says the project will not receive new features or enhancements and is community managed going forward. It points new users to Microsoft Agent Framework and links a migration guide. The latest autogen-ext release on PyPI is 0.7.5, from September 30, 2025, so pin that version if you stay on AutoGen.
LI Test
LI Test
Share Article:
Related resources.

What Is MCP Web Search? Live Results for Model Context Protocol Agents
October 12, 2026
Blog

How to Build LangGraph Integrations with the You.com Web Search API
October 7, 2026
Blog

How to Add Web Search to Flowise Agents With the You.com MCP Server
October 2, 2026
Blog


