Bemærk
Adgang til denne side kræver godkendelse. Du kan prøve at logge på eller ændre mapper.
Adgang til denne side kræver godkendelse. Du kan prøve at ændre mapper.
Microsoft Agent Framework supports Retrieval Augmented Generation (RAG) through context providers that add retrieved content before model invocation and search tools that let the model retrieve grounding data on demand.
For conversation/session patterns alongside retrieval, see Conversations & Memory overview. For service-specific setup, see Azure AI Search, Microsoft Foundry, and Neo4j.
Using TextSearchProvider
The TextSearchProvider class is an out-of-the-box implementation of a RAG context provider.
It supports different modes of operation, e.g. doing a search for each agent run with chat history, or advertising function tools for doing searches.
It can easily be attached to a ChatClientAgent using the AIContextProviders option.
// Configure the options for the TextSearchProvider.
TextSearchProviderOptions textSearchOptions = new()
{
SearchTime = TextSearchProviderOptions.TextSearchBehavior.BeforeAIInvoke,
};
// Create the AI agent with the TextSearchProvider.
AIAgent agent = azureOpenAIClient
.GetChatClient(deploymentName)
.AsAIAgent(new ChatClientAgentOptions
{
ChatOptions = new() { Instructions = "You are a helpful support specialist. Answer questions using the provided context and cite the source document when available." },
AIContextProviders = [new TextSearchProvider(SearchAdapter, textSearchOptions)]
});
The TextSearchProvider requires a function that provides the search results given a query. This can be implemented using any search technology, e.g. Azure AI Search, or a web search engine.
Tip
See Vector store integrations for more information on how to use a vector store for search results.
Here is an example of a mock search function that returns pre-defined results based on the query.
SourceName and SourceLink are optional, but if provided will be used by the agent to cite the source of the information when answering the user's question.
static Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchAdapter(string query, CancellationToken cancellationToken)
{
// The mock search inspects the user's question and returns pre-defined snippets
// that resemble documents stored in an external knowledge source.
List<TextSearchProvider.TextSearchResult> results = new();
if (query.Contains("return", StringComparison.OrdinalIgnoreCase) || query.Contains("refund", StringComparison.OrdinalIgnoreCase))
{
results.Add(new()
{
SourceName = "Contoso Outdoors Return Policy",
SourceLink = "https://contoso.com/policies/returns",
Text = "Customers may return any item within 30 days of delivery. Items should be unused and include original packaging. Refunds are issued to the original payment method within 5 business days of inspection."
});
}
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>(results);
}
TextSearchProvider Options
The TextSearchProvider can be customized via the TextSearchProviderOptions class. Here is an example of creating options to run the search prior to every model invocation and keep a short rolling window of chat history for searches.
TextSearchProviderOptions textSearchOptions = new()
{
// Run the search prior to every model invocation and keep a short rolling window of chat history for searches.
SearchTime = TextSearchProviderOptions.TextSearchBehavior.BeforeAIInvoke,
RecentMessageMemoryLimit = 6,
};
The TextSearchProvider class supports the following options via the TextSearchProviderOptions class.
| Option | Type | Description | Default |
|---|---|---|---|
| SearchTime | TextSearchProviderOptions.TextSearchBehavior |
Indicates when the search should be executed. There are two options, each time the agent is run, or on-demand via function calling. | TextSearchProviderOptions.TextSearchBehavior.BeforeAIInvoke |
| FunctionToolName | string |
The name of the exposed search tool when operating in on-demand mode. | "Search" |
| FunctionToolDescription | string |
The description of the exposed search tool when operating in on-demand mode. | "Allows searching for additional information to help answer the user question." |
| ContextPrompt | string |
The context prompt prefixed to results. | "## Additional Context\nConsider the following information from source documents when responding to the user:" |
| CitationsPrompt | string |
The instruction appended after results to request citations. | "Include citations to the source document with document name and link if document name and link is available." |
| ContextFormatter | Func<IList<TextSearchProvider.TextSearchResult>, string> |
Optional delegate to fully customize formatting of the result list. If provided, ContextPrompt and CitationsPrompt are ignored. |
null |
| RecentMessageMemoryLimit | int |
The number of recent conversation messages (both user and assistant) to keep in memory and include when constructing the search input for BeforeAIInvoke searches. |
0 (disabled) |
| RecentMessageRolesIncluded | List<ChatRole> |
The list of ChatRole types to filter recent messages to when deciding which recent messages to include when constructing the search input. |
ChatRole.User |
Tip
See the .NET samples for complete runnable examples.
Agent Framework provides native vector-store contracts and
create_vector_search_tool(). The helper turns any
SupportsVectorSearch implementation into a function tool, so the model can
retrieve grounding data before it answers.
Create a native vector search tool
First, define your vector-store model, create a collection, and load its
records. The following sample uses InMemoryCollection with
OpenAIEmbeddingClient, but you can supply any native Agent Framework
collection that implements SupportsVectorSearch. It then exposes optional
category and rating filters to the model, maps each result to grounding text,
and instructs the agent to search before it answers:
import asyncio
import json
import os
from typing import Annotated, Any, Literal
from urllib.request import urlopen
from agent_framework import (
Agent,
Filter,
FilterGroup,
InMemoryCollection,
Param,
VectorStoreField,
create_vector_search_tool,
vectorstoremodel,
)
from agent_framework.openai import OpenAIChatClient, OpenAIEmbeddingClient
from dotenv import load_dotenv
async def main() -> None:
"""Create an in-memory hotel search tool and give it to an agent."""
api_key = os.environ["OPENAI_API_KEY"]
collection: InMemoryCollection[str, Hotel] = InMemoryCollection(
Hotel,
embedding_generator=OpenAIEmbeddingClient(
model="text-embedding-3-small",
api_key=api_key,
),
)
await collection.ensure_collection_exists()
# 1. Load the hotel records.
hotels = await asyncio.to_thread(load_hotels)
await collection.upsert(hotels)
# 2. Param values become optional model-visible filter arguments.
# When the allowed values are known, use Literal so the tool schema exposes
# them as an enum.
category = Param(
"category",
Literal["Boutique", "Budget", "Extended-Stay", "Luxury", "Resort and Spa", "Suite"],
description="Only return hotels in this category.",
)
min_rating = Param(
"min_rating",
float,
description="The minimum guest rating.",
minimum=0,
maximum=5,
)
tool = create_vector_search_tool(
collection,
description="Search the hotel dataset, optionally filtering by category and minimum rating.",
filter=FilterGroup(
"and",
(
Filter("category", "eq", category),
Filter("rating", "gte", min_rating),
),
),
result_mapper=lambda result: (
f"(hotel_id: {result['record'].hotel_id}) {result['record'].hotel_name} "
f"(rating {result['record'].rating}) - {result['record'].description}. "
f"Address: {result['record'].address.city}, {result['record'].address.country}."
),
)
# 3. The agent chooses whether to supply the exposed category and minimum-rating filters.
async with Agent(
client=OpenAIChatClient(
model="gpt-5.4-nano",
api_key=api_key,
),
name="HotelAgent",
instructions=(
"Always use the search tool to answer hotel questions. "
"Use category and minimum rating filters when the request provides them. "
"Include the hotel_id in the answer."
),
tools=[tool],
) as agent:
result = await agent.run("Find a resort and spa with a rating of at least 4.")
print(result)
The full sample defines the Hotel model and loads the source records before
the shown collection setup. Set OPENAI_API_KEY before you run it.
Customize search behavior
Configure create_vector_search_tool() with the following options:
| Option | Purpose |
|---|---|
name |
Sets the function name exposed to the model. Use a unique name when you add multiple search tools. |
description |
Explains when and why the model should use the tool. |
approval_mode |
Sets tool approval to always_require or never_require. |
search_type |
Selects vector or keyword_hybrid search. The collection must support the selected mode. |
top and skip |
Set fixed paging values or use typed Param values that the model supplies. |
filter |
Applies a portable Filter or FilterGroup. A filter can contain typed Param values exposed in the tool schema. |
result_mapper |
Converts each SearchResponse into text or multimodal Content for the model. |
The generated tool always includes a query string. Any Param values in the
filter, top, or skip settings become additional validated tool arguments.
Use Literal and numeric constraints to keep model-supplied values within the
range your application accepts.
You can create multiple tools for different collections or search modes. Give
each tool a distinct name and description so the model can select the
appropriate knowledge source.
Choose a native vector store
Native Python implementations are available for in-memory search, Azure AI Search, PostgreSQL with pgvector, Qdrant, and Redis. Their search modes, package lifecycle, installation commands, and limitations differ. See Vector store integrations to select and configure an implementation. That page also identifies databases that currently have only a separate Semantic Kernel connector.
Note
Go support for this feature is coming soon. See the Agent Framework Go repository for the latest status.
Graph RAG
For GraphRAG using graph traversal enriched search with Cypher queries, see the Neo4j GraphRAG Provider.