mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.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
This commit is contained in:
@@ -90,9 +90,9 @@
|
||||
<!-- Identity -->
|
||||
<PackageVersion Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.77.0" />
|
||||
<!-- Workflows -->
|
||||
<PackageVersion Include="Microsoft.Bot.ObjectModel" Version="1.2025.922-1" />
|
||||
<PackageVersion Include="Microsoft.Bot.ObjectModel.Json" Version="1.2025.922-1" />
|
||||
<PackageVersion Include="Microsoft.Bot.ObjectModel.PowerFx" Version="1.2025.922-1" />
|
||||
<PackageVersion Include="Microsoft.Bot.ObjectModel" Version="1.2025.926-1" />
|
||||
<PackageVersion Include="Microsoft.Bot.ObjectModel.Json" Version="1.2025.926-1" />
|
||||
<PackageVersion Include="Microsoft.Bot.ObjectModel.PowerFx" Version="1.2025.926-1" />
|
||||
<PackageVersion Include="Microsoft.PowerFx.Interpreter" Version="1.4.0-build.20250821-1001" />
|
||||
<!-- Test -->
|
||||
<PackageVersion Include="FluentAssertions" Version="8.6.0" />
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Microsoft.Agents.Workflows.Declarative;
|
||||
public static class DeclarativeWorkflowBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds a process from the provided YAML definition of a CPS Topic ObjectModel.
|
||||
/// Builds a workflow from the provided YAML definition.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInput">The type of the input message</typeparam>
|
||||
/// <param name="workflowFile">The path to the workflow.</param>
|
||||
@@ -35,7 +35,7 @@ public static class DeclarativeWorkflowBuilder
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a process from the provided YAML definition of a CPS Topic ObjectModel.
|
||||
/// Builds a workflow from the provided YAML definition.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInput">The type of the input message</typeparam>
|
||||
/// <param name="yamlReader">The reader that provides the workflow object model YAML.</param>
|
||||
@@ -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,
|
||||
|
||||
+4
-4
@@ -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<TValue>(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<TValue>(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))
|
||||
|
||||
+1
@@ -16,6 +16,7 @@ internal sealed class DeclarativeWorkflowContext : IWorkflowContext
|
||||
{
|
||||
public static readonly FrozenSet<string> ManagedScopes =
|
||||
[
|
||||
VariableScopeNames.Local,
|
||||
VariableScopeNames.Topic,
|
||||
VariableScopeNames.Global,
|
||||
];
|
||||
|
||||
+9
-2
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
+1
@@ -37,6 +37,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="Microsoft.Agents.Workflows.Declarative.UnitTests" />
|
||||
<InternalsVisibleTo Include="Microsoft.Agents.Workflows.Declarative.IntegrationTests" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,11 @@ namespace Microsoft.Agents.Workflows.Declarative.PowerFx;
|
||||
/// </summary>
|
||||
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<string> 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,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
+2
-2
@@ -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()
|
||||
|
||||
+9
-9
@@ -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
|
||||
|
||||
+2
-2
@@ -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}
|
||||
|
||||
+2
-2
@@ -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}
|
||||
|
||||
+1
-1
@@ -12,4 +12,4 @@ trigger:
|
||||
input:
|
||||
messages: =[UserMessage(System.LastMessageText)]
|
||||
output:
|
||||
messages: Topic.Answer
|
||||
messages: Local.Answer
|
||||
|
||||
+2
-2
@@ -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}"
|
||||
|
||||
+9
-13
@@ -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<WorkflowAgentProvider> mockAgentProvider = new(MockBehavior.Strict);
|
||||
DeclarativeWorkflowOptions options = new(mockAgentProvider.Object);
|
||||
WorkflowActionVisitor visitor = new(new RootExecutor(), state, options);
|
||||
WorkflowActionVisitor visitor = new(new DeclarativeWorkflowExecutor<string>(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<MessageActivityEvent>(), 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<TInput>(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<RootExecutor>(WorkflowActionVisitor.Steps.Root("anything")),
|
||||
IMessageHandler<string>
|
||||
{
|
||||
public async ValueTask HandleAsync(string message, IWorkflowContext context) =>
|
||||
await context.SendMessageAsync($"{this.Id}: {DateTime.UtcNow:t}").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -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<BlankValue>(this.State.Get(variableName, scopeName));
|
||||
|
||||
protected static TAction AssignParent<TAction>(DialogAction.Builder actionBuilder) where TAction : DialogAction
|
||||
|
||||
+8
-8
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}";
|
||||
}
|
||||
|
||||
+3
-3
@@ -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
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+2
-2
@@ -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}
|
||||
|
||||
+2
-2
@@ -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}
|
||||
|
||||
+5
-1
@@ -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!
|
||||
+6
-6
@@ -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
|
||||
|
||||
+6
-6
@@ -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
|
||||
|
||||
+6
-6
@@ -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
|
||||
|
||||
+16
@@ -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}"
|
||||
+1
-1
@@ -7,6 +7,6 @@ trigger:
|
||||
actions:
|
||||
- kind: ParseValue
|
||||
id: parse_var
|
||||
variable: Topic.MyVar
|
||||
variable: Local.MyVar
|
||||
value: "42"
|
||||
valueType: Number
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
|
||||
+2
-2
@@ -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}"
|
||||
|
||||
+1
-1
@@ -7,5 +7,5 @@ trigger:
|
||||
|
||||
- kind: SetTextVariable
|
||||
id: set_text
|
||||
variable: Topic.TestVar
|
||||
variable: Local.TestVar
|
||||
value: Test content
|
||||
|
||||
+1
-1
@@ -7,5 +7,5 @@ trigger:
|
||||
|
||||
- kind: SetVariable
|
||||
id: set_var
|
||||
variable: Topic.TestVar
|
||||
variable: Local.TestVar
|
||||
value: =3
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user