mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
49d69b3bf5
* Expose workflow as MCP Tool * Expose workflow as MCP Tool * Cleanup * PR feedback fixes * update changelog to include PR numner * Improvements to error handling. * Adding a sample project demonstrating how to setup Agents and Workflows together. * Ensure duplicate agent registrations are properly handled.
88 lines
4.7 KiB
C#
88 lines
4.7 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using Microsoft.Azure.Functions.Worker.Core.FunctionMetadata;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace Microsoft.Agents.AI.Hosting.AzureFunctions;
|
|
|
|
/// <summary>
|
|
/// Transforms function metadata by registering durable agent functions for each explicitly configured agent.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This transformer adds entity, HTTP, and MCP tool trigger functions for agents that have
|
|
/// explicit <see cref="FunctionsAgentOptions"/>. Agents auto-registered by workflows
|
|
/// (which lack explicit options) are handled by <see cref="DurableWorkflowsFunctionMetadataTransformer"/>.
|
|
/// </remarks>
|
|
internal sealed class DurableAgentFunctionMetadataTransformer : IFunctionMetadataTransformer
|
|
{
|
|
private readonly ILogger<DurableAgentFunctionMetadataTransformer> _logger;
|
|
private readonly IReadOnlyDictionary<string, Func<IServiceProvider, AIAgent>> _agents;
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private readonly IFunctionsAgentOptionsProvider _functionsAgentOptionsProvider;
|
|
|
|
public DurableAgentFunctionMetadataTransformer(
|
|
IReadOnlyDictionary<string, Func<IServiceProvider, AIAgent>> agents,
|
|
ILogger<DurableAgentFunctionMetadataTransformer> logger,
|
|
IServiceProvider serviceProvider,
|
|
IFunctionsAgentOptionsProvider functionsAgentOptionsProvider)
|
|
{
|
|
this._agents = agents ?? throw new ArgumentNullException(nameof(agents));
|
|
this._logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
this._serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
|
|
this._functionsAgentOptionsProvider = functionsAgentOptionsProvider ?? throw new ArgumentNullException(nameof(functionsAgentOptionsProvider));
|
|
}
|
|
|
|
public string Name => nameof(DurableAgentFunctionMetadataTransformer);
|
|
|
|
public void Transform(IList<IFunctionMetadata> original)
|
|
{
|
|
this._logger.LogTransformingFunctionMetadata(original.Count);
|
|
|
|
foreach (KeyValuePair<string, Func<IServiceProvider, AIAgent>> kvp in this._agents)
|
|
{
|
|
string agentName = kvp.Key;
|
|
|
|
// Only generate triggers for agents with explicit Functions agent options.
|
|
// Agents auto-registered by workflows are handled by DurableWorkflowsFunctionMetadataTransformer.
|
|
if (!this._functionsAgentOptionsProvider.TryGet(agentName, out FunctionsAgentOptions? agentTriggerOptions))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
this._logger.LogRegisteringTriggerForAgent(agentName, "entity");
|
|
original.Add(FunctionMetadataFactory.CreateEntityTrigger(agentName));
|
|
|
|
if (agentTriggerOptions.HttpTrigger.IsEnabled)
|
|
{
|
|
this._logger.LogRegisteringTriggerForAgent(agentName, "http");
|
|
original.Add(FunctionMetadataFactory.CreateHttpTrigger(agentName, $"agents/{agentName}/run", BuiltInFunctions.RunAgentHttpFunctionEntryPoint));
|
|
}
|
|
|
|
if (agentTriggerOptions.McpToolTrigger.IsEnabled)
|
|
{
|
|
AIAgent agent = kvp.Value(this._serviceProvider);
|
|
this._logger.LogRegisteringTriggerForAgent(agentName, "mcpTool");
|
|
original.Add(CreateMcpToolTrigger(agentName, agent.Description));
|
|
}
|
|
}
|
|
}
|
|
|
|
private static DefaultFunctionMetadata CreateMcpToolTrigger(string agentName, string? description)
|
|
{
|
|
return new DefaultFunctionMetadata
|
|
{
|
|
Name = $"{BuiltInFunctions.McpToolPrefix}{agentName}",
|
|
Language = "dotnet-isolated",
|
|
RawBindings =
|
|
[
|
|
$$"""{"name":"context","type":"mcpToolTrigger","direction":"In","toolName":"{{agentName}}","description":"{{description}}","toolProperties":"[{\"propertyName\":\"query\",\"propertyType\":\"string\",\"description\":\"The query to send to the agent.\",\"isRequired\":true,\"isArray\":false},{\"propertyName\":\"threadId\",\"propertyType\":\"string\",\"description\":\"Optional thread identifier.\",\"isRequired\":false,\"isArray\":false}]"}""",
|
|
"""{"name":"query","type":"mcpToolProperty","direction":"In","propertyName":"query","description":"The query to send to the agent","isRequired":true,"dataType":"String","propertyType":"string"}""",
|
|
"""{"name":"threadId","type":"mcpToolProperty","direction":"In","propertyName":"threadId","description":"The thread identifier.","isRequired":false,"dataType":"String","propertyType":"string"}""",
|
|
"""{"name":"client","type":"durableClient","direction":"In"}"""
|
|
],
|
|
EntryPoint = BuiltInFunctions.RunAgentMcpToolFunctionEntryPoint,
|
|
ScriptFile = BuiltInFunctions.ScriptFile,
|
|
};
|
|
}
|
|
}
|