mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 02:19:06 +00:00
.Net: Add agentic tool registration guide to SK -> AF migration. (#13464)
### Motivation and Context Addresses a gap in the SK → Agent Framework migration guide for scenarios where tools are added to the kernel after it's already built via `kernel.Plugins.Add()`. Referenced from [microsoft/agent-framework#3276](https://github.com/microsoft/agent-framework/issues/3276#issuecomment-3777591036). ### Description Adds a "Runtime Tool Registration Transformation" section to `SemanticKernelToAgentFramework.md` showing the middleware pattern for dynamic tool registration. **Semantic Kernel pattern:** ```csharp Kernel kernel = kernelBuilder.Build(); ChatCompletionAgent agent = new() { Kernel = kernel }; // Later: add tools post-creation KernelFunction function = KernelFunctionFactory.CreateFromMethod(GetWeather); KernelPlugin plugin = KernelPluginFactory.CreateFromFunctions("WeatherPlugin", [function]); kernel.Plugins.Add(plugin); ``` **Agent Framework equivalent:** ```csharp var augmentedAgent = existingAgent.AsBuilder() .Use(async (chatMessages, agentThread, agentRunOptions, next, cancellationToken) => { if (agentRunOptions is ChatClientAgentRunOptions opts) { opts.ChatOptions ??= new ChatOptions(); opts.ChatOptions.Tools ??= []; opts.ChatOptions.Tools.Add(AIFunctionFactory.Create(GetWeather)); } return await next(chatMessages, agentThread, agentRunOptions, cancellationToken); }) .Build(); ``` This middleware approach creates a dedicated augmented agent instance without disrupting existing usages. ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone 😄 <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > On SemanticKernelToAgentFramework.md, I got this valuable issue and I think worth adding a small piece of example in the migration when any tool is being added to the agent/kernel via instance level, providing the path suggested in the issue as a solution, mainly the option 1 provided by rogerbarreto. > > https://github.com/microsoft/agent-framework/issues/3276 </details> <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: rogerbarreto <[email protected]>
This commit is contained in:
@@ -384,6 +384,73 @@ AIAgent agent = chatClient.CreateAIAgent(
|
||||
7. Pass tools directly to agent creation method
|
||||
</configuration_changes>
|
||||
|
||||
### Runtime Tool Registration Transformation
|
||||
|
||||
<configuration_changes>
|
||||
In Semantic Kernel, plugins/tools could be added to the kernel after it was already built using `kernel.Plugins.Add()`. Agent Framework provides a similar capability using the builder middleware API.
|
||||
|
||||
**Replace this Semantic Kernel post-creation tool registration pattern:**
|
||||
```csharp
|
||||
// Define the tool function
|
||||
[Description("Get the weather for a location")]
|
||||
static string GetWeather(string location) => $"Weather in {location}";
|
||||
|
||||
// Semantic Kernel - Tools added after kernel is already built
|
||||
Kernel kernel = kernelBuilder.Build();
|
||||
ChatCompletionAgent agent = new() { Kernel = kernel };
|
||||
|
||||
// Later: Add tools to the existing kernel instance
|
||||
KernelFunction function = KernelFunctionFactory.CreateFromMethod(GetWeather);
|
||||
KernelPlugin plugin = KernelPluginFactory.CreateFromFunctions("WeatherPlugin", [function]);
|
||||
kernel.Plugins.Add(plugin);
|
||||
|
||||
// Tools are now available on subsequent invocations
|
||||
await foreach (var item in agent.InvokeAsync(userInput, thread)) { ... }
|
||||
```
|
||||
|
||||
**With this Agent Framework pattern using builder middleware:**
|
||||
```csharp
|
||||
// Define the tool function
|
||||
[Description("Get the weather for a location")]
|
||||
static string GetWeather(string location) => $"Weather in {location}";
|
||||
|
||||
// Start with an existing agent
|
||||
AIAgent existingAgent = chatClient.CreateAIAgent(
|
||||
instructions: "You are a helpful assistant");
|
||||
|
||||
// Create an augmented agent with additional tools using builder middleware
|
||||
var augmentedAgent = existingAgent.AsBuilder()
|
||||
.Use(async (chatMessages, agentThread, agentRunOptions, next, cancellationToken) =>
|
||||
{
|
||||
if (agentRunOptions is ChatClientAgentRunOptions chatClientAgentRunOptions)
|
||||
{
|
||||
chatClientAgentRunOptions.ChatOptions ??= new ChatOptions();
|
||||
chatClientAgentRunOptions.ChatOptions.Tools ??= [];
|
||||
chatClientAgentRunOptions.ChatOptions.Tools.Add(AIFunctionFactory.Create(GetWeather));
|
||||
}
|
||||
|
||||
return await next(chatMessages, agentThread, agentRunOptions, cancellationToken);
|
||||
})
|
||||
.Build();
|
||||
|
||||
// Use the augmented agent with the additional tools
|
||||
AgentRunResponse result = await augmentedAgent.RunAsync(userInput, thread);
|
||||
```
|
||||
|
||||
**Required changes:**
|
||||
1. Call `AsBuilder()` on the existing agent to get a builder
|
||||
2. Use the `Use()` middleware method to intercept and modify run options
|
||||
3. Add tools to `ChatClientAgentRunOptions.ChatOptions.Tools` in the middleware
|
||||
4. Call `Build()` to create the augmented agent instance
|
||||
5. Use the new augmented agent for invocations that need the additional tools
|
||||
|
||||
**Note:** This pattern is the preferred approach as it provides:
|
||||
- A controlled environment with a dedicated agent instance
|
||||
- No disruption to existing agent usages
|
||||
- Dynamic tool composition per user, tenant, or feature flags
|
||||
- Modular system composition without recreating agents
|
||||
</configuration_changes>
|
||||
|
||||
### Invocation Method Transformation
|
||||
|
||||
<api_changes>
|
||||
|
||||
Reference in New Issue
Block a user