Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
7942350
Ported from Fork
crickman Jul 15, 2025
6f535d1
Typos
crickman Jul 15, 2025
82a0b83
Merge branch 'main' into feature_declarative_workflow
crickman Jul 15, 2025
1194eec
Typo
crickman Jul 15, 2025
aab19d9
More conversion
crickman Jul 16, 2025
c85b55c
Clean-up and validation
crickman Jul 17, 2025
a04e7cf
More tests and organization
crickman Jul 17, 2025
f116112
Some more state actions
crickman Jul 17, 2025
27f49c5
Checkpoint (pre-refactor)
crickman Jul 17, 2025
14f1b0e
Usage definition
crickman Jul 18, 2025
8dc5a01
rename
crickman Jul 18, 2025
45243ce
Update readme
crickman Jul 21, 2025
e4cf1a0
Merge branch 'main' into feature_declarative_workflow
crickman Jul 22, 2025
9d654de
Requirements
crickman Jul 22, 2025
4ced8ec
Definition update
crickman Jul 22, 2025
8d305e7
Update requirements
crickman Jul 23, 2025
64c68b2
Typos
crickman Jul 23, 2025
2fbdfbc
Typo
crickman Jul 23, 2025
3b0cb2a
Typo
crickman Jul 23, 2025
380fd1f
Validation checkpoint
crickman Jul 23, 2025
c95f776
Build checkpoint
crickman Jul 23, 2025
0a233d3
ClearAllVariables experiment
crickman Jul 23, 2025
2ed7f82
Merge branch 'main' into feature_declarative_workflow
crickman Jul 23, 2025
a47e344
Requirements
crickman Jul 23, 2025
bb597d1
Checkpoint
crickman Jul 23, 2025
ca2a960
Cleanup
crickman Jul 23, 2025
aa3e664
Fix init step
crickman Jul 23, 2025
ff0cd9c
More cleanup
crickman Jul 24, 2025
a5aeccb
Clean-up
crickman Jul 24, 2025
f727488
Checkpoint for demo
crickman Jul 29, 2025
7caa5e6
Demo
crickman Jul 29, 2025
a2eba0f
Namespace
crickman Jul 29, 2025
e207667
Namespace
crickman Jul 29, 2025
c10012e
Demo comments
crickman Jul 30, 2025
b65fcc9
Dev sample
crickman Aug 1, 2025
fefe717
Merge branch 'main' into feature_declarative_workflow
crickman Aug 1, 2025
1dfb5b9
Typo
crickman Aug 1, 2025
06b2ce2
Contetx rename / update
crickman Aug 1, 2025
d6a8387
Merge branch 'feature_declarative_workflow' of https://github.com/mic…
crickman Aug 1, 2025
b0e5c5b
Clean-up debug trace
crickman Aug 5, 2025
56c5f71
Merge branch 'main' into feature_declarative_workflow_merge
crickman Aug 5, 2025
c0f5d7b
Merge branch 'feature_declarative_workflow' of https://github.com/mic…
crickman Aug 5, 2025
e6caf59
Checkpoint
crickman Aug 6, 2025
c5df731
Checkpoint++
crickman Aug 6, 2025
297e18e
Loop update
crickman Aug 6, 2025
f3bbe0d
Intercept
crickman Aug 7, 2025
d970f59
Complete expression support
crickman Aug 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dotnet/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.5" />
<PackageVersion Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
<PackageVersion Include="Microsoft.Bcl.Numerics" Version="9.0.5" />
<PackageVersion Include="Microsoft.Bot.ObjectModel" Version="2025.6.4-1" />
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="4.13.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" />
<PackageVersion Include="Microsoft.Identity.Client" Version="4.74.1" />
<PackageVersion Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.74.1" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.13.0" />
<PackageVersion Include="Microsoft.ML.OnnxRuntime" Version="1.22.1" />
<PackageVersion Include="Microsoft.ML.Tokenizers.Data.Cl100kBase" Version="1.0.1" />
<PackageVersion Include="Microsoft.PowerFx.Interpreter" Version="1.3.1" />
<PackageVersion Include="Microsoft.SemanticKernel.Abstractions" Version="1.58.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.OpenAI" Version="1.58.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Core" Version="1.58.0" />
Expand Down
1 change: 1 addition & 0 deletions dotnet/SK-dotnet.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<Project Path="samples/Demos/BookingRestaurant/BookingRestaurant.csproj" />
<Project Path="samples/Demos/CodeInterpreterPlugin/CodeInterpreterPlugin.csproj" />
<Project Path="samples/Demos/ContentSafety/ContentSafety.csproj" />
<Project Path="samples/Demos/DeclarativeWorkflow/DeclarativeWorkflow.csproj" Id="de05e970-d552-4c4b-9d69-b64bb9baff3f" />
<Project Path="samples/Demos/FunctionInvocationApproval/FunctionInvocationApproval.csproj" />
<Project Path="samples/Demos/HomeAutomation/HomeAutomation.csproj" />
<Project Path="samples/Demos/ModelContextProtocolPlugin/ModelContextProtocolPlugin.csproj" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<NoWarn>CA2007;CS0612;VSTHRD111;SKEXP0080</NoWarn>
<UserSecretsId>5ee045b0-aea3-4f08-8d31-32d1a6f8fed0</UserSecretsId>
</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" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\Experimental\Process.Core\Process.Core.csproj" />
<ProjectReference Include="..\..\..\src\Experimental\Process.LocalRuntime\Process.LocalRuntime.csproj" />
<ProjectReference Include="..\..\..\src\Connectors\Connectors.AzureOpenAI\Connectors.AzureOpenAI.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="demo250729.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
82 changes: 82 additions & 0 deletions dotnet/samples/Demos/DeclarativeWorkflow/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Diagnostics;
using System.Reflection;
using Azure.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.SemanticKernel;

namespace Demo.DeclarativeWorkflow;

internal static class Program
{
private const string InputEventId = "start-workflow";

public static async Task Main(string[] args)
{
// Load configuration and create kernel with Azure OpenAI Chat Completion service
IConfiguration config = InitializeConfig();
// Note: "Kernel" isn't required as part of the new "process framework".
Kernel kernel = CreateKernel(config["AzureOpenAI:Endpoint"]!, config["AzureOpenAI:ChatDeploymentName"]!);

Notify("PROCESS INIT\n");

Stopwatch timer = Stopwatch.StartNew();

//////////////////////////////////////////////
// Interpret the workflow YAML into a KernelProcess
using StreamReader yamlReader = File.OpenText("demo250729.yaml");
KernelProcess process = ObjectModelBuilder.Build(yamlReader, InputEventId);
//////////////////////////////////////////////

Notify($"\nPROCESS DEFINED: {timer.Elapsed}\n");

Notify("\nPROCESS INVOKE\n");

//////////////////////////////////////////////
// Run the process, just like any other KernelProcess
// NOTE: The pattern here is expected to change in the new "process framework"
// (ideally, it will become less complex)
await using LocalKernelProcessContext context =
await process.StartAsync(
kernel,
new KernelProcessEvent()
{
Id = InputEventId,
// Pass the first argument as the input data for the process, if present.
Data = args.FirstOrDefault() ?? string.Empty
});
//////////////////////////////////////////////

Notify("\nPROCESS DONE");
}

// Load configuration from user-secrets
private static IConfigurationRoot InitializeConfig() =>
new ConfigurationBuilder()
.AddUserSecrets(Assembly.GetExecutingAssembly())
.Build();

// Create kernel with Azure OpenAI Chat Completion service
private static Kernel CreateKernel(string endpoint, string model)
{
IKernelBuilder kernelBuilder = Kernel.CreateBuilder();

kernelBuilder.AddAzureOpenAIChatCompletion(model, endpoint, new AzureCliCredential());

return kernelBuilder.Build();
}

private static void Notify(string message)
{
Console.ForegroundColor = ConsoleColor.Cyan;
try
{
Console.WriteLine(message);
}
finally
{
Console.ResetColor();
}
}
}
57 changes: 57 additions & 0 deletions dotnet/samples/Demos/DeclarativeWorkflow/demo250729.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
kind: AdaptiveDialog
beginDialog:
kind: OnActivity
id: activity_xyz123
actions:

# Capture optional agent instructions
- kind: SetVariable
id: setVariable_NZ2u0l
variable: Topic.Instructions
value: =System.LastMessage.Text

# Assign a list of inputs in JSON format to a variable
- kind: SetVariable
id: setVariable_aASlmF
displayName: List all of questions for LLM
variable: Topic.Questions
value: |-
=[
"Why is the sky blue?",
"What is the capital of France?",
"Where do rainbows come from?",
]

# Loop over each question in the list
- kind: Foreach
id: foreach_mVIecC
items: =Topic.Questions
index: Topic.LoopIndex
value: Topic.Question
actions:

# Display the current question
- kind: SendActivity
id: sendActivity_lMn07p
activity: "Question {Topic.LoopIndex + 1} - {Topic.Question}"

# Use AI to answer the question
- kind: AnswerQuestionWithAI
id: question_wEJ456
variable: Topic.Answer
userInput: =Topic.Question
additionalInstructions: "{Topic.Instructions}"

# Display the AI's answer
- kind: SendActivity
id: sendActivity_zA3f0p
activity: "AI - {Topic.Answer}"

# After processing all questions, display a completion message
- kind: SendActivity
id: sendActivity_SVoNSV
activity: Complete!

# End the conversation
- kind: EndConversation
id: end_8nXE8H
24 changes: 24 additions & 0 deletions dotnet/samples/Demos/DeclarativeWorkflow/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Summary

This demo showcases the ability to parse a YAML workflow based on Copilo Studio actions
and produce a `KernelProcess` that can be executed in the same fashion as any other `KernelProcess`.

## Key Features

This demo illustrates the following capabilities:

- Parse YAML workflow actions using `Microsoft.Bot.ObjectModel`
- Store and retrieve variable state
- Evaluate expressions using `Microsoft.PowerFx.Interpreter`
- Support control flow (foreach, goto, etc...)
- Generate response from LLM using _Semantic Kernel_

## Status Details

- This is using a POC based on the _Process Framework_ from the _Semantic Kernel_ repo.
- When the redesigned _Process Framework_ is available in the _Agent Framework_ repo it must
be re-implemented using the new API patterns.
- Capturing and restoring workflow state is not yet available in either version of the _Process Framework_.
- The ability to emit events from the _KernelProcess_ to the host API is not yet supported.
- `Microsoft.Bot.ObjectModel` is not (yet) available as a dependency that may be referenced by a _GitHub_ repository.
- The full set of CPSDL actions to be supported is not fully defined, nor are the "Pri-0" samples.
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,10 @@
<EmbeddedResource Include="$(RepoRoot)/dotnet/samples/LearnResources/Resources/Grimms-The-White-Snake.txt" Link="%(RecursiveDir)Resources/%(Filename)%(Extension)" />
</ItemGroup>

<ItemGroup>
<None Update="Step06\*.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ private KernelProcess SetupAccountOpeningProcess<TUserInputStep>() where TUserIn

var accountVerificationStep = process.AddStepFromProcess(NewAccountVerificationProcess.CreateProcess());
var accountCreationStep = process.AddStepFromProcess(NewAccountCreationProcess.CreateProcess());

var mailServiceStep = process.AddStepFromType<MailServiceStep>();

process
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static class ProcessStepFunctions
public const string RenderUserText = nameof(RenderMessageStep.RenderUserText);
}

private readonly static Stopwatch s_timer = Stopwatch.StartNew();
private static readonly Stopwatch s_timer = Stopwatch.StartNew();

/// <summary>
/// Render an explicit message to indicate the process has completed in the expected state.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
name: deepresearch
states:
- name: GatherFacts
actors:
- agent: LedgerFacts
inputs:
instructions: instructions
outputs:
task: task
facts: facts
thread: Planning
humanInLoopMode: onNoMessage
streamOutput: false
isFinal: false
- name: Plan
actors:
- agent: LedgerPlanner
inputs:
task: task
facts: facts
team: team
instructions: instructions
messagesOut: plannerMessages
thread: Planning
humanInLoopMode: never
streamOutput: true
isFinal: false
- name: ProcessProgress
actors:
- agent: ProgressLedger
inputs:
task: task
team: team
systemAgents: systemAgents
messagesOut: nextStepMessages
messagesIn:
- plannerMessages
thread: Run
humanInLoopMode: never
streamOutput: true
isFinal: false
- name: actionRouter
actors:
- agent: ActionRouterAgent
messagesIn:
- nextStepMessages
inputs:
team: team
systemAgents: systemAgents
outputs:
targetAgent: nextAgent
humanInLoopMode: never
streamOutput: true
- name: dynamicStepAgent
actors:
- agent: nextAgent
thread: Run
humanInLoopMode: never
streamOutput: true
- name: UpdateLedgerFact
actors:
- agent: LedgerFactsUpdate
thread: Run
inputs:
task: task
facts: facts
outputs:
updatedFacts: facts
humanInLoopMode: never
streamOutput: false
isFinal: false
- name: LedgerPlanUpdate
actors:
- agent: LedgerPlanUpdate
inputs:
facts: facts
team: team
messagesOut: plannerMessages
thread: Run
humanInLoopMode: never
streamOutput: true
isFinal: false
- name: Summarizer
actors:
- agent: FinalStepAgent
thread: Run
inputs:
task: task
humanInLoopMode: never
streamOutput: true
isFinal: true
transitions:
- from: GatherFacts
to: Plan
- from: Plan
to: ProcessProgress
- from: LedgerPlanUpdate
to: ProcessProgress
- from: ProcessProgress
to: actionRouter
- from: actionRouter
to: UpdateLedgerFact
condition: nextAgent.Equals(LedgerFactsUpdate)
- from: actionRouter
to: Summarizer
condition: nextAgent.Equals(FinalStepAgent)
- from: actionRouter
to: dynamicStepAgent
condition: nextAgent.NotContains(FinalStepAgent)
- from: dynamicStepAgent
to: ProcessProgress
- from: UpdateLedgerFact
to: LedgerPlanUpdate
variables:
- Type: userDefined
name: team
- Type: userDefined
name: instructions
- Type: userDefined
name: task
- Type: userDefined
name: facts
- Type: userDefined
name: plan
- Type: messages
name: plannerMessages
- Type: thread
name: Planning
- Type: thread
name: Run
- Type: messages
name: nextStepMessages
- Type: userDefined
name: nextAgent
- Type: userDefined
name: systemAgents
value:
- agent: FinalStepAgent
description: >-
Agent which summarizes the output after task is complete. When next speaker is none.
- agent: LedgerFactsUpdate
description: >-
Agent which can update the plan if we are looping without making progress or stall is detected.
startstate: GatherFacts
Loading
Loading