Skip to content

Commit 0086d38

Browse files
.NET: [BREAKING] Workflows API Review Naming Changes (Part 1?) (#4090)
* refactor: Normalize Run/RunStreaming with AIAgent * refactor: Clarify Session vs. Run -level concepts * Rename RunId to SessionId to better match Run/Session terminology in AIAgent * [BREAKING]: Will break existing checkpointed sessions in CosmosDb due to field rename * refactor: Rename and simplify interface around getting typed data out of ExternalRequest/Response * Also adds hints around using value types in PortableValue * refactor: Rename AddFanInEdge to AddFanInBarrierEdge This will prevent a breaking change later when we introduce a programmable FanIn edge, analogous to the FanOut edge's EdgeSelector. The goal, in the long run is to support a number of different FanIn scenarios, with naive FanIn (no barrier) by default, similar to FanOut. * refactor: AsAgent(this Workflow, ...) => AsAIAgent(...) * misc - part1: SwitchBuilder internal --------- Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
1 parent 5fd260e commit 0086d38

File tree

93 files changed

+397
-458
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+397
-458
lines changed

dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ Once the user has deduced what type (knight or knave) both Alice and Bob are, te
7070
If the user asks a general question about their surrounding, make something up which is consistent with the scenario.
7171
""", "Narrator");
7272

73-
return AgentWorkflowBuilder.BuildConcurrent([knight, knave, narrator]).AsAgent(name: key);
73+
return AgentWorkflowBuilder.BuildConcurrent([knight, knave, narrator]).AsAIAgent(name: key);
7474
});
7575

7676
// Workflow consisting of multiple specialized agents

dotnet/samples/GettingStarted/Workflows/Agents/CustomAgentExecutors/Program.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,7 @@ private static async Task Main()
3434
// Set up the Azure OpenAI client
3535
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
3636
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
37-
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
38-
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
39-
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
40-
var chatClient = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential()).GetChatClient(deploymentName).AsIChatClient();
37+
var chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient();
4138

4239
// Create the executors
4340
var sloganWriter = new SloganWriterExecutor("SloganWriter", chatClient);
@@ -51,7 +48,7 @@ private static async Task Main()
5148
.Build();
5249

5350
// Execute the workflow
54-
await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, input: "Create a slogan for a new electric SUV that is affordable and fun to drive.");
51+
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, input: "Create a slogan for a new electric SUV that is affordable and fun to drive.");
5552
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
5653
{
5754
if (evt is SloganGeneratedEvent or FeedbackEvent)

dotnet/samples/GettingStarted/Workflows/Agents/FoundryAgent/Program.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ private static async Task Main()
2424
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT")
2525
?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
2626
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
27-
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
28-
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
29-
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
30-
var persistentAgentsClient = new PersistentAgentsClient(endpoint, new DefaultAzureCredential());
27+
var persistentAgentsClient = new PersistentAgentsClient(endpoint, new AzureCliCredential());
3128

3229
// Create agents
3330
AIAgent frenchAgent = await GetTranslationAgentAsync("French", persistentAgentsClient, deploymentName);
@@ -41,7 +38,7 @@ private static async Task Main()
4138
.Build();
4239

4340
// Execute the workflow
44-
await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, new ChatMessage(ChatRole.User, "Hello World!"));
41+
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, new ChatMessage(ChatRole.User, "Hello World!"));
4542
// Must send the turn token to trigger the agents.
4643
// The agents are wrapped as executors. When they receive messages,
4744
// they will cache the messages and only start processing when they receive a TurnToken.

dotnet/samples/GettingStarted/Workflows/Agents/GroupChatToolApproval/Program.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ private static async Task Main()
9191

9292
List<ChatMessage> messages = [new(ChatRole.User, "We need to deploy version 2.4.0 to production. Please coordinate the deployment.")];
9393

94-
await using StreamingRun run = await InProcessExecution.Lockstep.StreamAsync(workflow, messages);
94+
await using StreamingRun run = await InProcessExecution.Lockstep.RunStreamingAsync(workflow, messages);
9595
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
9696

9797
string? lastExecutorId = null;
@@ -101,7 +101,7 @@ private static async Task Main()
101101
{
102102
case RequestInfoEvent e:
103103
{
104-
if (e.Request.DataIs(out FunctionApprovalRequestContent? approvalRequestContent))
104+
if (e.Request.TryGetDataAs(out FunctionApprovalRequestContent? approvalRequestContent))
105105
{
106106
Console.WriteLine();
107107
Console.WriteLine($"[APPROVAL REQUIRED] From agent: {e.Request.PortInfo.PortId}");

dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/Program.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,11 @@ private static async Task Main()
3232
// Set up the Azure OpenAI client
3333
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
3434
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
35-
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
36-
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
37-
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
38-
var chatClient = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential()).GetChatClient(deploymentName).AsIChatClient();
35+
var chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient();
3936

4037
// Create the workflow and turn it into an agent
4138
var workflow = WorkflowFactory.BuildWorkflow(chatClient);
42-
var agent = workflow.AsAgent("workflow-agent", "Workflow Agent");
39+
var agent = workflow.AsAIAgent("workflow-agent", "Workflow Agent");
4340
var session = await agent.CreateSessionAsync();
4441

4542
// Start an interactive loop to interact with the workflow as if it were an agent

dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ internal static Workflow BuildWorkflow(IChatClient chatClient)
2424
// Build the workflow by adding executors and connecting them
2525
return new WorkflowBuilder(startExecutor)
2626
.AddFanOutEdge(startExecutor, [frenchAgent, englishAgent])
27-
.AddFanInEdge([frenchAgent, englishAgent], aggregationExecutor)
27+
.AddFanInBarrierEdge([frenchAgent, englishAgent], aggregationExecutor)
2828
.WithOutputFrom(aggregationExecutor)
2929
.Build();
3030
}

dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/Program.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ private static async Task Main()
3333

3434
// Execute the workflow and save checkpoints
3535
await using StreamingRun checkpointedRun = await InProcessExecution
36-
.StreamAsync(workflow, NumberSignal.Init, checkpointManager);
36+
.RunStreamingAsync(workflow, NumberSignal.Init, checkpointManager);
3737

3838
await foreach (WorkflowEvent evt in checkpointedRun.WatchStreamAsync())
3939
{
@@ -73,7 +73,7 @@ private static async Task Main()
7373
CheckpointInfo savedCheckpoint = checkpoints[CheckpointIndex];
7474

7575
await using StreamingRun newCheckpointedRun =
76-
await InProcessExecution.ResumeStreamAsync(newWorkflow, savedCheckpoint, checkpointManager);
76+
await InProcessExecution.ResumeStreamingAsync(newWorkflow, savedCheckpoint, checkpointManager);
7777

7878
await foreach (WorkflowEvent evt in newCheckpointedRun.WatchStreamAsync())
7979
{

dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/Program.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ private static async Task Main()
3131
var checkpoints = new List<CheckpointInfo>();
3232

3333
// Execute the workflow and save checkpoints
34-
await using StreamingRun checkpointedRun = await InProcessExecution
35-
.StreamAsync(workflow, NumberSignal.Init, checkpointManager)
36-
;
34+
await using StreamingRun checkpointedRun = await InProcessExecution.RunStreamingAsync(workflow, NumberSignal.Init, checkpointManager);
3735
await foreach (WorkflowEvent evt in checkpointedRun.WatchStreamAsync())
3836
{
3937
if (evt is ExecutorCompletedEvent executorCompletedEvt)

dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/Program.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ private static async Task Main()
3535

3636
// Execute the workflow and save checkpoints
3737
await using StreamingRun checkpointedRun = await InProcessExecution
38-
.StreamAsync(workflow, new SignalWithNumber(NumberSignal.Init), checkpointManager)
38+
.RunStreamingAsync(workflow, new SignalWithNumber(NumberSignal.Init), checkpointManager)
3939
;
4040
await foreach (WorkflowEvent evt in checkpointedRun.WatchStreamAsync())
4141
{
@@ -98,8 +98,7 @@ private static async Task Main()
9898

9999
private static ExternalResponse HandleExternalRequest(ExternalRequest request)
100100
{
101-
var signal = request.DataAs<SignalWithNumber>();
102-
if (signal is not null)
101+
if (request.TryGetDataAs<SignalWithNumber>(out var signal))
103102
{
104103
switch (signal.Signal)
105104
{

dotnet/samples/GettingStarted/Workflows/Concurrent/Concurrent/Program.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,7 @@ private static async Task Main()
3434
// Set up the Azure OpenAI client
3535
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
3636
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
37-
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
38-
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
39-
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
40-
var chatClient = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential()).GetChatClient(deploymentName).AsIChatClient();
37+
var chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient();
4138

4239
// Create the executors
4340
ChatClientAgent physicist = new(
@@ -56,12 +53,12 @@ private static async Task Main()
5653
// Build the workflow by adding executors and connecting them
5754
var workflow = new WorkflowBuilder(startExecutor)
5855
.AddFanOutEdge(startExecutor, [physicist, chemist])
59-
.AddFanInEdge([physicist, chemist], aggregationExecutor)
56+
.AddFanInBarrierEdge([physicist, chemist], aggregationExecutor)
6057
.WithOutputFrom(aggregationExecutor)
6158
.Build();
6259

6360
// Execute the workflow in streaming mode
64-
await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, input: "What is temperature?");
61+
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, input: "What is temperature?");
6562
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
6663
{
6764
if (evt is WorkflowOutputEvent output)

0 commit comments

Comments
 (0)