Skip to content

Commit 74f3c8c

Browse files
authored
Merge pull request #766 from eavanvalkenburg/bridge
Python: added docs on using the `as_af_tool` feature of SK
2 parents 433d458 + 685e95a commit 74f3c8c

2 files changed

Lines changed: 353 additions & 3 deletions

File tree

agent-framework/migration-guide/from-semantic-kernel/index.md

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ zone_pivot_groups: programming-languages
55
author: westey-m
66
ms.topic: reference
77
ms.author: westey
8-
ms.date: 09/25/2025
8+
ms.date: 11/11/2025
99
ms.service: agent-framework
1010
---
1111

@@ -528,6 +528,153 @@ print("Plugin state:", plugin.state)
528528
529529
This mechanism is also useful for tools that need additional input that cannot be supplied by the LLM, such as connections, secrets, etc.
530530

531+
### Compatibility: Using KernelFunction as Agent Framework tools
532+
533+
If you have existing Semantic Kernel code with `KernelFunction` instances (either from prompts or from methods), you can convert them to Agent Framework tools using the `.as_agent_framework_tool` method.
534+
535+
> [!IMPORTANT]
536+
> This feature requires `semantic-kernel` version 1.38 or higher.
537+
538+
#### Using KernelFunction from a prompt template
539+
540+
```python
541+
from semantic_kernel import Kernel
542+
from semantic_kernel.functions import KernelFunctionFromPrompt
543+
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion, OpenAIChatPromptExecutionSettings
544+
from semantic_kernel.prompt_template import KernelPromptTemplate, PromptTemplateConfig
545+
from agent_framework.openai import OpenAIResponsesClient
546+
547+
# Create a kernel with services and plugins
548+
kernel = Kernel()
549+
# will get the api_key and model_id from the environment
550+
kernel.add_service(OpenAIChatCompletion(service_id="default"))
551+
552+
# Create a function from a prompt template that uses plugin functions
553+
function_definition = """
554+
Today is: {{time.date}}
555+
Current time is: {{time.time}}
556+
557+
Answer to the following questions using JSON syntax, including the data used.
558+
Is it morning, afternoon, evening, or night (morning/afternoon/evening/night)?
559+
Is it weekend time (weekend/not weekend)?
560+
"""
561+
562+
prompt_template_config = PromptTemplateConfig(template=function_definition)
563+
prompt_template = KernelPromptTemplate(prompt_template_config=prompt_template_config)
564+
565+
# Create a KernelFunction from the prompt
566+
kernel_function = KernelFunctionFromPrompt(
567+
description="Determine the kind of day based on the current time and date.",
568+
plugin_name="TimePlugin",
569+
prompt_execution_settings=OpenAIChatPromptExecutionSettings(service_id="default", max_tokens=100),
570+
function_name="kind_of_day",
571+
prompt_template=prompt_template,
572+
)
573+
574+
# Convert the KernelFunction to an Agent Framework tool
575+
agent_tool = kernel_function.as_agent_framework_tool(kernel=kernel)
576+
577+
# Use the tool with an Agent Framework agent
578+
agent = OpenAIResponsesClient(model_id="gpt-4o").create_agent(tools=agent_tool)
579+
response = await agent.run("What kind of day is it?")
580+
print(response.text)
581+
```
582+
583+
#### Using KernelFunction from a method
584+
585+
```python
586+
from semantic_kernel.functions import kernel_function
587+
from agent_framework.openai import OpenAIResponsesClient
588+
589+
# Create a plugin class with kernel functions
590+
@kernel_function(name="get_weather", description="Get the weather for a location")
591+
def get_weather(self, location: str) -> str:
592+
return f"The weather in {location} is sunny."
593+
594+
# Get the KernelFunction and convert it to an Agent Framework tool
595+
agent_tool = get_weather.as_agent_framework_tool()
596+
597+
# Use the tool with an Agent Framework agent
598+
agent = OpenAIResponsesClient(model_id="gpt-4o").create_agent(tools=agent_tool)
599+
response = await agent.run("What's the weather in Seattle?")
600+
print(response.text)
601+
```
602+
603+
#### Using VectorStore with create_search_function
604+
605+
You can also use Semantic Kernel's VectorStore integrations with Agent Framework. The `create_search_function` method from a vector store collection returns a `KernelFunction` that can be converted to an Agent Framework tool.
606+
607+
```python
608+
from semantic_kernel import Kernel
609+
from semantic_kernel.connectors.ai.open_ai import OpenAITextEmbedding
610+
from semantic_kernel.connectors.azure_ai_search import AzureAISearchCollection
611+
from semantic_kernel.functions import KernelParameterMetadata
612+
from agent_framework.openai import OpenAIResponsesClient
613+
614+
# Define your data model
615+
class HotelSampleClass:
616+
HotelId: str
617+
HotelName: str
618+
Description: str
619+
# ... other fields
620+
621+
# Create an Azure AI Search collection
622+
collection = AzureAISearchCollection[str, HotelSampleClass](
623+
record_type=HotelSampleClass,
624+
embedding_generator=OpenAITextEmbedding()
625+
)
626+
627+
async with collection:
628+
await collection.ensure_collection_exists()
629+
# Load your records into the collection
630+
# await collection.upsert(records)
631+
632+
# Create a search function from the collection
633+
search_function = collection.create_search_function(
634+
description="A hotel search engine, allows searching for hotels in specific cities.",
635+
search_type="keyword_hybrid",
636+
filter=lambda x: x.Address.Country == "USA",
637+
parameters=[
638+
KernelParameterMetadata(
639+
name="query",
640+
description="What to search for.",
641+
type="str",
642+
is_required=True,
643+
type_object=str,
644+
),
645+
KernelParameterMetadata(
646+
name="city",
647+
description="The city that you want to search for a hotel in.",
648+
type="str",
649+
type_object=str,
650+
),
651+
KernelParameterMetadata(
652+
name="top",
653+
description="Number of results to return.",
654+
type="int",
655+
default_value=5,
656+
type_object=int,
657+
),
658+
],
659+
string_mapper=lambda x: f"(hotel_id: {x.record.HotelId}) {x.record.HotelName} - {x.record.Description}",
660+
)
661+
662+
# Convert the search function to an Agent Framework tool
663+
search_tool = search_function.as_agent_framework_tool()
664+
665+
# Use the tool with an Agent Framework agent
666+
agent = OpenAIResponsesClient(model_id="gpt-4o").create_agent(
667+
instructions="You are a travel agent that helps people find hotels.",
668+
tools=search_tool
669+
)
670+
response = await agent.run("Find me a hotel in Seattle")
671+
print(response.text)
672+
```
673+
674+
This pattern works with any Semantic Kernel VectorStore connector (Azure AI Search, Qdrant, Pinecone, etc.), allowing you to leverage your existing vector search infrastructure with Agent Framework agents.
675+
676+
This compatibility layer allows you to gradually migrate your code from Semantic Kernel to Agent Framework, reusing your existing `KernelFunction` implementations while taking advantage of Agent Framework's simplified agent creation and execution patterns.
677+
531678
## 6. Agent Non-Streaming Invocation
532679

533680
Key differences can be seen in the method names from `invoke` to `run`, return types (for example, `AgentRunResponse`) and parameters.

agent-framework/user-guide/agents/agent-rag.md

Lines changed: 205 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ zone_pivot_groups: programming-languages
55
author: westey-m
66
ms.topic: reference
77
ms.author: westey
8-
ms.date: 11/06/2025
8+
ms.date: 11/11/2025
99
ms.service: agent-framework
1010
---
1111

@@ -87,7 +87,210 @@ The `TextSearchProvider` class supports the following options via the `TextSearc
8787
::: zone-end
8888
::: zone pivot="programming-language-python"
8989

90-
More info coming soon.
90+
## Using Semantic Kernel VectorStore with Agent Framework
91+
92+
Agent Framework supports using Semantic Kernel's VectorStore collections to provide RAG capabilities to agents. This is achieved through the bridge functionality that converts Semantic Kernel search functions into Agent Framework tools.
93+
94+
> [!IMPORTANT]
95+
> This feature requires `semantic-kernel` version 1.38 or higher.
96+
97+
### Creating a Search Tool from VectorStore
98+
99+
The `create_search_function` method from a Semantic Kernel VectorStore collection returns a `KernelFunction` that can be converted to an Agent Framework tool using `.as_agent_framework_tool()`.
100+
Use [the vector store connectors documentation](/semantic-kernel/concepts/vector-store-connectors) to learn how to set up different vector store collections.
101+
102+
```python
103+
from semantic_kernel.connectors.ai.open_ai import OpenAITextEmbedding
104+
from semantic_kernel.connectors.azure_ai_search import AzureAISearchCollection
105+
from semantic_kernel.functions import KernelParameterMetadata
106+
from agent_framework.openai import OpenAIResponsesClient
107+
108+
# Define your data model
109+
class SupportArticle:
110+
article_id: str
111+
title: str
112+
content: str
113+
category: str
114+
# ... other fields
115+
116+
# Create an Azure AI Search collection
117+
collection = AzureAISearchCollection[str, SupportArticle](
118+
record_type=SupportArticle,
119+
embedding_generator=OpenAITextEmbedding()
120+
)
121+
122+
async with collection:
123+
await collection.ensure_collection_exists()
124+
# Load your knowledge base articles into the collection
125+
# await collection.upsert(articles)
126+
127+
# Create a search function from the collection
128+
search_function = collection.create_search_function(
129+
function_name="search_knowledge_base",
130+
description="Search the knowledge base for support articles and product information.",
131+
search_type="keyword_hybrid",
132+
parameters=[
133+
KernelParameterMetadata(
134+
name="query",
135+
description="The search query to find relevant information.",
136+
type="str",
137+
is_required=True,
138+
type_object=str,
139+
),
140+
KernelParameterMetadata(
141+
name="top",
142+
description="Number of results to return.",
143+
type="int",
144+
default_value=3,
145+
type_object=int,
146+
),
147+
],
148+
string_mapper=lambda x: f"[{x.record.category}] {x.record.title}: {x.record.content}",
149+
)
150+
151+
# Convert the search function to an Agent Framework tool
152+
search_tool = search_function.as_agent_framework_tool()
153+
154+
# Create an agent with the search tool
155+
agent = OpenAIResponsesClient(model_id="gpt-4o").create_agent(
156+
instructions="You are a helpful support specialist. Use the search tool to find relevant information before answering questions. Always cite your sources.",
157+
tools=search_tool
158+
)
159+
160+
# Use the agent with RAG capabilities
161+
response = await agent.run("How do I return a product?")
162+
print(response.text)
163+
```
164+
165+
### Customizing Search Behavior
166+
167+
You can customize the search function with various options:
168+
169+
```python
170+
# Create a search function with filtering and custom formatting
171+
search_function = collection.create_search_function(
172+
function_name="search_support_articles",
173+
description="Search for support articles in specific categories.",
174+
search_type="keyword_hybrid",
175+
# Apply filters to restrict search scope
176+
filter=lambda x: x.is_published == True,
177+
parameters=[
178+
KernelParameterMetadata(
179+
name="query",
180+
description="What to search for in the knowledge base.",
181+
type="str",
182+
is_required=True,
183+
type_object=str,
184+
),
185+
KernelParameterMetadata(
186+
name="category",
187+
description="Filter by category: returns, shipping, products, or billing.",
188+
type="str",
189+
type_object=str,
190+
),
191+
KernelParameterMetadata(
192+
name="top",
193+
description="Maximum number of results to return.",
194+
type="int",
195+
default_value=5,
196+
type_object=int,
197+
),
198+
],
199+
# Customize how results are formatted for the agent
200+
string_mapper=lambda x: f"Article: {x.record.title}\nCategory: {x.record.category}\nContent: {x.record.content}\nSource: {x.record.article_id}",
201+
)
202+
```
203+
204+
For the full details on the parameters available for `create_search_function`, see the [Semantic Kernel documentation](/semantic-kernel/concepts/vector-store-connectors/).
205+
206+
### Using Multiple Search Functions
207+
208+
You can provide multiple search tools to an agent for different knowledge domains:
209+
210+
```python
211+
# Create search functions for different knowledge bases
212+
product_search = product_collection.create_search_function(
213+
function_name="search_products",
214+
description="Search for product information and specifications.",
215+
search_type="semantic_hybrid",
216+
string_mapper=lambda x: f"{x.record.name}: {x.record.description}",
217+
).as_agent_framework_tool()
218+
219+
policy_search = policy_collection.create_search_function(
220+
function_name="search_policies",
221+
description="Search for company policies and procedures.",
222+
search_type="keyword_hybrid",
223+
string_mapper=lambda x: f"Policy: {x.record.title}\n{x.record.content}",
224+
).as_agent_framework_tool()
225+
226+
# Create an agent with multiple search tools
227+
agent = chat_client.create_agent(
228+
instructions="You are a support agent. Use the appropriate search tool to find information before answering. Cite your sources.",
229+
tools=[product_search, policy_search]
230+
)
231+
```
232+
233+
You can also create multiple search functions from the same collection with different descriptions and parameters to provide specialized search capabilities:
234+
235+
```python
236+
# Create multiple search functions from the same collection
237+
# Generic search for broad queries
238+
general_search = support_collection.create_search_function(
239+
function_name="search_all_articles",
240+
description="Search all support articles for general information.",
241+
search_type="semantic_hybrid",
242+
parameters=[
243+
KernelParameterMetadata(
244+
name="query",
245+
description="The search query.",
246+
type="str",
247+
is_required=True,
248+
type_object=str,
249+
),
250+
],
251+
string_mapper=lambda x: f"{x.record.title}: {x.record.content}",
252+
).as_agent_framework_tool()
253+
254+
# Detailed lookup for specific article IDs
255+
detail_lookup = support_collection.create_search_function(
256+
function_name="get_article_details",
257+
description="Get detailed information for a specific article by its ID.",
258+
search_type="keyword",
259+
top=1,
260+
parameters=[
261+
KernelParameterMetadata(
262+
name="article_id",
263+
description="The specific article ID to retrieve.",
264+
type="str",
265+
is_required=True,
266+
type_object=str,
267+
),
268+
],
269+
string_mapper=lambda x: f"Title: {x.record.title}\nFull Content: {x.record.content}\nLast Updated: {x.record.updated_date}",
270+
).as_agent_framework_tool()
271+
272+
# Create an agent with both search functions
273+
agent = chat_client.create_agent(
274+
instructions="You are a support agent. Use search_all_articles for general queries and get_article_details when you need full details about a specific article.",
275+
tools=[general_search, detail_lookup]
276+
)
277+
```
278+
279+
This approach allows the agent to choose the most appropriate search strategy based on the user's query.
280+
281+
### Supported VectorStore Connectors
282+
283+
This pattern works with any Semantic Kernel VectorStore connector, including:
284+
285+
- Azure AI Search (`AzureAISearchCollection`)
286+
- Qdrant (`QdrantCollection`)
287+
- Pinecone (`PineconeCollection`)
288+
- Redis (`RedisCollection`)
289+
- Weaviate (`WeaviateCollection`)
290+
- In-Memory (`InMemoryVectorStoreCollection`)
291+
- And more
292+
293+
Each connector provides the same `create_search_function` method that can be bridged to Agent Framework tools, allowing you to choose the vector database that best fits your needs. See [the full list here](/semantic-kernel/concepts/vector-store-connectors/out-of-the-box-connectors).
91294

92295
::: zone-end
93296

0 commit comments

Comments
 (0)