Repository navigation
.NET: feat: adds the executorId as an additional property when running the workflow as agent in dotnet #7934
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
2022e83
5366f35
50606c7
5b418c4
a96df63
f975eab
edf6435
70b38a4
acffd27
3421ab8
638bc8a
8c0beae
5e871d3
c61d196
6df5254
48161c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| #nullable enable | ||
| Microsoft.Agents.AI.Workflows.Executor.RegisterCheckpointRestoringCallback(object! sharedStateKey, System.Func<Microsoft.Agents.AI.Workflows.IWorkflowContext!, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask>! callback) -> void | ||
| Microsoft.Agents.AI.Workflows.Executor.RegisterCheckpointRestoringCallback(System.Func<Microsoft.Agents.AI.Workflows.IWorkflowContext!, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask>! callback) -> void | ||
| const Microsoft.Agents.AI.Workflows.WorkflowAgentAdditionalProperties.ExecutorId = "executorId" -> string! | ||
| Microsoft.Agents.AI.Workflows.WorkflowAgentAdditionalProperties |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| #nullable enable | ||
| Microsoft.Agents.AI.Workflows.Executor.RegisterCheckpointRestoringCallback(object! sharedStateKey, System.Func<Microsoft.Agents.AI.Workflows.IWorkflowContext!, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask>! callback) -> void | ||
| Microsoft.Agents.AI.Workflows.Executor.RegisterCheckpointRestoringCallback(System.Func<Microsoft.Agents.AI.Workflows.IWorkflowContext!, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask>! callback) -> void | ||
| const Microsoft.Agents.AI.Workflows.WorkflowAgentAdditionalProperties.ExecutorId = "executorId" -> string! | ||
| Microsoft.Agents.AI.Workflows.WorkflowAgentAdditionalProperties |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| #nullable enable | ||
| Microsoft.Agents.AI.Workflows.Executor.RegisterCheckpointRestoringCallback(object! sharedStateKey, System.Func<Microsoft.Agents.AI.Workflows.IWorkflowContext!, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask>! callback) -> void | ||
| Microsoft.Agents.AI.Workflows.Executor.RegisterCheckpointRestoringCallback(System.Func<Microsoft.Agents.AI.Workflows.IWorkflowContext!, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask>! callback) -> void | ||
| const Microsoft.Agents.AI.Workflows.WorkflowAgentAdditionalProperties.ExecutorId = "executorId" -> string! | ||
| Microsoft.Agents.AI.Workflows.WorkflowAgentAdditionalProperties |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| #nullable enable | ||
| Microsoft.Agents.AI.Workflows.Executor.RegisterCheckpointRestoringCallback(object! sharedStateKey, System.Func<Microsoft.Agents.AI.Workflows.IWorkflowContext!, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask>! callback) -> void | ||
| Microsoft.Agents.AI.Workflows.Executor.RegisterCheckpointRestoringCallback(System.Func<Microsoft.Agents.AI.Workflows.IWorkflowContext!, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask>! callback) -> void | ||
| const Microsoft.Agents.AI.Workflows.WorkflowAgentAdditionalProperties.ExecutorId = "executorId" -> string! | ||
| Microsoft.Agents.AI.Workflows.WorkflowAgentAdditionalProperties |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| #nullable enable | ||
| Microsoft.Agents.AI.Workflows.Executor.RegisterCheckpointRestoringCallback(object! sharedStateKey, System.Func<Microsoft.Agents.AI.Workflows.IWorkflowContext!, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask>! callback) -> void | ||
| Microsoft.Agents.AI.Workflows.Executor.RegisterCheckpointRestoringCallback(System.Func<Microsoft.Agents.AI.Workflows.IWorkflowContext!, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask>! callback) -> void | ||
| const Microsoft.Agents.AI.Workflows.WorkflowAgentAdditionalProperties.ExecutorId = "executorId" -> string! | ||
| Microsoft.Agents.AI.Workflows.WorkflowAgentAdditionalProperties |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
|
|
||
| namespace Microsoft.Agents.AI.Workflows; | ||
|
|
||
| /// <summary> | ||
| /// Defines additional property keys used by workflow-hosted agents. | ||
| /// </summary> | ||
| public static class WorkflowAgentAdditionalProperties | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI: If we are unsure about something new that is public we often mark it as experimental, to make sure we can still make changes to it before graduating the feature. We then remove experimental once we are happy with the overall change.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks I think Tao Chen (@TaoChenOSU) and Peter Ibekwe (@peibekwe) will be able to inform the design here and whether or not we need to add those experimental aspects. |
||
| { | ||
| /// <summary> | ||
| /// The key for the workflow executor identifier that produced an agent response update. | ||
| /// </summary> | ||
| public const string ExecutorId = "executorId"; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -186,18 +186,28 @@ public AgentResponseUpdate CreateUpdate(string responseId, object raw, params AI | |
| }; | ||
| } | ||
|
|
||
| public AgentResponseUpdate CreateUpdate(string responseId, object raw, ChatMessage message) | ||
| public AgentResponseUpdate CreateUpdate(string responseId, object raw, ChatMessage message, string? executorId = default) | ||
| { | ||
| Throw.IfNull(message); | ||
|
|
||
| return new(message.Role, message.Contents) | ||
| return SetExecutorId(new(message.Role, message.Contents) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The behaviour pre-existed this change, Tao Chen (@TaoChenOSU) to confirm whether we should fix that or not |
||
| { | ||
| AuthorName = message.AuthorName, | ||
| CreatedAt = message.CreatedAt ?? DateTimeOffset.UtcNow, | ||
| MessageId = message.MessageId ?? Guid.NewGuid().ToString("N"), | ||
| ResponseId = responseId, | ||
| RawRepresentation = raw | ||
| }; | ||
| }, executorId); | ||
| } | ||
|
|
||
| private static AgentResponseUpdate SetExecutorId(AgentResponseUpdate update, string? executorId) | ||
|
baywet marked this conversation as resolved.
|
||
| { | ||
| if (!string.IsNullOrEmpty(executorId)) | ||
| { | ||
| update.AdditionalProperties ??= []; | ||
| update.AdditionalProperties[WorkflowAgentAdditionalProperties.ExecutorId] = executorId; | ||
| } | ||
| return update; | ||
| } | ||
|
|
||
| private async ValueTask<ResumeRunResult> CreateOrResumeRunAsync(List<ChatMessage> messages, CancellationToken cancellationToken = default) | ||
|
|
@@ -499,15 +509,15 @@ IAsyncEnumerable<AgentResponseUpdate> InvokeStageAsync( | |
| await run.TrySendMessageAsync(new TurnToken(emitEvents: true)).ConfigureAwait(false); | ||
| } | ||
|
|
||
| AgentResponseUpdate CreateObservabilityUpdate(WorkflowEvent evt) | ||
| => new(ChatRole.Assistant, []) | ||
| AgentResponseUpdate CreateObservabilityUpdate(WorkflowEvent evt, string? executorId = default) | ||
| => SetExecutorId(new(ChatRole.Assistant, []) | ||
| { | ||
| CreatedAt = DateTimeOffset.UtcNow, | ||
| MessageId = Guid.NewGuid().ToString("N"), | ||
| Role = ChatRole.Assistant, | ||
| ResponseId = this.LastResponseId, | ||
| RawRepresentation = evt | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe I'm wrong, but I would have thought that the raw representation would typically be some sort of WorkflowEvent, and if so, that users could get the executor id from that.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think I have enough context to reply to this comment. Why should it be a WorkflowEvent as opposed to an Executor Event? What parameters are you taking into consideration for this design suggestion?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't really know enough about this area either to know all the different raw representation types that might be represented here, but I think it's a good thing to verify before making the change. |
||
| }; | ||
| }, executorId); | ||
|
|
||
| await foreach (WorkflowEvent evt in run.WatchStreamAsync(blockOnPendingRequest: false, cancellationToken) | ||
| .ConfigureAwait(false) | ||
|
|
@@ -586,7 +596,7 @@ AgentResponseUpdate CreateObservabilityUpdate(WorkflowEvent evt) | |
| // the legacy default, keep today's behavior — gated by the include flag. | ||
| if (!Futures.EnableAgentResponseOutputTaggingAndFiltering && !this._includeWorkflowOutputsInResponse) | ||
| { | ||
| yield return CreateObservabilityUpdate(evt); | ||
| yield return CreateObservabilityUpdate(evt, agentResponse.ExecutorId); | ||
| break; | ||
| } | ||
|
|
||
|
|
@@ -610,13 +620,13 @@ AgentResponseUpdate CreateObservabilityUpdate(WorkflowEvent evt) | |
| } | ||
|
|
||
| emittedMessage = true; | ||
| yield return this.CreateUpdate(this.LastResponseId, evt, message); | ||
| yield return this.CreateUpdate(this.LastResponseId, evt, message, agentResponse.ExecutorId); | ||
| } | ||
| if (!emittedMessage && suppressedStreamedMessage) | ||
| { | ||
| // Preserve the completion event for observability after its correlated | ||
| // streamed content has already been forwarded. | ||
| yield return CreateObservabilityUpdate(evt); | ||
| yield return CreateObservabilityUpdate(evt, agentResponse.ExecutorId); | ||
| } | ||
| break; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.