// Copyright (c) Microsoft. All rights reserved. using Azure.AI.Projects; using Azure.AI.Projects.Agents; using Azure.Identity; using Microsoft.Extensions.Configuration; using OpenAI.Responses; using Shared.Foundry; using Shared.Workflows; namespace Demo.Workflows.Declarative.InputArguments; /// /// Demonstrate a workflow that consumes input arguments to dynamically enhance the agent /// instructions. Exits the loop when the user enters "exit". /// /// /// See the README.md file in the parent folder (../README.md) for detailed /// information about the configuration required to run this sample. /// 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)); // Ensure sample agents exist in Foundry. await CreateAgentAsync(foundryEndpoint, configuration); // Get input from command line or console string workflowInput = Application.GetInput(args); // Create the workflow factory. This class demonstrates how to initialize a // declarative workflow from a YAML file. Once the workflow is created, it // can be executed just like any regular workflow. WorkflowFactory workflowFactory = new("InputArguments.yaml", foundryEndpoint); // Execute the workflow: The WorkflowRunner demonstrates how to execute // a workflow, handle the workflow events, and providing external input. // This also includes the ability to checkpoint workflow state and how to // resume execution. WorkflowRunner runner = new(); 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. // In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid // latency issues, unintended credential probing, and potential security risks from fallback mechanisms. AIProjectClient aiProjectClient = new(foundryEndpoint, new DefaultAzureCredential()); await aiProjectClient.CreateAgentAsync( agentName: "LocationTriageAgent", agentDefinition: DefineLocationTriageAgent(configuration), agentDescription: "Chats with the user to solicit a location of interest."); await aiProjectClient.CreateAgentAsync( agentName: "LocationCaptureAgent", agentDefinition: DefineLocationCaptureAgent(configuration), agentDescription: "Evaluate the status of soliciting the location."); await aiProjectClient.CreateAgentAsync( agentName: "LocationAwareAgent", agentDefinition: DefineLocationAwareAgent(configuration), agentDescription: "Chats with the user with location awareness."); } private static DeclarativeAgentDefinition DefineLocationTriageAgent(IConfiguration configuration) => new(configuration.GetValue(Application.Settings.FoundryModel)) { Instructions = """ Your only job is to solicit a location from the user. Always repeat back the location when addressing the user, except when it is not known. """ }; private static DeclarativeAgentDefinition DefineLocationCaptureAgent(IConfiguration configuration) => new(configuration.GetValue(Application.Settings.FoundryModel)) { Instructions = """ Request a location from the user. This location could be their own location or perhaps a location they are interested in. City level precision is sufficient. If extrapolating region and country, confirm you have it right. """, TextOptions = new ResponseTextOptions { TextFormat = ResponseTextFormat.CreateJsonSchemaFormat( "TaskEvaluation", BinaryData.FromString( """ { "type": "object", "properties": { "place": { "type": "string", "description": "Captures only your understanding of the location specified by the user without explanation, or 'unknown' if not yet defined." }, "action": { "type": "string", "description": "The instruction for the next action to take regarding the need for additional detail or confirmation." }, "is_location_defined": { "type": "boolean", "description": "True if the user location is understood." }, "is_location_confirmed": { "type": "boolean", "description": "True if the user location is confirmed. An unambiguous location may be implicitly confirmed without explicit user confirmation." } }, "required": ["place", "action", "is_location_defined", "is_location_confirmed"], "additionalProperties": false } """), jsonSchemaFormatDescription: null, jsonSchemaIsStrict: true), } }; private static DeclarativeAgentDefinition DefineLocationAwareAgent(IConfiguration configuration) => new(configuration.GetValue(Application.Settings.FoundryModel)) { // Parameterized instructions reference the "location" input argument. Instructions = """ Talk to the user about their request. Their request is related to a specific location: {{location}}. """, StructuredInputs = { ["location"] = new StructuredInputDefinition { IsRequired = false, DefaultValue = BinaryData.FromString(@"""unknown"""), Description = "The user's location", } } }; }