From 4d63899812417abeca39ab5e79cb1ea38751e549 Mon Sep 17 00:00:00 2001
From: Chris <66376200+crickman@users.noreply.github.com>
Date: Fri, 26 Sep 2025 14:44:19 -0700
Subject: [PATCH] .NET Workflows - Introduce support for `Local` variable scope
(#944)
* Prepare for update
* Checkpoint
* Comments
* All fixed
* Mixed casre test added
* Rollback nuget
* Remove redundant restorable
* Namespace
---
dotnet/Directory.Packages.props | 6 +-
.../DeclarativeWorkflowBuilder.cs | 6 +-
.../Extensions/IWorkflowContextExtensions.cs | 8 +-
.../Interpreter/DeclarativeWorkflowContext.cs | 1 +
.../Interpreter/WorkflowActionVisitor.cs | 11 +-
.../Interpreter/WorkflowElementWalker.cs | 5 -
...rosoft.Agents.Workflows.Declarative.csproj | 1 +
.../PowerFx/RecalcEngineFactory.cs | 3 +-
.../PowerFx/WorkflowDiagnostics.cs | 4 +-
.../PowerFx/WorkflowFormulaState.cs | 48 ++++--
.../Framework/WorkflowTest.cs | 4 +-
.../Workflows/AddMessages.yaml | 18 +--
.../Workflows/GetMessage.yaml | 4 +-
.../Workflows/GetMessages.yaml | 4 +-
.../Workflows/InvokeAgent.yaml | 2 +-
.../Workflows/SendActivity.yaml | 4 +-
.../DeclarativeWorkflowTest.cs | 22 ++-
.../ObjectModel/WorkflowActionExecutorTest.cs | 6 +-
.../PowerFx/WorkflowExpressionEngineTests.cs | 16 +-
.../PowerFx/WorkflowFormulaStateTests.cs | 10 +-
.../WorkflowTest.cs | 4 +-
.../Workflows/Condition.yaml | 6 +-
.../Workflows/ConditionElse.yaml | 4 +-
.../Workflows/EditTable.yaml | 4 +-
.../Workflows/EditTableV2.yaml | 4 +-
.../Workflows/{Single.yaml => EndDialog.yaml} | 6 +-
.../Workflows/LoopBreak.yaml | 12 +-
.../Workflows/LoopContinue.yaml | 12 +-
.../Workflows/LoopEach.yaml | 12 +-
.../Workflows/MixedScopes.yaml | 16 ++
.../Workflows/ParseValue.yaml | 2 +-
.../Workflows/ResetVariable.yaml | 4 +-
.../Workflows/SendActivity.yaml | 4 +-
.../Workflows/SetTextVariable.yaml | 2 +-
.../Workflows/SetVariable.yaml | 2 +-
workflow-samples/DeepResearch.yaml | 144 +++++++++---------
workflow-samples/HumanInLoop.yaml | 12 +-
workflow-samples/MathChat.yaml | 16 +-
38 files changed, 242 insertions(+), 207 deletions(-)
rename dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/{Single.yaml => EndDialog.yaml} (50%)
create mode 100644 dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/MixedScopes.yaml
diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props
index 9ba4eb3ae2..7841b9be70 100644
--- a/dotnet/Directory.Packages.props
+++ b/dotnet/Directory.Packages.props
@@ -90,9 +90,9 @@
-
-
-
+
+
+
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/DeclarativeWorkflowBuilder.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/DeclarativeWorkflowBuilder.cs
index c68713d4a3..2e2a6460af 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/DeclarativeWorkflowBuilder.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/DeclarativeWorkflowBuilder.cs
@@ -17,7 +17,7 @@ namespace Microsoft.Agents.Workflows.Declarative;
public static class DeclarativeWorkflowBuilder
{
///
- /// Builds a process from the provided YAML definition of a CPS Topic ObjectModel.
+ /// Builds a workflow from the provided YAML definition.
///
/// The type of the input message
/// The path to the workflow.
@@ -35,7 +35,7 @@ public static class DeclarativeWorkflowBuilder
}
///
- /// Builds a process from the provided YAML definition of a CPS Topic ObjectModel.
+ /// Builds a workflow from the provided YAML definition.
///
/// The type of the input message
/// The reader that provides the workflow object model YAML.
@@ -71,7 +71,7 @@ public static class DeclarativeWorkflowBuilder
return visitor.Complete();
}
- private static ChatMessage DefaultTransform(object message) =>
+ internal static ChatMessage DefaultTransform(object message) =>
message switch
{
ChatMessage chatMessage => chatMessage,
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Extensions/IWorkflowContextExtensions.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Extensions/IWorkflowContextExtensions.cs
index 1ea2f6c8df..ee1b5697c2 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Extensions/IWorkflowContextExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Extensions/IWorkflowContextExtensions.cs
@@ -23,16 +23,16 @@ internal static class IWorkflowContextExtensions
context.SendMessageAsync(new ExecutorResultMessage(id, result));
public static ValueTask QueueStateResetAsync(this IWorkflowContext context, PropertyPath variablePath) =>
- context.QueueStateUpdateAsync(Throw.IfNull(variablePath.VariableName), UnassignedValue.Instance, Throw.IfNull(variablePath.VariableScopeName));
+ context.QueueStateUpdateAsync(Throw.IfNull(variablePath.VariableName), UnassignedValue.Instance, Throw.IfNull(variablePath.NamespaceAlias));
public static ValueTask QueueStateUpdateAsync(this IWorkflowContext context, PropertyPath variablePath, TValue? value) =>
- context.QueueStateUpdateAsync(Throw.IfNull(variablePath.VariableName), value, Throw.IfNull(variablePath.VariableScopeName));
+ context.QueueStateUpdateAsync(Throw.IfNull(variablePath.VariableName), value, Throw.IfNull(variablePath.NamespaceAlias));
public static ValueTask QueueSystemUpdateAsync(this IWorkflowContext context, string key, TValue? value) =>
DeclarativeContext(context).QueueSystemUpdateAsync(key, value);
public static FormulaValue ReadState(this IWorkflowContext context, PropertyPath variablePath) =>
- context.ReadState(Throw.IfNull(variablePath.VariableName), Throw.IfNull(variablePath.VariableScopeName));
+ context.ReadState(Throw.IfNull(variablePath.VariableName), Throw.IfNull(variablePath.NamespaceAlias));
public static FormulaValue ReadState(this IWorkflowContext context, string key, string? scopeName = null) =>
DeclarativeContext(context).State.Get(key, scopeName);
@@ -51,7 +51,7 @@ internal static class IWorkflowContextExtensions
public static async ValueTask EnsureWorkflowConversationAsync(this IWorkflowContext context, WorkflowAgentProvider agentProvider, StringExpression expression, CancellationToken cancellationToken)
{
if (expression.IsVariableReference &&
- expression.VariableReference.IsVariableReferenceWithScope(VariableScopeNames.System, out string? variableName))
+ expression.VariableReference.IsVariableReferenceWithScope(VariableNamespace.System, out string? variableName))
{
if (string.Equals(variableName, SystemScope.Names.Conversation, StringComparison.Ordinal) ||
string.Equals(variableName, SystemScope.Names.ConversationId, StringComparison.Ordinal))
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/DeclarativeWorkflowContext.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/DeclarativeWorkflowContext.cs
index d3859ccb77..b92ec3969f 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/DeclarativeWorkflowContext.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/DeclarativeWorkflowContext.cs
@@ -16,6 +16,7 @@ internal sealed class DeclarativeWorkflowContext : IWorkflowContext
{
public static readonly FrozenSet ManagedScopes =
[
+ VariableScopeNames.Local,
VariableScopeNames.Topic,
VariableScopeNames.Global,
];
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/WorkflowActionVisitor.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/WorkflowActionVisitor.cs
index b058c4dc36..c9ebdca9a6 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/WorkflowActionVisitor.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/WorkflowActionVisitor.cs
@@ -211,6 +211,15 @@ internal sealed class WorkflowActionVisitor : DialogActionVisitor
this.RestartAfter(item.Id.Value, endExecutor.ParentId);
}
+ protected override void Visit(EndDialog item)
+ {
+ this.Trace(item);
+
+ DefaultActionExecutor endExecutor = new(item, this._workflowState);
+ this.ContinueWith(endExecutor);
+ this.RestartAfter(item.Id.Value, endExecutor.ParentId);
+ }
+
protected override void Visit(Question item)
{
this.Trace(item);
@@ -388,8 +397,6 @@ internal sealed class WorkflowActionVisitor : DialogActionVisitor
protected override void Visit(UnknownDialogAction item) => this.NotSupported(item);
- protected override void Visit(EndDialog item) => this.NotSupported(item);
-
protected override void Visit(RepeatDialog item) => this.NotSupported(item);
protected override void Visit(ReplaceDialog item) => this.NotSupported(item);
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/WorkflowElementWalker.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/WorkflowElementWalker.cs
index cafb0a5a39..26f37f9102 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/WorkflowElementWalker.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/WorkflowElementWalker.cs
@@ -6,11 +6,6 @@ namespace Microsoft.Agents.Workflows.Declarative.Interpreter;
internal sealed class WorkflowElementWalker : BotElementWalker
{
- static WorkflowElementWalker()
- {
- ProductContext.SetContext(Product.Foundry);
- }
-
private readonly DialogActionVisitor _visitor;
public WorkflowElementWalker(DialogActionVisitor visitor)
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Microsoft.Agents.Workflows.Declarative.csproj b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Microsoft.Agents.Workflows.Declarative.csproj
index 5ac3d65dd0..5f6b6dded8 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Microsoft.Agents.Workflows.Declarative.csproj
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Microsoft.Agents.Workflows.Declarative.csproj
@@ -37,6 +37,7 @@
+
\ No newline at end of file
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/PowerFx/RecalcEngineFactory.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/PowerFx/RecalcEngineFactory.cs
index b6e7bff333..dfcea949b1 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/PowerFx/RecalcEngineFactory.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/PowerFx/RecalcEngineFactory.cs
@@ -17,8 +17,9 @@ internal static class RecalcEngineFactory
foreach (string scopeName in VariableScopeNames.AllScopes)
{
- engine.UpdateVariable(scopeName, RecordValue.Empty());
+ engine.UpdateVariable(WorkflowFormulaState.GetScopeName(scopeName), RecordValue.Empty());
}
+ engine.UpdateVariable(VariableScopeNames.Topic, RecordValue.Empty());
return engine;
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/PowerFx/WorkflowDiagnostics.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/PowerFx/WorkflowDiagnostics.cs
index 7b2486420a..4aff190608 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/PowerFx/WorkflowDiagnostics.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/PowerFx/WorkflowDiagnostics.cs
@@ -59,13 +59,13 @@ internal static class WorkflowDiagnostics
FormulaValue defaultValue = variableDiagnostic.ConstantValue?.ToFormula() ?? variableDiagnostic.Type.NewBlank();
- if (variableDiagnostic.Path.VariableScopeName?.Equals(VariableScopeNames.System, StringComparison.OrdinalIgnoreCase) is true &&
+ if (variableDiagnostic.Path.NamespaceAlias?.Equals(VariableScopeNames.System, StringComparison.OrdinalIgnoreCase) is true &&
!SystemScope.AllNames.Contains(variableDiagnostic.Path.VariableName))
{
throw new DeclarativeModelException($"Variable '{variableDiagnostic.Path.VariableName}' is not a supported system variable.");
}
- scopes.Set(variableDiagnostic.Path.VariableName, defaultValue, variableDiagnostic.Path.VariableScopeName ?? WorkflowFormulaState.DefaultScopeName);
+ scopes.Set(variableDiagnostic.Path.VariableName, defaultValue, variableDiagnostic.Path.NamespaceAlias ?? WorkflowFormulaState.DefaultScopeName);
}
}
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/PowerFx/WorkflowFormulaState.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/PowerFx/WorkflowFormulaState.cs
index 3fa2b7950d..735905cc97 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/PowerFx/WorkflowFormulaState.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/PowerFx/WorkflowFormulaState.cs
@@ -17,12 +17,11 @@ namespace Microsoft.Agents.Workflows.Declarative.PowerFx;
///
internal sealed class WorkflowFormulaState
{
- // ISSUE #488 - Update default scope for workflows to `Workflow` (instead of `Topic`)
- public const string DefaultScopeName = VariableScopeNames.Topic;
+ public const string DefaultScopeName = VariableScopeNames.Local;
public static readonly FrozenSet RestorableScopes =
[
- VariableScopeNames.Topic,
+ VariableScopeNames.Local,
VariableScopeNames.Global,
VariableScopeNames.System,
];
@@ -37,7 +36,8 @@ internal sealed class WorkflowFormulaState
public WorkflowFormulaState(RecalcEngine engine)
{
- this._scopes = VariableScopeNames.AllScopes.ToDictionary(scopeName => scopeName, scopeName => new WorkflowScope());
+ this._scopes = VariableScopeNames.AllScopes.ToDictionary(scopeName => GetScopeName(scopeName), _ => new WorkflowScope());
+
this.Engine = engine;
this.Evaluator = new WorkflowExpressionEngine(engine);
this.Bind();
@@ -87,11 +87,15 @@ internal sealed class WorkflowFormulaState
}
}
- public void Bind(string? targetScope = null)
+ public void Bind(string? scopeNameToBind = null)
{
- if (targetScope is not null)
+ if (scopeNameToBind is not null)
{
- Bind(targetScope);
+ Bind(scopeNameToBind);
+ if (VariableScopeNames.GetNamespaceFromName(scopeNameToBind) == VariableNamespace.Component)
+ {
+ Bind(scopeNameToBind, VariableScopeNames.Topic);
+ }
}
else
{
@@ -99,26 +103,38 @@ internal sealed class WorkflowFormulaState
{
Bind(scopeName);
}
+
+ Bind(DefaultScopeName, VariableScopeNames.Topic);
}
- void Bind(string scopeName)
+ void Bind(string scopeName, string? targetScope = null)
{
+ targetScope = GetScopeName(targetScope ?? scopeName);
RecordValue scopeRecord = this.GetScope(scopeName).ToRecord();
- this.Engine.DeleteFormula(scopeName);
- this.Engine.UpdateVariable(scopeName, scopeRecord);
+ this.Engine.DeleteFormula(targetScope);
+ this.Engine.UpdateVariable(targetScope, scopeRecord);
}
}
- private WorkflowScope GetScope(string? scopeName)
- {
- scopeName ??= DefaultScopeName;
+ private WorkflowScope GetScope(string? scopeName) => this._scopes[GetScopeName(scopeName)];
- if (!VariableScopeNames.IsValidName(scopeName))
+ public static string GetScopeName(string? scopeName)
+ {
+ if (!ProductContext.IsLocalScopeSupported())
{
- throw new DeclarativeActionException($"Invalid variable scope name: '{scopeName}'.");
+ ProductContext.SetContext(Product.Foundry);
}
- return this._scopes[scopeName];
+ scopeName ??= DefaultScopeName;
+
+ return
+ VariableScopeNames.GetNamespaceFromName(scopeName) switch
+ {
+ // Always alias component level scope as "Local"
+ VariableNamespace.Component => DefaultScopeName,
+ VariableNamespace.Unknown => throw new DeclarativeActionException($"Invalid variable scope name: '{scopeName}'."),
+ _ => scopeName,
+ };
}
///
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Framework/WorkflowTest.cs b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Framework/WorkflowTest.cs
index 574cbbb3c5..b982c608df 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Framework/WorkflowTest.cs
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Framework/WorkflowTest.cs
@@ -2,7 +2,7 @@
using System;
using System.Reflection;
-using Microsoft.Bot.ObjectModel;
+using Microsoft.Agents.Workflows.Declarative.PowerFx;
using Microsoft.Extensions.Configuration;
using Xunit.Abstractions;
@@ -35,7 +35,7 @@ public abstract class WorkflowTest : IDisposable
}
}
- internal static string FormatVariablePath(string variableName, string? scope = null) => $"{scope ?? VariableScopeNames.Topic}.{variableName}";
+ internal static string FormatVariablePath(string variableName, string? scope = null) => $"{scope ?? WorkflowFormulaState.DefaultScopeName}.{variableName}";
protected static IConfigurationRoot InitializeConfig() =>
new ConfigurationBuilder()
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/AddMessages.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/AddMessages.yaml
index f957c3fca0..06238aa3a2 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/AddMessages.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/AddMessages.yaml
@@ -7,23 +7,23 @@ trigger:
- kind: CreateConversation
id: conversation_create1
- conversationId: Topic.FirstConversationId
+ conversationId: Local.FirstConversationId
- kind: CreateConversation
id: conversation_create2
- conversationId: Topic.SecondConversationId
+ conversationId: Local.SecondConversationId
- kind: SendActivity
id: sendActivity_conversation
activity: |-
- Conversation 1: {Topic.FirstConversationId}
- Conversation 2: {Topic.SecondConversationId}
+ Conversation 1: {Local.FirstConversationId}
+ Conversation 2: {Local.SecondConversationId}
- kind: AddConversationMessage
id: add_message
- message: Topic.MyMessage1
+ message: Local.MyMessage1
role: User
- conversationId: =Topic.FirstConversationId
+ conversationId: =Local.FirstConversationId
content:
- type: Text
value: {System.LastMessage.Text}
@@ -31,12 +31,12 @@ trigger:
- kind: SendActivity
id: sendActivity_message
activity: |-
- Messsage 1: {Topic.MyMessage1}
+ Messsage 1: {Local.MyMessage1}
- kind: CopyConversationMessages
id: copy_messages
- conversationId: =Topic.SecondConversationId
- messages: =[Topic.MyMessage1]
+ conversationId: =Local.SecondConversationId
+ messages: =[Local.MyMessage1]
- kind: SendActivity
id: sendActivity_copy
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/GetMessage.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/GetMessage.yaml
index 72b7ef3eae..5cee7dc72c 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/GetMessage.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/GetMessage.yaml
@@ -7,11 +7,11 @@ trigger:
- kind: RetrieveConversationMessage
id: get_message
- message: Topic.MyMessage
+ message: Local.MyMessage
conversationId: thread_T8xIzNrNcPkUkoCEGzxg80Vt
messageId: msg_J4x6YZTDUUWNs60FOUAucldy
- kind: SendActivity
id: sendActivity_message
activity: |-
- {Topic.MyMessage}
+ {Local.MyMessage}
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/GetMessages.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/GetMessages.yaml
index 45eb153949..f47fbb76d5 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/GetMessages.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/GetMessages.yaml
@@ -7,10 +7,10 @@ trigger:
- kind: RetrieveConversationMessages
id: get_message
- messages: Topic.MyMessages
+ messages: Local.MyMessages
conversationId: thread_T8xIzNrNcPkUkoCEGzxg80Vt
- kind: SendActivity
id: sendActivity_message
activity: |-
- {Topic.MyMessages}
+ {Local.MyMessages}
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/InvokeAgent.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/InvokeAgent.yaml
index af874bdfce..02397eb733 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/InvokeAgent.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/InvokeAgent.yaml
@@ -12,4 +12,4 @@ trigger:
input:
messages: =[UserMessage(System.LastMessageText)]
output:
- messages: Topic.Answer
+ messages: Local.Answer
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/SendActivity.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/SendActivity.yaml
index 88d5ee97f5..18384df2da 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/SendActivity.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.IntegrationTests/Workflows/SendActivity.yaml
@@ -8,7 +8,7 @@ trigger:
# Capture input
- kind: SetVariable
id: set_user_input
- variable: Topic.UserInput
+ variable: Local.UserInput
value: =System.LastMessage.Text
# Capture environment variable
@@ -22,4 +22,4 @@ trigger:
id: send_result
activity: |-
Hello {Global.UserName},
- You said, "{Topic.UserInput}"
+ You said, "{Local.UserInput}"
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/DeclarativeWorkflowTest.cs b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/DeclarativeWorkflowTest.cs
index 61bac9da8c..f30a2a4f3f 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/DeclarativeWorkflowTest.cs
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/DeclarativeWorkflowTest.cs
@@ -7,7 +7,6 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.Agents.Workflows.Declarative.Interpreter;
using Microsoft.Agents.Workflows.Declarative.PowerFx;
-using Microsoft.Agents.Workflows.Reflection;
using Microsoft.Bot.ObjectModel;
using Moq;
using Xunit.Abstractions;
@@ -140,7 +139,8 @@ public sealed class DeclarativeWorkflowTest(ITestOutputHelper output) : Workflow
}
[Theory]
- [InlineData("Single.yaml", 1, "end_all")]
+ [InlineData("EndConversation.yaml", 1, "end_all")]
+ [InlineData("EndDialog.yaml", 1, "end_all")]
[InlineData("EditTable.yaml", 2, "edit_var")]
[InlineData("EditTableV2.yaml", 2, "edit_var")]
[InlineData("ParseValue.yaml", 1, "parse_var")]
@@ -149,6 +149,7 @@ public sealed class DeclarativeWorkflowTest(ITestOutputHelper output) : Workflow
[InlineData("SetTextVariable.yaml", 1, "set_text")]
[InlineData("ClearAllVariables.yaml", 1, "clear_all")]
[InlineData("ResetVariable.yaml", 2, "clear_var")]
+ [InlineData("MixedScopes.yaml", 2, "activity_input")]
public async Task ExecuteActionAsync(string workflowFile, int expectedCount, string expectedId)
{
await this.RunWorkflowAsync(workflowFile);
@@ -168,7 +169,6 @@ public sealed class DeclarativeWorkflowTest(ITestOutputHelper output) : Workflow
[InlineData(typeof(DisableTrigger.Builder))]
[InlineData(typeof(DisconnectedNodeContainer.Builder))]
[InlineData(typeof(EmitEvent.Builder))]
- [InlineData(typeof(EndDialog.Builder))]
[InlineData(typeof(GetActivityMembers.Builder))]
[InlineData(typeof(GetConversationMembers.Builder))]
[InlineData(typeof(HttpRequestAction.Builder))]
@@ -211,7 +211,7 @@ public sealed class DeclarativeWorkflowTest(ITestOutputHelper output) : Workflow
WorkflowFormulaState state = new(RecalcEngineFactory.Create());
Mock mockAgentProvider = new(MockBehavior.Strict);
DeclarativeWorkflowOptions options = new(mockAgentProvider.Object);
- WorkflowActionVisitor visitor = new(new RootExecutor(), state, options);
+ WorkflowActionVisitor visitor = new(new DeclarativeWorkflowExecutor(WorkflowActionVisitor.Steps.Root("anything"), state, (message) => DeclarativeWorkflowBuilder.DefaultTransform(message)), state, options);
WorkflowElementWalker walker = new(visitor);
walker.Visit(dialog);
Assert.True(visitor.HasUnsupportedActions);
@@ -244,7 +244,7 @@ public sealed class DeclarativeWorkflowTest(ITestOutputHelper output) : Workflow
Assert.Contains(this.WorkflowEvents.OfType(), e => string.Equals(e.Message.Trim(), message, StringComparison.Ordinal));
private Task RunWorkflowAsync(string workflowPath) =>
- this.RunWorkflowAsync(workflowPath, string.Empty);
+ this.RunWorkflowAsync(workflowPath, "Test input message");
private async Task RunWorkflowAsync(string workflowPath, TInput workflowInput) where TInput : notnull
{
@@ -272,6 +272,10 @@ public sealed class DeclarativeWorkflowTest(ITestOutputHelper output) : Workflow
{
this.Output.WriteLine($"ACTION EXIT: {actionCompleteEvent.ActionId}");
}
+ else if (workflowEvent is MessageActivityEvent activityEvent)
+ {
+ this.Output.WriteLine($"ACTIVITY: {activityEvent.Message}");
+ }
else if (workflowEvent is AgentRunResponseEvent messageEvent)
{
this.Output.WriteLine($"MESSAGE: {messageEvent.Response.Messages[0].Text.Trim()}");
@@ -279,12 +283,4 @@ public sealed class DeclarativeWorkflowTest(ITestOutputHelper output) : Workflow
}
this.WorkflowEventCounts = this.WorkflowEvents.GroupBy(e => e.GetType()).ToDictionary(e => e.Key, e => e.Count());
}
-
- private sealed class RootExecutor() :
- ReflectingExecutor(WorkflowActionVisitor.Steps.Root("anything")),
- IMessageHandler
- {
- public async ValueTask HandleAsync(string message, IWorkflowContext context) =>
- await context.SendMessageAsync($"{this.Id}: {DateTime.UtcNow:t}").ConfigureAwait(false);
- }
}
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/ObjectModel/WorkflowActionExecutorTest.cs b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/ObjectModel/WorkflowActionExecutorTest.cs
index a13bc8c2d2..7bae493fde 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/ObjectModel/WorkflowActionExecutorTest.cs
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/ObjectModel/WorkflowActionExecutorTest.cs
@@ -42,7 +42,7 @@ public abstract class WorkflowActionExecutorTest(ITestOutputHelper output) : Wor
Assert.Equal(model, action.Model);
}
- protected void VerifyState(string variableName, FormulaValue expectedValue) => this.VerifyState(variableName, VariableScopeNames.Topic, expectedValue);
+ protected void VerifyState(string variableName, FormulaValue expectedValue) => this.VerifyState(variableName, WorkflowFormulaState.DefaultScopeName, expectedValue);
internal void VerifyState(string variableName, string scopeName, FormulaValue expectedValue)
{
@@ -50,9 +50,7 @@ public abstract class WorkflowActionExecutorTest(ITestOutputHelper output) : Wor
Assert.Equal(expectedValue.Format(), actualValue.Format());
}
- protected void VerifyUndefined(string variableName) => this.VerifyUndefined(variableName, VariableScopeNames.Topic);
-
- internal void VerifyUndefined(string variableName, string scopeName) =>
+ internal void VerifyUndefined(string variableName, string? scopeName = null) =>
Assert.IsType(this.State.Get(variableName, scopeName));
protected static TAction AssignParent(DialogAction.Builder actionBuilder) where TAction : DialogAction
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/PowerFx/WorkflowExpressionEngineTests.cs b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/PowerFx/WorkflowExpressionEngineTests.cs
index 9d612b3dc5..5d74e3ff1e 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/PowerFx/WorkflowExpressionEngineTests.cs
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/PowerFx/WorkflowExpressionEngineTests.cs
@@ -34,14 +34,14 @@ public class WorkflowExpressionEngineTests : RecalcEngineTest
: base(output)
{
this.State.Set(Variables.GlobalValue, FormulaValue.New(255), VariableScopeNames.Global);
- this.State.Set(Variables.BoolValue, FormulaValue.New(true), VariableScopeNames.Topic);
- this.State.Set(Variables.StringValue, FormulaValue.New("Hello World"), VariableScopeNames.Topic);
- this.State.Set(Variables.IntValue, FormulaValue.New(long.MaxValue), VariableScopeNames.Topic);
- this.State.Set(Variables.NumberValue, FormulaValue.New(33.3), VariableScopeNames.Topic);
- this.State.Set(Variables.EnumValue, FormulaValue.New(nameof(VariablesToClear.ConversationScopedVariables)), VariableScopeNames.Topic);
- this.State.Set(Variables.ObjectValue, ObjectData, VariableScopeNames.Topic);
- this.State.Set(Variables.ArrayValue, TableData, VariableScopeNames.Topic);
- this.State.Set(Variables.BlankValue, FormulaValue.NewBlank(), VariableScopeNames.Topic);
+ this.State.Set(Variables.BoolValue, FormulaValue.New(true));
+ this.State.Set(Variables.StringValue, FormulaValue.New("Hello World"));
+ this.State.Set(Variables.IntValue, FormulaValue.New(long.MaxValue));
+ this.State.Set(Variables.NumberValue, FormulaValue.New(33.3));
+ this.State.Set(Variables.EnumValue, FormulaValue.New(nameof(VariablesToClear.ConversationScopedVariables)));
+ this.State.Set(Variables.ObjectValue, ObjectData);
+ this.State.Set(Variables.ArrayValue, TableData);
+ this.State.Set(Variables.BlankValue, FormulaValue.NewBlank());
this.State.Bind();
}
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/PowerFx/WorkflowFormulaStateTests.cs b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/PowerFx/WorkflowFormulaStateTests.cs
index bf026747ed..0ee97de4ea 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/PowerFx/WorkflowFormulaStateTests.cs
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/PowerFx/WorkflowFormulaStateTests.cs
@@ -15,7 +15,7 @@ public class WorkflowFormulaStateTests
{
// Arrange
FormulaValue testValue = FormulaValue.New("test");
- this.State.Set("key1", testValue, VariableScopeNames.Topic);
+ this.State.Set("key1", testValue);
// Act
FormulaValue result = this.State.Get("key1");
@@ -48,7 +48,7 @@ public class WorkflowFormulaStateTests
this.State.Set("key1", testValue);
// Assert
- FormulaValue result = this.State.Get("key1", VariableScopeNames.Topic);
+ FormulaValue result = this.State.Get("key1");
Assert.Equal(testValue, result);
}
@@ -74,11 +74,11 @@ public class WorkflowFormulaStateTests
FormulaValue newValue = FormulaValue.New("new");
// Act
- this.State.Set("key1", initialValue, VariableScopeNames.Topic);
- this.State.Set("key1", newValue, VariableScopeNames.Topic);
+ this.State.Set("key1", initialValue);
+ this.State.Set("key1", newValue);
// Assert
- FormulaValue result = this.State.Get("key1", VariableScopeNames.Topic);
+ FormulaValue result = this.State.Get("key1");
Assert.Equal(newValue, result);
}
}
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/WorkflowTest.cs b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/WorkflowTest.cs
index 809f05cbbc..dde50db9b8 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/WorkflowTest.cs
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/WorkflowTest.cs
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
-using Microsoft.Bot.ObjectModel;
+using Microsoft.Agents.Workflows.Declarative.PowerFx;
using Xunit.Abstractions;
namespace Microsoft.Agents.Workflows.Declarative.UnitTests;
@@ -36,5 +36,5 @@ public abstract class WorkflowTest : IDisposable
internal static string? FormatOptionalPath(string? variableName, string? scope = null) =>
variableName is null ? null : FormatVariablePath(variableName, scope);
- internal static string FormatVariablePath(string variableName, string? scope = null) => $"{scope ?? VariableScopeNames.Topic}.{variableName}";
+ internal static string FormatVariablePath(string variableName, string? scope = null) => $"{scope ?? WorkflowFormulaState.DefaultScopeName}.{variableName}";
}
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/Condition.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/Condition.yaml
index 9505c5dc6d..c79f5f0552 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/Condition.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/Condition.yaml
@@ -7,21 +7,21 @@ trigger:
- kind: SetVariable
id: setVariable_test
- variable: Topic.TestValue
+ variable: Local.TestValue
value: =Value(System.LastMessageText)
- kind: ConditionGroup
id: conditionGroup_test
conditions:
- id: conditionItem_odd
- condition: =Mod(Topic.TestValue, 2) = 1
+ condition: =Mod(Local.TestValue, 2) = 1
actions:
- kind: SendActivity
id: sendActivity_odd
activity: ODD
- id: conditionItem_even
- condition: =Mod(Topic.TestValue, 2) = 0
+ condition: =Mod(Local.TestValue, 2) = 0
actions:
- kind: SendActivity
id: sendActivity_even
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/ConditionElse.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/ConditionElse.yaml
index 6431e83be6..667720a913 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/ConditionElse.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/ConditionElse.yaml
@@ -7,14 +7,14 @@ trigger:
- kind: SetVariable
id: setVariable_test
- variable: Topic.TestValue
+ variable: Local.TestValue
value: =Value(System.LastMessageText)
- kind: ConditionGroup
id: conditionGroup_test
conditions:
- id: conditionItem_odd
- condition: =Mod(Topic.TestValue, 2) = 1
+ condition: =Mod(Local.TestValue, 2) = 1
actions:
- kind: SendActivity
id: sendActivity_odd
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/EditTable.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/EditTable.yaml
index 560a503d6c..a4c7453c50 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/EditTable.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/EditTable.yaml
@@ -7,11 +7,11 @@ trigger:
- kind: SetVariable
id: set_var
- variable: Topic.MyTable
+ variable: Local.MyTable
value: =[{id: 3}]
- kind: EditTable
id: edit_var
- itemsVariable: Topic.MyTable
+ itemsVariable: Local.MyTable
changeType: Add
value: ={id: 7}
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/EditTableV2.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/EditTableV2.yaml
index 9a214fb8c0..b1debbff1d 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/EditTableV2.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/EditTableV2.yaml
@@ -7,12 +7,12 @@ trigger:
- kind: SetVariable
id: set_var
- variable: Topic.MyTable
+ variable: Local.MyTable
value: =[{id: 3}]
- kind: EditTableV2
id: edit_var
- itemsVariable: Topic.MyTable
+ itemsVariable: Local.MyTable
changeType:
kind: AddItemOperation
value: ={id: 7}
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/Single.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/EndDialog.yaml
similarity index 50%
rename from dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/Single.yaml
rename to dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/EndDialog.yaml
index 6199adcd1b..e883b609d8 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/Single.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/EndDialog.yaml
@@ -5,5 +5,9 @@ trigger:
id: my_workflow
actions:
- - kind: EndConversation
+ - kind: EndDialog
id: end_all
+
+ - kind: SendActivity
+ id: send_activity_1
+ activity: NEVER 1!
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/LoopBreak.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/LoopBreak.yaml
index 7eba8fb9ee..31a0cdcf78 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/LoopBreak.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/LoopBreak.yaml
@@ -7,24 +7,24 @@ trigger:
- kind: SetVariable
id: setVariable_count
- variable: Topic.Count
+ variable: Local.Count
value: =0
- kind: Foreach
id: foreach_loop
items: =["a", "b", "c", "d", "e", "f"]
- index: Topic.LoopIndex
- value: Topic.LoopValue
+ index: Local.LoopIndex
+ value: Local.LoopValue
actions:
- kind: BreakLoop
id: breakLoop_now
- kind: SetVariable
id: setVariable_loop
- variable: Topic.Count
- value: =Topic.Count + 1
+ variable: Local.Count
+ value: =Local.Count + 1
- kind: SendActivity
id: sendActivity_loop
- activity: x{Topic.Count} - {Topic.LoopIndex}:{Topic.LoopValue}
+ activity: x{Local.Count} - {Local.LoopIndex}:{Local.LoopValue}
- kind: EndConversation
id: end_all
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/LoopContinue.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/LoopContinue.yaml
index d9cc78fc93..d45892348d 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/LoopContinue.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/LoopContinue.yaml
@@ -7,24 +7,24 @@ trigger:
actions:
- kind: SetVariable
id: setVariable_count
- variable: Topic.Count
+ variable: Local.Count
value: =0
- kind: Foreach
id: foreach_loop
items: =["a", "b", "c", "d", "e", "f"]
- index: Topic.LoopIndex
- value: Topic.LoopValue
+ index: Local.LoopIndex
+ value: Local.LoopValue
actions:
- kind: ContinueLoop
id: continueLoop_now
- kind: SetVariable
id: setVariable_loop
- variable: Topic.Count
- value: =Topic.Count + 1
+ variable: Local.Count
+ value: =Local.Count + 1
- kind: SendActivity
id: sendActivity_loop
- activity: x{Topic.Count} - {Topic.LoopIndex}:{Topic.LoopValue}
+ activity: x{Local.Count} - {Local.LoopIndex}:{Local.LoopValue}
- kind: EndConversation
id: end_all
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/LoopEach.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/LoopEach.yaml
index 7b3d90ad92..2dacc8eced 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/LoopEach.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/LoopEach.yaml
@@ -7,22 +7,22 @@ trigger:
actions:
- kind: SetVariable
id: setVariable_count
- variable: Topic.Count
+ variable: Local.Count
value: =0
- kind: Foreach
id: foreach_loop
items: =["a", "b", "c", "d", "e", "f"]
- index: Topic.LoopIndex
- value: Topic.LoopValue
+ index: Local.LoopIndex
+ value: Local.LoopValue
actions:
- kind: SetVariable
id: setVariable_loop
- variable: Topic.Count
- value: =Topic.Count + 1
+ variable: Local.Count
+ value: =Local.Count + 1
- kind: SendActivity
id: sendActivity_loop
- activity: x{Topic.Count} - {Topic.LoopIndex}:{Topic.LoopValue}
+ activity: x{Local.Count} - {Local.LoopIndex}:{Local.LoopValue}
- kind: EndConversation
id: end_all
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/MixedScopes.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/MixedScopes.yaml
new file mode 100644
index 0000000000..a97851a637
--- /dev/null
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/MixedScopes.yaml
@@ -0,0 +1,16 @@
+kind: Workflow
+trigger:
+
+ kind: OnConversationStart
+ id: my_workflow
+ actions:
+
+ - kind: SetVariable
+ id: set_input
+ variable: Topic.TestValue
+ value: =System.LastMessageText
+
+ - kind: SendActivity
+ id: activity_input
+ activity: |-
+ Input: "{Local.TestValue}"
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/ParseValue.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/ParseValue.yaml
index 3a346fd4d9..89edf9a0bd 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/ParseValue.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/ParseValue.yaml
@@ -7,6 +7,6 @@ trigger:
actions:
- kind: ParseValue
id: parse_var
- variable: Topic.MyVar
+ variable: Local.MyVar
value: "42"
valueType: Number
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/ResetVariable.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/ResetVariable.yaml
index c28d2f11f7..812b3619a0 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/ResetVariable.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/ResetVariable.yaml
@@ -7,9 +7,9 @@ trigger:
- kind: SetVariable
id: set_var
- variable: Topic.MyVar
+ variable: Local.MyVar
value: 42
- kind: ResetVariable
id: clear_var
- variable: Topic.MyVar
+ variable: Local.MyVar
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/SendActivity.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/SendActivity.yaml
index a334e85204..f7db5d2180 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/SendActivity.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/SendActivity.yaml
@@ -7,10 +7,10 @@ trigger:
- kind: SetVariable
id: set_input
- variable: Topic.TestValue
+ variable: Local.TestValue
value: =System.LastMessageText
- kind: SendActivity
id: activity_input
activity: |-
- Input: {Topic.TestValue}
+ Input: "{Local.TestValue}"
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/SetTextVariable.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/SetTextVariable.yaml
index 103747e7e0..3ec10277e2 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/SetTextVariable.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/SetTextVariable.yaml
@@ -7,5 +7,5 @@ trigger:
- kind: SetTextVariable
id: set_text
- variable: Topic.TestVar
+ variable: Local.TestVar
value: Test content
diff --git a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/SetVariable.yaml b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/SetVariable.yaml
index 6827830b0e..de61276b6e 100644
--- a/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/SetVariable.yaml
+++ b/dotnet/tests/Microsoft.Agents.Workflows.Declarative.UnitTests/Workflows/SetVariable.yaml
@@ -7,5 +7,5 @@ trigger:
- kind: SetVariable
id: set_var
- variable: Topic.TestVar
+ variable: Local.TestVar
value: =3
diff --git a/workflow-samples/DeepResearch.yaml b/workflow-samples/DeepResearch.yaml
index 6b61534eac..6b258d32b1 100644
--- a/workflow-samples/DeepResearch.yaml
+++ b/workflow-samples/DeepResearch.yaml
@@ -39,7 +39,7 @@ trigger:
- kind: SetVariable
id: setVariable_aASlmF
displayName: List all available agents for this orchestrator
- variable: Topic.AvailableAgents
+ variable: Local.AvailableAgents
value: |-
=[
{
@@ -62,20 +62,20 @@ trigger:
- kind: SetVariable
id: setVariable_V6yEbo
displayName: Get a summary of all the agents for use in prompts
- variable: Topic.TeamDescription
- value: "=Concat(ForAll(Topic.AvailableAgents, $\"- \" & name & $\": \" & description), Value, \"\n\")"
+ variable: Local.TeamDescription
+ value: "=Concat(ForAll(Local.AvailableAgents, $\"- \" & name & $\": \" & description), Value, \"\n\")"
- kind: SetVariable
id: setVariable_NZ2u0l
displayName: Set Task
- variable: Topic.InputTask
+ variable: Local.InputTask
value: =System.LastMessage.Text
- kind: SetVariable
id: setVariable_10u2ZN
displayName: Set Task
- variable: Topic.SeedTask
- value: =Topic.InputTask
+ variable: Local.SeedTask
+ value: =Local.InputTask
- kind: SendActivity
id: sendActivity_yFsbRy
@@ -83,18 +83,18 @@ trigger:
- kind: CreateConversation
id: conversation_1a2b3c
- conversationId: Topic.InternalConversationId
+ conversationId: Local.InternalConversationId
- kind: InvokeAzureAgent
id: question_UDoMUw
displayName: Get Facts
- conversationId: =Topic.InternalConversationId
+ conversationId: =Local.InternalConversationId
agent:
name: =Env.FOUNDRY_AGENT_RESEARCHANALYST
output:
- messages: Topic.TaskFacts
+ messages: Local.TaskFacts
input:
- messages: =[UserMessage(Topic.InputTask)]
+ messages: =[UserMessage(Local.InputTask)]
additionalInstructions: |-
In order to help begin addressing the user request, please answer the following pre-survey to the best of your ability.
Keep in mind that you are Ken Jennings-level with trivia, and Mensa-level with puzzles, so there should be a deep well to draw from.
@@ -122,19 +122,19 @@ trigger:
- kind: InvokeAzureAgent
id: question_DsBaJU
displayName: Create a Plan
- conversationId: =Topic.InternalConversationId
+ conversationId: =Local.InternalConversationId
agent:
name: =Env.FOUNDRY_AGENT_RESEARCHMANAGER
output:
- messages: Topic.Plan
+ messages: Local.Plan
input:
- messages: =[UserMessage(Topic.InputTask)]
+ messages: =[UserMessage(Local.InputTask)]
additionalInstructions: |-
Your only job is to devise an efficient plan that identifies (by name) how a team member may contribute to addressing the user request.
Only select the following team which is listed as "- [Name]: [Description]"
- {Topic.TeamDescription}
+ {Local.TeamDescription}
The plan must be a bullet point list must be in the form "- [AgentName]: [Specific action or task for that agent to perform]"
@@ -143,60 +143,60 @@ trigger:
- kind: SetVariable
id: setVariable_Kk2LDL
displayName: Define instructions
- variable: Topic.TaskInstructions
+ variable: Local.TaskInstructions
value: |-
="# TASK
Address the following user request:
- " & Topic.InputTask & "
+ " & Local.InputTask & "
# TEAM
Use the following team to answer this request:
- " & Topic.TeamDescription & "
+ " & Local.TeamDescription & "
# FACTS
Consider this initial fact sheet:
- " & Trim(Topic.TaskFacts.Text) & "
+ " & Trim(Local.TaskFacts.Text) & "
# PLAN
Here is the plan to follow as best as possible:
- " & Topic.Plan.Text
+ " & Local.Plan.Text
- kind: SendActivity
id: sendActivity_bwNZiM
- activity: {Topic.TaskInstructions}
+ activity: {Local.TaskInstructions}
- kind: InvokeAzureAgent
id: question_o3BQkf
displayName: Progress Ledger Prompt
- conversationId: =Topic.InternalConversationId
+ conversationId: =Local.InternalConversationId
agent:
name: =Env.FOUNDRY_AGENT_RESEARCHMANAGER
output:
- messages: Topic.ProgressLedgerUpdate
+ messages: Local.ProgressLedgerUpdate
input:
- messages: =[UserMessage(Topic.AgentResponseText)]
+ messages: =[UserMessage(Local.AgentResponseText)]
additionalInstructions: |-
Recall we are working on the following request:
- {Topic.InputTask}
+ {Local.InputTask}
And we have assembled the following team:
- {Topic.TeamDescription}
+ {Local.TeamDescription}
To make progress on the request, please answer the following questions, including necessary reasoning:
- Is the request fully satisfied? (True if complete, or False if the original request has yet to be SUCCESSFULLY and FULLY addressed)
- Are we in a loop where we are repeating the same requests and / or getting the same responses from an agent multiple times? Loops can span multiple turns, and can include repeated actions like scrolling up or down more than a handful of times.
- Are we making forward progress? (True if just starting, or recent messages are adding value. False if recent messages show evidence of being stuck in a loop or if there is evidence of significant barriers to success such as the inability to read from a required file)
- - Who should speak next? (select from: {Concat(Topic.AvailableAgents, name, ",")})
+ - Who should speak next? (select from: {Concat(Local.AvailableAgents, name, ",")})
- What instruction or question would you give this team member? (Phrase as if speaking directly to them, and include any specific information they may need)
Please output an answer in pure JSON format according to the following schema. The JSON object must be parsable as-is. DO NOT OUTPUT ANYTHING OTHER THAN JSON, AND DO NOT DEVIATE FROM THIS SCHEMA:
@@ -216,7 +216,7 @@ trigger:
}},
"next_speaker": {{
"reason": string,
- "answer": string (select from: {Concat(Topic.AvailableAgents, name, ",")})
+ "answer": string (select from: {Concat(Local.AvailableAgents, name, ",")})
}},
"instruction_or_question": {{
"reason": string,
@@ -227,8 +227,8 @@ trigger:
- kind: ParseValue
id: parse_rNZtlV
displayName: Parse ledger response
- variable: Topic.TypedProgressLedger
- value: =Topic.ProgressLedgerUpdate.Text
+ variable: Local.TypedProgressLedger
+ value: =Local.ProgressLedgerUpdate.Text
valueType:
kind: Record
properties:
@@ -271,13 +271,13 @@ trigger:
id: conditionGroup_mVIecC
conditions:
- id: conditionItem_fj432c
- condition: =Topic.TypedProgressLedger.is_request_satisfied.answer
+ condition: =Local.TypedProgressLedger.is_request_satisfied.answer
displayName: If Done
actions:
- kind: SendActivity
id: sendActivity_kdl3mC
- activity: Completed! {Topic.TypedProgressLedger.is_request_satisfied.reason}
+ activity: Completed! {Local.TypedProgressLedger.is_request_satisfied.reason}
- kind: InvokeAzureAgent
id: question_Ke3l1d
@@ -286,9 +286,9 @@ trigger:
agent:
name: =Env.FOUNDRY_AGENT_RESEARCHMANAGER
output:
- messages: Topic.FinalResponse
+ messages: Local.FinalResponse
input:
- messages: =[UserMessage(Topic.SeedTask)]
+ messages: =[UserMessage(Local.SeedTask)]
additionalInstructions: |-
We have completed the task.
Based only on the conversation and without adding any new information, synthesize the result of the conversation as a complete response to the user task.
@@ -298,15 +298,15 @@ trigger:
id: end_SVoNSV
- id: conditionItem_yiqund
- condition: =Topic.TypedProgressLedger.is_in_loop.answer || Not(Topic.TypedProgressLedger.is_progress_being_made.answer)
+ condition: =Local.TypedProgressLedger.is_in_loop.answer || Not(Local.TypedProgressLedger.is_progress_being_made.answer)
displayName: If Stalling
actions:
- kind: SetVariable
id: setVariable_H5lXdD
displayName: Increase stall count
- variable: Topic.StallCount
- value: =Topic.StallCount + 1
+ variable: Local.StallCount
+ value: =Local.StallCount + 1
- kind: ConditionGroup
@@ -319,22 +319,22 @@ trigger:
actions:
- kind: SendActivity
id: sendActivity_fpaNL9
- activity: {Topic.TypedProgressLedger.is_in_loop.reason}
+ activity: {Local.TypedProgressLedger.is_in_loop.reason}
- id: conditionItem_NnqvXh
- condition: =Not(Topic.TypedProgressLedger.is_progress_being_made.answer)
+ condition: =Not(Local.TypedProgressLedger.is_progress_being_made.answer)
displayName: Is No Progress
actions:
- kind: SendActivity
id: sendActivity_NnqvXh
- activity: {Topic.TypedProgressLedger.is_progress_being_made.reason}
+ activity: {Local.TypedProgressLedger.is_progress_being_made.reason}
- kind: ConditionGroup
id: conditionGroup_xzNrdM
conditions:
- id: conditionItem_NlQTBv
- condition: =Topic.StallCount > 2
+ condition: =Local.StallCount > 2
displayName: Stall Count Exceeded
actions:
@@ -346,11 +346,11 @@ trigger:
id: conditionGroup_4s1Z27
conditions:
- id: conditionItem_EXAlhZ
- condition: =Topic.RestartCount > 2
+ condition: =Local.RestartCount > 2
actions:
- kind: SendActivity
id: sendActivity_xKxFUU
- activity: Stopping after attempting {Topic.RestartCount} restarts...
+ activity: Stopping after attempting {Local.RestartCount} restarts...
- kind: EndConversation
id: end_GHVrFh
@@ -362,18 +362,18 @@ trigger:
- kind: InvokeAzureAgent
id: question_wFJ123
displayName: Get New Facts Prompt
- conversationId: =Topic.InternalConversationId
+ conversationId: =Local.InternalConversationId
agent:
name: =Env.FOUNDRY_AGENT_RESEARCHANALYST
output:
- messages: Topic.TaskFacts
+ messages: Local.TaskFacts
input:
messages: |-
=[
UserMessage(
"As a reminder, we are working to solve the following task:
- " & Topic.InputTask)
+ " & Local.InputTask)
]
additionalInstructions: |-
It's clear we aren't making as much progress as we would like, but we may have learned something new.
@@ -384,7 +384,7 @@ trigger:
Here is the old fact sheet:
- {Topic.TaskFacts}
+ {Local.TaskFacts}
- kind: SendActivity
id: sendActivity_dsBaJU
@@ -393,11 +393,11 @@ trigger:
- kind: InvokeAzureAgent
id: question_uEJ456
displayName: Create new Plan Prompt
- conversationId: =Topic.InternalConversationId
+ conversationId: =Local.InternalConversationId
agent:
name: =Env.FOUNDRY_AGENT_RESEARCHMANAGER
output:
- messages: Topic.Plan
+ messages: Local.Plan
input:
additionalInstructions: |-
Please briefly explain what went wrong on this last run (the root cause of the failure),
@@ -405,47 +405,47 @@ trigger:
As before, the new plan should be concise, be expressed in bullet-point form, and consider the following team composition
(do not involve any other outside people since we cannot contact anyone else):
- {Topic.TeamDescription}
+ {Local.TeamDescription}
- kind: SetVariable
id: setVariable_jW7tmM
displayName: Set Plan as Context
- variable: Topic.TaskInstructions
+ variable: Local.TaskInstructions
value: |-
="# TASK
Address the following user request:
- " & Topic.InputTask & "
+ " & Local.InputTask & "
# TEAM
Use the following team to answer this request:
- " & Topic.TeamDescription & "
+ " & Local.TeamDescription & "
# FACTS
Consider this initial fact sheet:
- " & Topic.TaskFacts.Text & "
+ " & Local.TaskFacts.Text & "
# PLAN
Here is the plan to follow as best as possible:
- " & Topic.Plan.Text
+ " & Local.Plan.Text
- kind: SetVariable
id: setVariable_6J2snP
displayName: Reset Stall count
- variable: Topic.StallCount
+ variable: Local.StallCount
value: 0
- kind: SetVariable
id: setVariable_S6HCgh
displayName: Increase Restart count
- variable: Topic.RestartCount
- value: =Topic.RestartCount + 1
+ variable: Local.RestartCount
+ value: =Local.RestartCount + 1
- kind: GotoAction
id: goto_LzfJ8u
@@ -455,25 +455,25 @@ trigger:
- kind: SendActivity
id: sendActivity_L7ooQO
activity: |-
- ({Topic.TypedProgressLedger.next_speaker.reason})
+ ({Local.TypedProgressLedger.next_speaker.reason})
- {Topic.TypedProgressLedger.next_speaker.answer} - {Topic.TypedProgressLedger.instruction_or_question.answer}
+ {Local.TypedProgressLedger.next_speaker.answer} - {Local.TypedProgressLedger.instruction_or_question.answer}
- kind: SetVariable
id: setVariable_L7ooQO
- variable: Topic.StallCount
+ variable: Local.StallCount
value: 0
- kind: SetVariable
id: setVariable_nxN1mE
- variable: Topic.NextSpeaker
- value: =Search(Topic.AvailableAgents, Topic.TypedProgressLedger.next_speaker.answer, name)
+ variable: Local.NextSpeaker
+ value: =Search(Local.AvailableAgents, Local.TypedProgressLedger.next_speaker.answer, name)
- kind: ConditionGroup
id: conditionGroup_QFPiF5
conditions:
- id: conditionItem_GmigcU
- condition: =CountRows(Topic.NextSpeaker) = 1
+ condition: =CountRows(Local.NextSpeaker) = 1
displayName: If next Agent tool Exists
actions:
@@ -482,23 +482,23 @@ trigger:
displayName: Progress Ledger Prompt
conversationId: =System.ConversationId
agent:
- name: =First(Topic.NextSpeaker).agentid
+ name: =First(Local.NextSpeaker).agentid
output:
- messages: Topic.AgentResponse
+ messages: Local.AgentResponse
input:
- messages: =[UserMessage(Topic.SeedTask)]
+ messages: =[UserMessage(Local.SeedTask)]
additionalInstructions: |-
- {Topic.TypedProgressLedger.instruction_or_question.answer}
+ {Local.TypedProgressLedger.instruction_or_question.answer}
- kind: SetVariable
id: setVariable_XzNrdM
- variable: Topic.AgentResponseText
- value: =Topic.AgentResponse.Text
+ variable: Local.AgentResponseText
+ value: =Local.AgentResponse.Text
- kind: ResetVariable
id: setVariable_8eIx2A
displayName: Clear seed task
- variable: Topic.SeedTask
+ variable: Local.SeedTask
elseActions:
- kind: SendActivity
@@ -508,8 +508,8 @@ trigger:
- kind: SetVariable
id: setVariable_BhcsI7
displayName: Increase stall count
- variable: Topic.StallCount
- value: =Topic.StallCount + 1
+ variable: Local.StallCount
+ value: =Local.StallCount + 1
- kind: GotoAction
id: goto_76Hne8
diff --git a/workflow-samples/HumanInLoop.yaml b/workflow-samples/HumanInLoop.yaml
index 461e2b9c56..18959b067d 100644
--- a/workflow-samples/HumanInLoop.yaml
+++ b/workflow-samples/HumanInLoop.yaml
@@ -14,14 +14,14 @@ trigger:
# Capture original input
- kind: SetVariable
id: set_project
- variable: Topic.OriginalInput
+ variable: Local.OriginalInput
value: =System.LastMessage.Text
# Request input from user
- kind: Question
id: question_confirm
alwaysPrompt: false
- property: Topic.ConfirmedInput
+ property: Local.ConfirmedInput
prompt:
kind: Message
text:
@@ -35,14 +35,14 @@ trigger:
conditions:
# Didn't match
- - condition: =Topic.OriginalInput <> Topic.ConfirmedInput
+ - condition: =Local.OriginalInput <> Local.ConfirmedInput
id: check_confirm
actions:
- kind: SendActivity
id: sendActivity_mismatch
activity: |-
- "{Topic.ConfirmedInput}" does not match the original input of "{Topic.OriginalInput}". Please try again.
+ "{Local.ConfirmedInput}" does not match the original input of "{Local.OriginalInput}". Please try again.
- kind: GotoAction
id: goto_again
@@ -54,10 +54,10 @@ trigger:
id: sendActivity_confirmed
activity: |-
You entered:
- {Topic.OriginalInput}
+ {Local.OriginalInput}
Confirmed input:
- {Topic.ConfirmedInput}
+ {Local.ConfirmedInput}
diff --git a/workflow-samples/MathChat.yaml b/workflow-samples/MathChat.yaml
index 668e0bfb4b..7d2ff07cf5 100644
--- a/workflow-samples/MathChat.yaml
+++ b/workflow-samples/MathChat.yaml
@@ -33,7 +33,7 @@ trigger:
- kind: SetVariable
id: set_project
- variable: Topic.Project
+ variable: Local.Project
value: =System.LastMessage.Text
- kind: InvokeAzureAgent
@@ -42,11 +42,11 @@ trigger:
agent:
name: =Env.FOUNDRY_AGENT_STUDENT
input:
- messages: =[UserMessage(Topic.Project)]
+ messages: =[UserMessage(Local.Project)]
- kind: ResetVariable
id: reset_project
- variable: Topic.Project
+ variable: Local.Project
- kind: InvokeAzureAgent
id: question_teacher
@@ -54,18 +54,18 @@ trigger:
agent:
name: =Env.FOUNDRY_AGENT_TEACHER
output:
- messages: Topic.TeacherResponse
+ messages: Local.TeacherResponse
- kind: SetVariable
id: set_count_increment
- variable: Topic.TurnCount
- value: =Topic.TurnCount + 1
+ variable: Local.TurnCount
+ value: =Local.TurnCount + 1
- kind: ConditionGroup
id: check_completion
conditions:
- - condition: =!IsBlank(Find("CONGRATULATIONS", Upper(Topic.TeacherResponse.Text)))
+ - condition: =!IsBlank(Find("CONGRATULATIONS", Upper(Local.TeacherResponse.Text)))
id: check_turn_done
actions:
@@ -73,7 +73,7 @@ trigger:
id: sendActivity_done
activity: GOLD STAR!
- - condition: =Topic.TurnCount < 4
+ - condition: =Local.TurnCount < 4
id: check_turn_count
actions: