### xUnit Test Example for Workflow Core Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/test-helpers.md Inherit from WorkflowTest and call Setup() in the constructor. Use helper methods like StartWorkflow, WaitForWorkflowToComplete, GetStatus, and GetData to test workflow logic. ```csharp public class xUnitTest : WorkflowTest { public xUnitTest() { Setup(); } [Fact] public void MyWorkflow() { var workflowId = StartWorkflow(new MyDataClass() { Value1 = 2, Value2 = 3 }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); UnhandledStepErrors.Count.Should().Be(0); GetData(workflowId).Value3.Should().Be(5); } } ``` -------------------------------- ### Use System Prompts Effectively Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/azure-ai-foundry.md Guides agent behavior with clear instructions in the system prompt. This example defines a customer support agent with specific guidelines. ```csharp .AgentLoop(cfg => cfg .SystemPrompt(@"You are a customer support agent. Guidelines: 1. Always be polite and professional 2. Search the knowledge base before answering 3. If you can't help, create a support ticket 4. Never share sensitive customer data") ...); ``` -------------------------------- ### Install WorkflowCore.Testing NuGet Package Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/test-helpers.md Use the Package Manager Console to install the testing utilities. ```powershell PM> Install-Package WorkflowCore.Testing ``` -------------------------------- ### NUnit Test Example for Workflow Core Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/test-helpers.md Inherit from WorkflowTest and override the Setup method. Use NUnit attributes like [TestFixture] and [SetUp]. Test workflow execution using helper methods. ```csharp [TestFixture] public class NUnitTest : WorkflowTest { [SetUp] protected override void Setup() { base.Setup(); } [Test] public void NUnit_workflow_test_sample() { var workflowId = StartWorkflow(new MyDataClass() { Value1 = 2, Value2 = 3 }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); UnhandledStepErrors.Count.Should().Be(0); GetData(workflowId).Value3.Should().Be(5); } } ``` -------------------------------- ### Install WorkflowCore.Users NuGet Package Source: https://github.com/danielgerlag/workflow-core/blob/master/src/extensions/WorkflowCore.Users/readme.md Use the Package Manager Console to install the WorkflowCore.Users NuGet package. ```powershell PM> Install-Package WorkflowCore.Users ``` -------------------------------- ### Configure Workflow Core in ASP.NET Core Startup Source: https://github.com/danielgerlag/workflow-core/wiki/97.-Using-with-ASP.NET-Core Configure Workflow Core services by calling `AddWorkflow` in `ConfigureServices`. This example shows configuration with MongoDB and Elasticsearch persistence. The workflow host is started in `Configure` after registering workflows. ```csharp public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddWorkflow(cfg => { cfg.UseMongoDB(@"mongodb://mongo:27017", "workflow"); cfg.UseElasticsearch(new ConnectionSettings(new Uri("http://elastic:9200")), "workflows"); }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvc(); var host = app.ApplicationServices.GetService(); host.RegisterWorkflow(); host.Start(); } } ``` -------------------------------- ### Install RabbitMQ Provider NuGet Package Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.QueueProviders.RabbitMQ/README.md Install the WorkflowCore.QueueProviders.RabbitMQ NuGet package using the Package Manager Console. ```powershell PM> Install-Package WorkflowCore.QueueProviders.RabbitMQ -Pre ``` -------------------------------- ### Install WorkflowCore.Providers.Azure using Nuget Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Providers.Azure/README.md Use the Nuget package console to install the Azure providers for Workflow Core. ```powershell PM> Install-Package WorkflowCore.Providers.Azure ``` -------------------------------- ### Initialize and Start Workflow Host Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/getting-started.md Retrieve the `IWorkflowHost` from `IServiceProvider`, register workflows, start the host, and initiate a workflow instance. Ensure to stop the host when done. ```csharp var host = serviceProvider.GetService(); host.RegisterWorkflow(); host.Start(); host.StartWorkflow("HelloWorld", 1, null); Console.ReadLine(); host.Stop(); ``` -------------------------------- ### Install WorkflowCore.Providers.Azure using .NET CLI Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Providers.Azure/README.md Use the .NET CLI to add the Azure providers package to your project. ```bash dotnet add package WorkflowCore.Providers.Azure ``` -------------------------------- ### Install Sqlite Persistence Package Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Persistence.Sqlite/README.md Install the 'WorkflowCore.Persistence.Sqlite' NuGet package using the Package Manager Console. ```powershell PM> Install-Package WorkflowCore.Persistence.Sqlite -Pre ``` -------------------------------- ### Install MySQL Persistence Package Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Persistence.MySQL/README.md Use this NuGet command to install the MySQL persistence provider for Workflow Core. ```powershell PM> Install-Package WorkflowCore.Persistence.MySQL -Pre ``` -------------------------------- ### Install MongoDB Persistence Package Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Persistence.MongoDB/README.md Install the MongoDB persistence provider using the NuGet package manager. ```powershell PM> Install-Package WorkflowCore.Persistence.MongoDB ``` -------------------------------- ### Install WorkflowCore NuGet Package Source: https://github.com/danielgerlag/workflow-core/wiki/Home Use the Package Manager Console to install the WorkflowCore NuGet package. ```powershell PM> Install-Package WorkflowCore ``` -------------------------------- ### Initialize and Run Workflow Host Source: https://github.com/danielgerlag/workflow-core/wiki/01.-Getting-started Obtain the workflow host from the service provider, register your workflows, start the host's thread pool, and initiate a workflow instance. Ensure to stop the host when done. ```C# var host = serviceProvider.GetService(); host.RegisterWorkflow(); host.Start(); host.StartWorkflow("HelloWorld", 1, null); Console.ReadLine(); host.Stop(); ``` -------------------------------- ### Install PostgreSQL Persistence Provider Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Persistence.PostgreSQL/README.md Use this NuGet command to install the PostgreSQL persistence provider for Workflow Core. ```powershell PM> Install-Package WorkflowCore.Persistence.PostgreSQL -Pre ``` -------------------------------- ### Install Elasticsearch Plugin using .NET CLI Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/elastic-search.md Use this command in the .NET CLI to add the Elasticsearch provider package to your project. ```bash dotnet add package WorkflowCore.Providers.Elasticsearch ``` -------------------------------- ### Install SQL Server Queue Provider NuGet Package Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.QueueProviders.SqlServer/README.md Use this Package Manager Console command to install the necessary NuGet package for the SQL Server Service Broker queue provider. ```powershell PM> Install-Package WorkflowCore.QueueProviders.SqlServer -Pre ``` -------------------------------- ### Define a Basic Workflow Structure Source: https://github.com/danielgerlag/workflow-core/blob/master/src/samples/WorkflowCore.Sample01/README.md Use the fluent API to define the sequence of steps in a workflow. This example shows starting with one step and then proceeding to another. ```C# public class HelloWorldWorkflow : IWorkflow { public void Build(IWorkflowBuilder builder) { builder .StartWith() .Then(); } ... ``` -------------------------------- ### Install Oracle Persistence Provider Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Persistence.Oracle/README.md Install the Oracle Persistence provider NuGet package using the Package Manager Console. ```powershell PM> Install-Package WorkflowCore.Persistence.Oracle -Pre ``` -------------------------------- ### Install Workflow Core using .NET CLI Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/index.md Use this command in your terminal to add the WorkflowCore NuGet package to your project. ```bash dotnet add package WorkflowCore ``` -------------------------------- ### Workflow with User Input and Outputs Source: https://github.com/danielgerlag/workflow-core/blob/master/README.md Example of a workflow that takes user input, processes it, and outputs data. Use Input() to map data to step parameters and Output() to map step results back to workflow data. ```csharp public class MyData { public string Email { get; set; } public string Password { get; set; } public string UserId { get; set; } } public class MyWorkflow : IWorkflow { public void Build(IWorkflowBuilder builder) { builder .StartWith() .Input(step => step.Email, data => data.Email) .Input(step => step.Password, data => data.Password) .Output(data => data.UserId, step => step.UserId) .Then() .WaitFor("confirmation", data => data.UserId) .Then() .Input(step => step.UserId, data => data.UserId); } } ``` -------------------------------- ### Install RavenDB Persistence Provider Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Persistence.RavenDB/README.md Install the RavenDB Persistence provider NuGet package using the Package Manager Console. ```powershell PM> Install-Package WorkflowCore.Persistence.RavenDB ``` -------------------------------- ### JSON Input with Object Graph Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/json-yaml.md Example of passing an object graph as input to a step in JSON format. ```json "inputs": { "Body": { "Value1": 1, "Value2": 2 }, "Headers": { "Content-Type": "application/json" } }, ``` -------------------------------- ### Install AWS Providers NuGet Package Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Providers.AWS/README.md Use the Package Manager Console to install the necessary NuGet package for AWS providers. ```powershell PM> Install-Package WorkflowCore.Providers.AWS ``` -------------------------------- ### Create a Custom Tool Source: https://github.com/danielgerlag/workflow-core/blob/master/src/samples/WorkflowCore.Sample.AzureFoundry/README.md Implement the IAgentTool interface to create custom tools for agents. This example shows a StockPriceTool that retrieves stock prices. ```csharp public class StockPriceTool : IAgentTool { public string Name => "stock_price"; public string Description => "Get the current stock price for a ticker symbol"; public string ParametersSchema => @"{ ""type"": ""object"", ""properties"": { ""ticker"": { ""type"": ""string"", ""description"": ""Stock ticker symbol (e.g., MSFT, AAPL) "" } }, ""required"": ["ticker"] }"; private readonly IStockService _stockService; public StockPriceTool(IStockService stockService) { _stockService = stockService; } public async Task ExecuteAsync( string toolCallId, string arguments, CancellationToken ct) { var args = JsonSerializer.Deserialize(arguments); var price = await _stockService.GetPriceAsync(args.Ticker, ct); return ToolResult.Succeeded(toolCallId, Name, JsonSerializer.Serialize(new { ticker = args.Ticker, price = price })); } } ``` -------------------------------- ### Install SQL Server Persistence NuGet Package Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Persistence.SqlServer/README.md Install the necessary NuGet package to enable SQL Server persistence for Workflow Core. ```powershell PM> Install-Package WorkflowCore.Persistence.SqlServer ``` -------------------------------- ### Install Elasticsearch Plugin using NuGet Package Console Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/elastic-search.md Use this command in the Package Manager Console to install the Elasticsearch provider for Workflow Core. ```powershell PM> Install-Package WorkflowCore.Providers.Elasticsearch ``` -------------------------------- ### Write Clear Tool Descriptions Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/azure-ai-foundry.md Provides examples of good and bad tool descriptions. A good description clearly explains what the tool does and what it returns, aiding the LLM in deciding when to use it. ```csharp // ❌ Bad public string Description => "Gets weather"; // ✅ Good public string Description => "Get the current weather conditions for a specific city. " + "Returns temperature, humidity, and conditions."; ``` -------------------------------- ### YAML Workflow with Inputs and Outputs Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/json-yaml.md A YAML workflow definition demonstrating input and output binding, similar to the JSON example. ```yaml Id: AddWorkflow Version: 1 DataType: MyApp.MyDataClass, MyApp Steps: - Id: Hello StepType: MyApp.HelloWorld, MyApp NextStepId: Add - Id: Add StepType: MyApp.AddNumbers, MyApp NextStepId: Bye Inputs: Value1: data.Value1 Value2: data.Value2 Outputs: Answer: step.Result - Id: Bye StepType: MyApp.GoodbyeWorld, MyApp ``` -------------------------------- ### Register Custom Tools with the Tool Registry Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/azure-ai-foundry.md Register instances of your custom tools with the IToolRegistry in your Dependency Injection setup. ```csharp // In your DI setup services.AddSingleton(); services.AddSingleton(); // After building service provider var toolRegistry = serviceProvider.GetRequiredService(); toolRegistry.Register(serviceProvider.GetRequiredService()); toolRegistry.Register(serviceProvider.GetRequiredService()); ``` -------------------------------- ### Registering a Custom Persistence Provider Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/persistence.md Example of how to register a custom persistence provider within the Workflow Core service configuration. ```csharp services.AddWorkflow(options => { options.UsePersistence(sp => new MyCustomPersistenceProvider()); }); ``` -------------------------------- ### Start Workflow and Complete Review Using Workflow ID Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/azure-ai-foundry.md Initiate a workflow and later complete a human review step using the workflow's ID as the event key. ```csharp // Start workflow var workflowId = await host.StartWorkflow("ContentReview", data); // Later, complete the review using workflowId as the event key await host.PublishEvent("HumanReview", workflowId, reviewAction); ``` -------------------------------- ### Add Azure AI Foundry Package Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/azure-ai-foundry.md Install the Azure AI Foundry package for WorkflowCore using the .NET CLI. ```bash dotnet add package WorkflowCore.AI.AzureFoundry ``` -------------------------------- ### Install SQL Server Lock Provider NuGet Package Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.LockProviders.SqlServer/README.md Install the necessary NuGet package to enable SQL Server locking functionality for Workflow Core. ```powershell PM> Install-Package WorkflowCore.LockProviders.SqlServer ``` -------------------------------- ### Define Workflow with YAML Source: https://github.com/danielgerlag/workflow-core/blob/master/README.md Define workflows using YAML for external configuration. Ensure the WorkFlowCore.DSL package is installed. ```yaml Id: HelloWorld Version: 1 Steps: - Id: Hello StepType: MyApp.HelloWorld, MyApp NextStepId: Bye - Id: Bye StepType: MyApp.GoodbyeWorld, MyApp ``` -------------------------------- ### Execute Workflow Metrics Middleware in C# Source: https://github.com/danielgerlag/workflow-core/blob/master/ReleaseNotes/3.4.0.md Implement `IWorkflowMiddleware` to run after each workflow execution. Use `WorkflowMiddlewarePhase.ExecuteWorkflow` to specify the phase. Ensure `next()` is called to continue the middleware chain. This example collects metrics for completed and suspended workflows. ```csharp public class MetricsMiddleware : IWorkflowMiddleware { private readonly ConcurrentHashSet() _suspendedWorkflows = new ConcurrentHashSet(); private readonly Counter _completed; private readonly Counter _suspended; public MetricsMiddleware() { _completed = Prometheus.Metrics.CreateCounter( "workflow_completed", "Workflow completed"); _suspended = Prometheus.Metrics.CreateCounter( "workflow_suspended", "Workflow suspended"); } public WorkflowMiddlewarePhase Phase => WorkflowMiddlewarePhase.ExecuteWorkflow; public Task HandleAsync( WorkflowInstance workflow, WorkflowDelegate next) { switch (workflow.Status) { case WorkflowStatus.Complete: TryDecrementSuspended(workflow); _completed.Inc(); break; case WorkflowStatus.Suspended: _suspendedWorkflows.Add(workflow.Id); _suspended.Inc(); break; default: TryDecrementSuspended(workflow); break; } return next(); } private void TryDecrementSuspended(WorkflowInstance workflow) { if (_suspendedWorkflows.TryRemove(workflow.Id)) { _suspended.Dec(); } } } ``` -------------------------------- ### Run Azure Foundry Sample Project Source: https://github.com/danielgerlag/workflow-core/blob/master/src/extensions/WorkflowCore.AI.AzureFoundry/readme.md Instructions to run the sample project for the Azure Foundry extension. This involves navigating to the sample directory, copying the environment file, updating credentials, and running the application. ```bash cd src/samples/WorkflowCore.Sample.AzureFoundry cp .env.example .env # Edit .env with your Azure AI credentials dotnet run ``` -------------------------------- ### Implement Pre-Workflow Middleware to Set Description Source: https://github.com/danielgerlag/workflow-core/blob/master/ReleaseNotes/3.3.0.md Implement a pre-workflow middleware to dynamically set the workflow description based on input parameters. Ensure `next` is called to continue the middleware chain. ```cs public class AddDescriptionWorkflowMiddleware : IWorkflowMiddleware { public WorkflowMiddlewarePhase Phase => WorkflowMiddlewarePhase.PreWorkflow; public Task HandleAsync( WorkflowInstance workflow, WorkflowDelegate next ) { if (workflow.Data is IDescriptiveWorkflowParams descriptiveParams) { workflow.Description = descriptiveParams.Description; } return next(); } } ``` ```cs public interface IDescriptiveWorkflowParams { string Description { get; } } ``` ```cs public MyWorkflowParams : IDescriptiveWorkflowParams { public string Description => $"Run task '{TaskName}'"; public string TaskName { get; set; } } ``` -------------------------------- ### Create a Step with Inputs and Outputs Source: https://github.com/danielgerlag/workflow-core/blob/master/src/samples/WorkflowCore.Sample03/README.md Create a step that exposes public properties for inputs and outputs. These properties will be used to bind data from the workflow's data class. ```C# public class AddNumbers : StepBody { public int Input1 { get; set; } public int Input2 { get; set; } public int Output { get; set; } public override ExecutionResult Run(IStepExecutionContext context) { Output = (Input1 + Input2); return ExecutionResult.Next(); } } ``` -------------------------------- ### Basic AzureFoundry Configuration Options Source: https://github.com/danielgerlag/workflow-core/blob/master/src/extensions/WorkflowCore.AI.AzureFoundry/readme.md Configure Azure AI Foundry services, including endpoint, authentication, and default model settings. Optional settings for Azure AI Search are also available. ```csharp services.AddAzureFoundry(options => { // Required: Azure AI Foundry endpoint options.Endpoint = "https://myresource.services.ai.azure.com"; // Authentication (choose one) options.ApiKey = "your-api-key"; // API key authentication // OR options.Credential = new DefaultAzureCredential(); // Azure AD authentication // Model configuration options.DefaultModel = "gpt-4o"; options.DefaultEmbeddingModel = "text-embedding-3-small"; options.DefaultTemperature = 0.7f; options.DefaultMaxTokens = 4096; // Azure AI Search (optional, for RAG) options.SearchEndpoint = "https://mysearch.search.windows.net"; options.SearchApiKey = "your-search-api-key"; }); ``` -------------------------------- ### Agent with Tools Workflow Source: https://github.com/danielgerlag/workflow-core/blob/master/src/samples/WorkflowCore.Sample.AzureFoundry/README.md Sets up an autonomous agent that can utilize tools like 'weather' and 'calculator' to fulfill user requests. The agent decides which tools to use and executes them automatically. ```csharp builder .StartWith(context => ExecutionResult.Next()) .AgentLoop(cfg => cfg .SystemPrompt(@"You are a helpful assistant with access to tools. Use the weather tool to get weather information. Use the calculator tool for math operations. Always explain what you're doing.") .Message(data => data.UserRequest) .WithTool("weather") .WithTool("calculator") .MaxIterations(5) .AutoExecuteTools(true) .OutputTo(data => data.AgentResponse)); ``` -------------------------------- ### Define Workflow with JSON Source: https://github.com/danielgerlag/workflow-core/blob/master/README.md Define workflows using JSON for external configuration. Ensure the WorkFlowCore.DSL package is installed. ```json { "Id": "HelloWorld", "Version": 1, "Steps": [ { "Id": "Hello", "StepType": "MyApp.HelloWorld, MyApp", "NextStepId": "Bye" }, { "Id": "Bye", "StepType": "MyApp.GoodbyeWorld, MyApp" } ] } ``` -------------------------------- ### Build Workflow with Data Passing Source: https://github.com/danielgerlag/workflow-core/blob/master/src/samples/WorkflowCore.Sample03/README.md Construct the workflow by defining steps and mapping data between the workflow's data class and step properties. Use .Input() to pass data into steps and .Output() to capture data from steps. ```C# public class PassingDataWorkflow : IWorkflow { public void Build(IWorkflowBuilder builder) { builder .StartWith(context => { Console.WriteLine("Starting workflow..."); return ExecutionResult.Next(); }) .Then() .Input(step => step.Input1, data => data.Value1) .Input(step => step.Input2, data => data.Value2) .Output(data => data.Value3, step => step.Output) .Then() .Name("Print custom message") .Input(step => step.Message, data => "The answer is " + data.Value3.ToString()) .Then(context => { Console.WriteLine("Workflow complete"); return ExecutionResult.Next(); }); } ... ``` -------------------------------- ### Implement Post-Workflow Middleware for Summary Logging Source: https://github.com/danielgerlag/workflow-core/blob/master/ReleaseNotes/3.3.0.md Implement a post-workflow middleware to log a summary of the workflow execution, including total duration and step durations. Ensure `next` is called to continue the middleware chain. ```cs public class PrintWorkflowSummaryMiddleware : IWorkflowMiddleware { private readonly ILogger _log; public PrintWorkflowSummaryMiddleware( ILogger log ) { _log = log; } public WorkflowMiddlewarePhase Phase => WorkflowMiddlewarePhase.PostWorkflow; public Task HandleAsync( WorkflowInstance workflow, WorkflowDelegate next ) { if (!workflow.CompleteTime.HasValue) { return next(); } var duration = workflow.CompleteTime.Value - workflow.CreateTime; _log.LogInformation($"Workflow {workflow.Description} completed in {duration:g}"); foreach (var step in workflow.ExecutionPointers) { var stepName = step.StepName; var stepDuration = (step.EndTime - step.StartTime) ?? TimeSpan.Zero; _log.LogInformation($" - Step {stepName} completed in {stepDuration:g}"); } return next(); } } ``` -------------------------------- ### Configure RavenDB Store Options Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Persistence.RavenDB/README.md Compose RavenStoreOptions using the model provided by the library. Ensure to set the server URL, database name, and certificate details if required. ```csharp var options = new RavenStoreOptions { ServerUrl = "https://ravendbserver.domain.com:8080", DatabaseName = "TestDatabase", CertificatePath = System.IO.Path.Combine(AppContext.BaseDirectory, "Resources/servercert.pfx"), CertificatePassword = "CertificatePassword" } ``` -------------------------------- ### Decision Branching JSON Representation Source: https://github.com/danielgerlag/workflow-core/blob/master/ReleaseNotes/3.1.0.md Example JSON structure representing a workflow with decision branching, showing how steps and their conditions are defined. ```json { "Id": "DecisionWorkflow", "Version": 1, "DataType": "MyApp.MyData, MyApp", "Steps": [ { "Id": "decide", "StepType": "...", "SelectNextStep": { "Print1": "data.Value1 == \"one\"", "Print2": "data.Value1 == \"two\"" } }, { "Id": "Print1", "StepType": "MyApp.PrintMessage, MyApp", "Inputs": { "Message": "\"Hello from 1\"" } }, { "Id": "Print2", "StepType": "MyApp.PrintMessage, MyApp", "Inputs": { "Message": "\"Hello from 2\"" } } ] } ``` -------------------------------- ### Configure SQL Server Persistence in Service Provider Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Persistence.SqlServer/README.md Configure the service provider to use SQL Server for persistence by calling the UseSqlServer extension method. Provide the connection string and optional flags for creating the database and tables if they don't exist. ```csharp services.AddWorkflow(x => x.UseSqlServer(@"Server=.;Database=WorkflowCore;Trusted_Connection=True;", true, true)); ``` -------------------------------- ### Get Open User Actions Source: https://github.com/danielgerlag/workflow-core/blob/master/src/extensions/WorkflowCore.Users/readme.md Retrieve a list of pending user actions for a specific workflow instance using the WorkflowHost's GetOpenUserActions method. ```csharp var openItems = host.GetOpenUserActions(workflowId); ``` -------------------------------- ### Implement Step with Sleep and Persistence Source: https://github.com/danielgerlag/workflow-core/wiki/01.-Getting-started Use `ExecutionResult.Sleep` to defer workflow execution and `context.PersistenceData` to store and retrieve state between runs. This example sleeps for 12 hours. ```csharp public class SleepStep : StepBody { public override ExecutionResult Run(IStepExecutionContext context) { if (context.PersistenceData == null) return ExecutionResult.Sleep(Timespan.FromHours(12), new Object()); else return ExecutionResult.Next(); } } ``` -------------------------------- ### Workflow Definition with Deferred Execution Source: https://github.com/danielgerlag/workflow-core/blob/master/src/samples/WorkflowCore.Sample05/README.md Define a workflow that includes a step designed for deferred execution. This example shows how to configure the sleep period for the SleepStep and chain it with other steps. ```C# public class DeferSampleWorkflow : IWorkflow { public void Build(IWorkflowBuilder builder) { builder .StartWith(context => { Console.WriteLine("Workflow started"); return ExecutionResult.Next(); }) .Then() .Input(step => step.Period, data => TimeSpan.FromSeconds(20)) .Then(context => { Console.WriteLine("workflow complete"); return ExecutionResult.Next(); }); } ... ``` -------------------------------- ### Filter Custom Data by Numeric Range Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/elastic-search.md Apply a numeric range filter to your custom data objects. This example filters for workflows where the `Value2` property is less than 5. ```csharp searchIndex.Search("", 0, 10, NumericRangeFilter.LessThan(x => x.Value2, 5)) ``` -------------------------------- ### Define Workflow with Fluent API Source: https://github.com/danielgerlag/workflow-core/wiki/Home Define a workflow's steps using the fluent API provided by Workflow Core. This example shows a simple sequence of tasks. ```csharp public class MyWorkflow : IWorkflow { public void Build(IWorkflowBuilder builder) { builder .StartWith() .Then() .Then; } } ``` -------------------------------- ### Configure Oracle Persistence with Default Options Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Persistence.Oracle/README.md Configure the service provider to use Oracle persistence with default options. Ensure your connection string is correctly formatted. ```csharp services.AddWorkflow(x => x.UseOracle(@"Server=127.0.0.1;Database=workflow;User=root;Password=password;", true, true)); ``` -------------------------------- ### Configure Sqlite Persistence Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Persistence.Sqlite/README.md Configure the service provider to use Sqlite for persistence by calling the '.UseSqlite' extension method. Provide the connection string and a boolean indicating whether to create the database if it doesn't exist. ```csharp services.AddWorkflow(x => x.UseSqlite(@"Data Source=database.db;", true)); ``` -------------------------------- ### Set Agent Loop Iteration Limit Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/azure-ai-foundry.md Sets the maximum number of iterations for an agent loop to prevent excessive costs. This example limits the loop to 10 LLM calls. ```csharp .AgentLoop(cfg => cfg .MaxIterations(10) // Stop after 10 LLM calls ...); ``` -------------------------------- ### Configure AzureFoundry Services and Define Workflow Source: https://github.com/danielgerlag/workflow-core/blob/master/src/extensions/WorkflowCore.AI.AzureFoundry/readme.md Configure the necessary services for AzureFoundry integration and define a workflow that utilizes AI steps like AgentLoop. Ensure to provide your Azure AI endpoint and API key. ```csharp // 1. Configure services services.AddWorkflow(); services.AddAzureFoundry(options => { options.Endpoint = "https://myresource.services.ai.azure.com"; options.ApiKey = Environment.GetEnvironmentVariable("AZURE_AI_API_KEY"); options.DefaultModel = "gpt-4o"; }); // 2. Define a workflow with AI steps public class CustomerSupportWorkflow : IWorkflow { public string Id => "CustomerSupport"; public int Version => 1; public void Build(IWorkflowBuilder builder) { builder .StartWith(context => ExecutionResult.Next()) .AgentLoop(cfg => cfg .SystemPrompt("You are a helpful customer support agent.") .Message(data => data.CustomerQuery) .WithTool() .WithTool() .MaxIterations(5) .OutputTo(data => data.Response)); } } // 3. Run the workflow var workflowId = await host.StartWorkflow("CustomerSupport", new SupportData { CustomerQuery = "How do I reset my password?" }); ``` -------------------------------- ### Saga Transaction Expressed in YAML Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/sagas.md Defines a saga transaction using YAML format. Similar to the JSON example, it utilizes `WorkflowCore.Primitives.Sequence` with `Saga: true` and specifies compensation steps. ```yaml Id: Saga-Sample Version: 1 DataType: MyApp.MyDataClass, MyApp Steps: - Id: Hello StepType: MyApp.HelloWorld, MyApp NextStepId: MySaga - Id: MySaga StepType: WorkflowCore.Primitives.Sequence, WorkflowCore NextStepId: Bye Saga: true Do: - - Id: do1 StepType: MyApp.Task1, MyApp NextStepId: do2 CompensateWith: - Id: undo1 StepType: MyApp.UndoTask1, MyApp - Id: do2 StepType: MyApp.Task2, MyApp CompensateWith: - Id: undo2-1 NextStepId: undo2-2 StepType: MyApp.UndoTask2, MyApp - Id: undo2-2 StepType: MyApp.DoSomethingElse, MyApp - Id: Bye StepType: MyApp.GoodbyeWorld, MyApp ``` -------------------------------- ### Activity Step YAML Configuration Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/activities.md Configures an activity step using YAML, specifying the activity name, event key, and parameters. Supports optional fields like 'CancelCondition'. ```yaml Id: MyActivityStep StepType: WorkflowCore.Primitives.Activity, WorkflowCore NextStepId: "..." CancelCondition: "..." Inputs: ActivityName: '"my-activity"' EventKey: '"Key1"' Parameters: data.SomeValue ``` -------------------------------- ### Define Workflow Step with Inputs and Outputs Source: https://github.com/danielgerlag/workflow-core/wiki/02.-Data Define a workflow step that accepts inputs and produces an output. Ensure the output property is set within the Run method. ```C# public class AddNumbers : StepBody { public int Input1 { get; set; } public int Input2 { get; set; } public int Output { get; set; } public override ExecutionResult Run(IStepExecutionContext context) { Output = (Input1 + Input2); return ExecutionResult.Next(); } } ``` -------------------------------- ### Configure API Key Authentication for Azure Foundry Source: https://github.com/danielgerlag/workflow-core/blob/master/src/extensions/WorkflowCore.AI.AzureFoundry/readme.md Configure the Azure Foundry extension using an API key for authentication. Ensure the API key is securely stored and accessed, for example, via environment variables. ```csharp services.AddAzureFoundry(options => { options.Endpoint = "https://myresource.services.ai.azure.com"; options.ApiKey = Environment.GetEnvironmentVariable("AZURE_AI_API_KEY"); }); ``` -------------------------------- ### Implement Custom Agent Tool Source: https://github.com/danielgerlag/workflow-core/blob/master/src/extensions/WorkflowCore.AI.AzureFoundry/readme.md Create custom tools for AI agents by implementing the IAgentTool interface. Define the tool's name, description, parameter schema, and execution logic. ```csharp public class WeatherTool : IAgentTool { public string Name => "weather"; public string Description => "Get current weather for a city"; public string ParametersSchema => @"{ ""type"": ""object"", ""properties"": { ""city"": { ""type"": ""string"", ""description"": ""City name"" } }, ""required"": [""city""] }"; private readonly IWeatherService _weatherService; public WeatherTool(IWeatherService weatherService) { _weatherService = weatherService; } public async Task ExecuteAsync( string toolCallId, string arguments, CancellationToken cancellationToken) { try { var args = JsonSerializer.Deserialize(arguments); var weather = await _weatherService.GetWeatherAsync(args.City, cancellationToken); return ToolResult.Succeeded(toolCallId, Name, JsonSerializer.Serialize(weather)); } catch (Exception ex) { return ToolResult.Failed(toolCallId, Name, ex.Message); } } } ``` -------------------------------- ### Configure Azure AD Authentication for Azure Foundry Source: https://github.com/danielgerlag/workflow-core/blob/master/src/extensions/WorkflowCore.AI.AzureFoundry/readme.md Configure the Azure Foundry extension using Azure Active Directory (Azure AD) for authentication. This example uses DefaultAzureCredential, but specific credential types like ManagedIdentityCredential or ClientSecretCredential can also be used. ```csharp services.AddAzureFoundry(options => { options.Endpoint = "https://myresource.services.ai.azure.com"; options.Credential = new DefaultAzureCredential(); // Or specific credential types: // options.Credential = new ManagedIdentityCredential(); // options.Credential = new ClientSecretCredential(tenantId, clientId, secret); }); ``` -------------------------------- ### Configure MySQL Persistence in Service Provider Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Persistence.MySQL/README.md Add the MySQL persistence provider to your service collection using the UseMySQL extension method. Provide your MySQL connection string and specify whether to create the database and tables if they don't exist. ```csharp services.AddWorkflow(x => x.UseMySQL(@"Server=127.0.0.1;Database=workflow;User=root;Password=password;", true, true)); ``` -------------------------------- ### C# Workflow with Multiple Outcomes Source: https://github.com/danielgerlag/workflow-core/wiki/03.-Multiple-outcomes Define a workflow that forks based on the outcome of a preceding step. Use '.When()' to specify conditions and '.Do()' to define the subsequent steps for each outcome. This example forks to different task pairs based on a random 0 or 1 outcome. ```C# public class MultipleOutcomeWorkflow : IWorkflow { public void Build(IWorkflowBuilder builder) { builder .StartWith(x => x.Name("Random Step")) .When(data => 0).Do(then => then .StartWith() .Then()) .When(data => 1).Do(then => then .StartWith() .Then()) .Then(); } } ``` -------------------------------- ### Define a Custom Tool for Knowledge Base Search Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/azure-ai-foundry.md Implement the IAgentTool interface to create a tool that searches a knowledge base. Define parameters and execution logic. ```csharp public class SearchKnowledgeBase : IAgentTool { private readonly IKnowledgeBaseService _kb; public SearchKnowledgeBase(IKnowledgeBaseService kb) { _kb = kb; } public string Name => "search_knowledge_base"; public string Description => "Search the knowledge base for articles matching the query"; public string ParametersSchema => @"{ ""type"": ""object"", ""properties"": { ""query"": { ""type"": ""string"", ""description"": ""Search query"" }, ""category"": { ""type"": ""string"", ""description"": ""Optional category filter"" } }, ""required"": [""query""] }"; public async Task ExecuteAsync( string toolCallId, string arguments, CancellationToken ct) { var args = JsonSerializer.Deserialize(arguments); var results = await _kb.SearchAsync(args.Query, args.Category, ct); if (results.Any()) { return ToolResult.Succeeded( toolCallId, Name, JsonSerializer.Serialize(results)); } return ToolResult.Succeeded( toolCallId, Name, "No articles found matching the query."); } } ``` -------------------------------- ### Publishing an External Event Source: https://github.com/danielgerlag/workflow-core/wiki/04.-Responding-to-external-events Demonstrates how to publish an external event from the host. This will trigger any workflows that are waiting for 'MyEvent' with the key '0'. ```C# //External events are published via the host //All workflows that have subscribed to MyEvent 0, will be passed "hello" host.PublishEvent("MyEvent", "0", "hello"); ``` -------------------------------- ### Simple Chat Completion Workflow Source: https://github.com/danielgerlag/workflow-core/blob/master/src/samples/WorkflowCore.Sample.AzureFoundry/README.md Implements a basic conversational chat loop with a language model. Use this for multi-turn conversations where persistent context is needed. ```csharp builder .StartWith(context => ExecutionResult.Next()) .ChatCompletion(cfg => cfg .SystemPrompt("You are a helpful assistant") .UserMessage(data => data.UserMessage) .OutputTo(data => data.Response)); ``` -------------------------------- ### Register Services and Workflow Step for Dependency Injection in C# Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/getting-started.md Configures the service collection to include logging, workflow services, the custom service, and the workflow step as transient. Avoid registering steps as singletons. ```csharp IServiceCollection services = new ServiceCollection(); services.AddLogging(); services.AddWorkflow(); services.AddTransient(); services.AddTransient(); ``` -------------------------------- ### Workflow with Error Handling and Retries Source: https://github.com/danielgerlag/workflow-core/blob/master/README.md Demonstrates how to configure error handling for workflow steps, including retry logic with a specified delay. ```csharp public class MyWorkflow : IWorkflow { public void Build(IWorkflowBuilder builder) { builder .StartWith() .Then() .OnError(WorkflowErrorHandling.Retry, TimeSpan.FromMinutes(10)) .Then() .OnError(WorkflowErrorHandling.Retry, TimeSpan.FromMinutes(10)); } } ``` -------------------------------- ### Consume a Service via Dependency Injection in a Workflow Step in C# Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/getting-started.md Demonstrates how a workflow step can consume a service through constructor injection. Ensure the service and step are registered with the IoC container. ```csharp public class DoSomething : StepBody { private IMyService _myService; public DoSomething(IMyService myService) { _myService = myService; } public override ExecutionResult Run(IStepExecutionContext context) { _myService.DoTheThings(); return ExecutionResult.Next(); } } ``` -------------------------------- ### Configure AgentLoop Step Source: https://github.com/danielgerlag/workflow-core/blob/master/src/extensions/WorkflowCore.AI.AzureFoundry/readme.md Set up an agent loop for complex workflows where the LLM decides tool execution. This includes defining the system prompt, user message, available tools, and loop constraints. Automatic tool execution is enabled by default. ```csharp builder .AgentLoop(cfg => cfg .SystemPrompt("You are an agent with access to tools") .Message(data => data.UserRequest) .WithTool() // Register available tools .WithTool() .MaxIterations(10) // Prevent infinite loops .AutoExecuteTools() // Automatically execute tool calls .OutputTo(data => data.AgentResponse) .OutputIterationsTo(data => data.IterationsUsed) .OutputToolResultsTo(data => data.ToolResults)); ``` -------------------------------- ### JSON Workflow Definition with Inputs and Outputs Source: https://github.com/danielgerlag/workflow-core/wiki/10.-Loading-workflow-definitions-from-JSON Illustrates a workflow that takes inputs for an 'Add' step and outputs the result. 'Inputs' map JSON keys to step properties using expressions referencing 'data'. 'Outputs' map step properties to data properties using expressions referencing 'step'. ```json { "Id": "AddWorkflow", "Version": 1, "DataType": "MyApp.MyDataClass, MyApp", "Steps": [ { "Id": "Hello", "StepType": "MyApp.HelloWorld, MyApp", "NextStepId": "Add" }, { "Id": "Add", "StepType": "MyApp.AddNumbers, MyApp", "NextStepId": "Bye", "Inputs": { "Value1": "data.Value1", "Value2": "data.Value2" }, "Outputs": { "Answer": "step.Result" } }, { "Id": "Bye", "StepType": "MyApp.GoodbyeWorld, MyApp" } ] } ``` -------------------------------- ### Simple Chat Completion Workflow Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/azure-ai-foundry.md Implement a basic workflow step to invoke an LLM for chat completion using a system prompt and user message. ```csharp public class SimpleChatWorkflow : IWorkflow { public void Build(IWorkflowBuilder builder) { builder .StartWith(context => ExecutionResult.Next()) .ChatCompletion(cfg => cfg .SystemPrompt("You are a helpful assistant") .UserMessage(data => data.Question) .OutputTo(data => data.Answer)); } } ``` -------------------------------- ### Activity Step JSON Configuration with Optional Fields Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/activities.md Configures an activity step using JSON, including optional fields like 'CancelCondition' and 'EffectiveDate'. 'ActivityName' and 'Parameters' are required inputs. ```json { "Id": "MyActivityStep", "StepType": "WorkflowCore.Primitives.Activity, WorkflowCore", "NextStepId": "...", "CancelCondition": "...", "Inputs": { "ActivityName": "\"my-activity\"", "Parameters": "data.SomeValue" } } ``` -------------------------------- ### Load Workflow Definition Source: https://github.com/danielgerlag/workflow-core/blob/master/docs/json-yaml.md Instantiate the IDefinitionLoader and use it to load a workflow definition from a JSON or YAML string. ```csharp using WorkflowCore.Interface; ... var loader = serviceProvider.GetService(); loader.LoadDefinition("<>", Deserializers.Json); ``` -------------------------------- ### Define a Simple Step Body Source: https://github.com/danielgerlag/workflow-core/wiki/01.-Getting-started Implement the `StepBody` abstract class to define a basic workflow step. The `Run` method contains the logic for the step. Dependency injection is supported. ```csharp public class HelloWorld : StepBody { public override ExecutionResult Run(IStepExecutionContext context) { Console.WriteLine("Hello world"); return ExecutionResult.Next(); } } ``` -------------------------------- ### Register a Custom Tool Source: https://github.com/danielgerlag/workflow-core/blob/master/src/samples/WorkflowCore.Sample.AzureFoundry/README.md Register your custom tool with the service provider and tool registry to make it available for agents. ```csharp services.AddSingleton(); toolRegistry.Register(serviceProvider.GetRequiredService()); ``` -------------------------------- ### Environment Variables for AzureFoundry Configuration Source: https://github.com/danielgerlag/workflow-core/blob/master/src/extensions/WorkflowCore.AI.AzureFoundry/readme.md Configure Azure AI Foundry settings using environment variables, including endpoint, API key, default model, and project name. ```bash AZURE_AI_ENDPOINT=https://myresource.services.ai.azure.com AZURE_AI_API_KEY=your-api-key AZURE_AI_DEFAULT_MODEL=gpt-4o AZURE_AI_PROJECT=myproject ``` -------------------------------- ### Configure Redis Services in Workflow Core Source: https://github.com/danielgerlag/workflow-core/blob/master/src/providers/WorkflowCore.Providers.Redis/README.md Configure persistence, locking, queues, and event hubs using Redis by calling extension methods on IServiceCollection. ```csharp services.AddWorkflow(cfg => { cfg.UseRedisPersistence("localhost:6379", "app-name"); cfg.UseRedisLocking("localhost:6379"); cfg.UseRedisQueues("localhost:6379", "app-name"); cfg.UseRedisEventHub("localhost:6379", "channel-name"); }); ``` -------------------------------- ### Configure VectorSearch Step Source: https://github.com/danielgerlag/workflow-core/blob/master/src/extensions/WorkflowCore.AI.AzureFoundry/readme.md Configure a step for performing vector similarity searches against Azure AI Search. This snippet shows how to specify the query, index name, number of results (TopK), and optional OData filters. ```csharp builder .VectorSearch(cfg => cfg .Input(s => s.Query, data => data.SearchQuery) .Input(s => s.IndexName, data => "knowledge-base") .Input(s => s.TopK, data => 5) .Input(s => s.Filter, data => "category eq 'support'") // OData filter .Output(s => s.Results, data => data.SearchResults)); ```