chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<InjectIsExternalInitOnLegacy>true</InjectIsExternalInitOnLegacy>
|
||||
<InjectSharedFoundryAgents>true</InjectSharedFoundryAgents>
|
||||
<InjectSharedWorkflowsExecution>true</InjectSharedWorkflowsExecution>
|
||||
<InjectSharedWorkflowsSettings>true</InjectSharedWorkflowsSettings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Workflows.Declarative\Microsoft.Agents.AI.Workflows.Declarative.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Workflows.Declarative.Foundry\Microsoft.Agents.AI.Workflows.Declarative.Foundry.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="InvokeFunctionTool.yaml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,55 @@
|
||||
#
|
||||
# This workflow demonstrates using InvokeFunctionTool to call functions directly
|
||||
# from the workflow without going through an AI agent first.
|
||||
#
|
||||
# InvokeFunctionTool allows workflows to:
|
||||
# - Pre-fetch data before calling an AI agent
|
||||
# - Execute operations directly without AI involvement
|
||||
# - Store function results in workflow variables for later use
|
||||
#
|
||||
# Example input:
|
||||
# What are the specials in the menu?
|
||||
#
|
||||
kind: Workflow
|
||||
trigger:
|
||||
|
||||
kind: OnConversationStart
|
||||
id: workflow_invoke_function_tool_demo
|
||||
actions:
|
||||
|
||||
# Invoke GetSpecials function to get today's specials directly from the workflow
|
||||
- kind: InvokeFunctionTool
|
||||
id: invoke_get_specials
|
||||
conversationId: =System.ConversationId
|
||||
requireApproval: true
|
||||
functionName: GetSpecials
|
||||
output:
|
||||
autoSend: true
|
||||
result: Local.Specials
|
||||
messages: Local.FunctionMessage
|
||||
|
||||
# Display a message showing we retrieved the specials
|
||||
- kind: SendMessage
|
||||
id: show_specials_intro
|
||||
message: "Today's specials have been retrieved. Here they are: {Local.Specials}"
|
||||
|
||||
# Now use an agent to format and present the specials to the user
|
||||
- kind: InvokeAzureAgent
|
||||
id: invoke_menu_agent
|
||||
conversationId: =System.ConversationId
|
||||
agent:
|
||||
name: FunctionMenuAgent
|
||||
input:
|
||||
messages: =UserMessage("Please describe today's specials in an appealing way.")
|
||||
output:
|
||||
messages: Local.AgentResponse
|
||||
|
||||
# Allow the user to ask follow-up questions in a loop
|
||||
- kind: InvokeAzureAgent
|
||||
id: invoke_followup
|
||||
conversationId: =System.ConversationId
|
||||
agent:
|
||||
name: FunctionMenuAgent
|
||||
input:
|
||||
externalLoop:
|
||||
when: =Upper(System.LastMessage.Text) <> "EXIT"
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Demo.Workflows.Declarative.InvokeFunctionTool;
|
||||
|
||||
#pragma warning disable CA1822 // Mark members as static
|
||||
|
||||
/// <summary>
|
||||
/// Plugin providing menu-related functions that can be invoked directly by the workflow
|
||||
/// using the InvokeFunctionTool action.
|
||||
/// </summary>
|
||||
public sealed class MenuPlugin
|
||||
{
|
||||
[Description("Provides a list items on the menu.")]
|
||||
public MenuItem[] GetMenu()
|
||||
{
|
||||
return s_menuItems;
|
||||
}
|
||||
|
||||
[Description("Provides a list of specials from the menu.")]
|
||||
public MenuItem[] GetSpecials()
|
||||
{
|
||||
return [.. s_menuItems.Where(i => i.IsSpecial)];
|
||||
}
|
||||
|
||||
[Description("Provides the price of the requested menu item.")]
|
||||
public float? GetItemPrice(
|
||||
[Description("The name of the menu item.")]
|
||||
string name)
|
||||
{
|
||||
return s_menuItems.FirstOrDefault(i => i.Name.Equals(name, StringComparison.OrdinalIgnoreCase))?.Price;
|
||||
}
|
||||
|
||||
private static readonly MenuItem[] s_menuItems =
|
||||
[
|
||||
new()
|
||||
{
|
||||
Category = "Soup",
|
||||
Name = "Clam Chowder",
|
||||
Price = 4.95f,
|
||||
IsSpecial = true,
|
||||
},
|
||||
new()
|
||||
{
|
||||
Category = "Soup",
|
||||
Name = "Tomato Soup",
|
||||
Price = 4.95f,
|
||||
IsSpecial = false,
|
||||
},
|
||||
new()
|
||||
{
|
||||
Category = "Salad",
|
||||
Name = "Cobb Salad",
|
||||
Price = 9.99f,
|
||||
},
|
||||
new()
|
||||
{
|
||||
Category = "Salad",
|
||||
Name = "House Salad",
|
||||
Price = 4.95f,
|
||||
},
|
||||
new()
|
||||
{
|
||||
Category = "Drink",
|
||||
Name = "Chai Tea",
|
||||
Price = 2.95f,
|
||||
IsSpecial = true,
|
||||
},
|
||||
new()
|
||||
{
|
||||
Category = "Drink",
|
||||
Name = "Soda",
|
||||
Price = 1.95f,
|
||||
},
|
||||
];
|
||||
|
||||
public sealed class MenuItem
|
||||
{
|
||||
public string Category { get; init; } = string.Empty;
|
||||
public string Name { get; init; } = string.Empty;
|
||||
public float Price { get; init; }
|
||||
public bool IsSpecial { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using OpenAI.Responses;
|
||||
using Shared.Foundry;
|
||||
using Shared.Workflows;
|
||||
|
||||
namespace Demo.Workflows.Declarative.InvokeFunctionTool;
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate a workflow that uses InvokeFunctionTool to call functions directly
|
||||
/// from the workflow without going through an AI agent first.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The InvokeFunctionTool action allows workflows to invoke function tools directly,
|
||||
/// enabling pre-fetching of data or executing operations before calling an AI agent.
|
||||
/// See the README.md file in the parent folder (../README.md) for detailed
|
||||
/// information about the configuration required to run this sample.
|
||||
/// </remarks>
|
||||
internal sealed class Program
|
||||
{
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
// Initialize configuration
|
||||
IConfiguration configuration = Application.InitializeConfig();
|
||||
Uri foundryEndpoint = new(configuration.GetValue(Application.Settings.FoundryEndpoint));
|
||||
|
||||
// Create the menu plugin with functions that can be invoked directly by the workflow
|
||||
MenuPlugin menuPlugin = new();
|
||||
AIFunction[] functions =
|
||||
[
|
||||
AIFunctionFactory.Create(menuPlugin.GetMenu),
|
||||
AIFunctionFactory.Create(menuPlugin.GetSpecials),
|
||||
AIFunctionFactory.Create(menuPlugin.GetItemPrice),
|
||||
];
|
||||
|
||||
// Ensure sample agent exists in Foundry
|
||||
await CreateAgentAsync(foundryEndpoint, configuration);
|
||||
|
||||
// Get input from command line or console
|
||||
string workflowInput = Application.GetInput(args);
|
||||
|
||||
// Create the workflow factory.
|
||||
WorkflowFactory workflowFactory = new("InvokeFunctionTool.yaml", foundryEndpoint);
|
||||
|
||||
// Execute the workflow
|
||||
WorkflowRunner runner = new(functions) { UseJsonCheckpoints = true };
|
||||
await runner.ExecuteAsync(workflowFactory.CreateWorkflow, workflowInput);
|
||||
}
|
||||
|
||||
private static async Task CreateAgentAsync(Uri foundryEndpoint, IConfiguration configuration)
|
||||
{
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
AIProjectClient aiProjectClient = new(foundryEndpoint, new DefaultAzureCredential());
|
||||
|
||||
await aiProjectClient.CreateAgentAsync(
|
||||
agentName: "FunctionMenuAgent",
|
||||
agentDefinition: DefineMenuAgent(configuration, []), // Create Agent with no function tool in the definition.
|
||||
agentDescription: "Provides information about the restaurant menu");
|
||||
}
|
||||
|
||||
private static DeclarativeAgentDefinition DefineMenuAgent(IConfiguration configuration, AIFunction[] functions)
|
||||
{
|
||||
DeclarativeAgentDefinition agentDefinition =
|
||||
new(configuration.GetValue(Application.Settings.FoundryModel))
|
||||
{
|
||||
Instructions =
|
||||
"""
|
||||
Answer the users questions about the menu.
|
||||
Use the information provided in the conversation history to answer questions.
|
||||
If the information is already available in the conversation, use it directly.
|
||||
For questions or input that do not require searching the documentation, inform the
|
||||
user that you can only answer questions about what's on the menu.
|
||||
"""
|
||||
};
|
||||
|
||||
foreach (AIFunction function in functions)
|
||||
{
|
||||
agentDefinition.Tools.Add(function.AsOpenAIResponseTool());
|
||||
}
|
||||
|
||||
return agentDefinition;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user