mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
6b2ff3ed7acbc4e607f2481cff196c7aad429f25
135
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
07a1e83492 |
.NET: Forward Magentic participant replies to manager (#6156)
MagenticOrchestrator.TakeTurnAsync dropped the `messages` parameter on subsequent turns, so participant replies never reached the manager's ChatHistory. The manager kept re-dispatching the same speaker every round until MaxRounds. Append the incoming messages to taskContext.ChatHistory before running the coordination round (matches Python's _handle_response). Adds RecordingReplayAgent + regression test that asserts the worker's reply reaches round-2's progress-ledger call. Co-authored-by: Jacob Alber <jaalber@microsoft.com> |
||
|
|
1fccf16f11 | feat: Remove [Experimental] tag from .NET Orchestrations (#6164) | ||
|
|
8ed2159c4b |
.NET: Workflow Outputs Overhaul: Support Tagging, Filtering Agent Outputs (#6045)
* test: reshuffle .NET Workflow tests in preparation for Outputs overhaul Phase 1 of the .NET Workflows outputs overhaul (see working/implementation-plan.md). Pure moves/renames in dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests; no production code changes, no new test cases. The split keeps each orchestration mode in its own source file so the upcoming tag-aware and orchestration-default test additions land on clean diffs. Renames: * WorkflowBuilderSmokeTests.cs -> WorkflowBuilderTests.cs (with class rename to match). The scope is no longer "smoke"-only once subsequent phases add tag-aware builder tests. * InputWaiterAndOutputFilterTests.cs -> InputWaiterTests.cs + OutputFilterTests.cs. The file already declared the two test classes separately; this split simply gives each its own file so the output-filter cases have a dedicated home for tag-aware additions. Split of AgentWorkflowBuilderTests.cs: * AgentWorkflowBuilderTests.cs is now the outer `public static partial class AgentWorkflowBuilderTests` holding the shared test helpers (DoubleEchoAgent + session + WithBarrier variant, WorkflowRunResult, RunWorkflow* methods) bumped from `private` to `internal` so the new top-level GroupChatWorkflowBuilderTests in the same assembly can reach them. * AgentWorkflowBuilder.SequentialTests.cs (nested SequentialTests): BuildSequential_InvalidArguments_Throws, BuildSequential_AgentsRunInOrderAsync. * AgentWorkflowBuilder.ConcurrentTests.cs (nested ConcurrentTests): BuildConcurrent_InvalidArguments_Throws, BuildConcurrent_AgentsRunInParallelAsync. Sequential and Concurrent are kept as nested classes because they're modes of the same `AgentWorkflowBuilder` static factory and do not produce dedicated builder types. New file: * GroupChatWorkflowBuilderTests.cs (top-level): the existing BuildGroupChat_* and GroupChatManager_* cases moved out of the old AgentWorkflowBuilderTests file. They exercise the `GroupChatWorkflowBuilder` type (returned by `AgentWorkflowBuilder.CreateGroupChatBuilderWith`), so a dedicated top-level test class - matching the convention reserved by the plan for HandoffWorkflowBuilderTests / MagenticWorkflowBuilderTests - is the right home. Cross-class helper references qualify with `AgentWorkflowBuilderTests.DoubleEchoAgent` and `AgentWorkflowBuilderTests.RunWorkflowAsync`. The outer partial class is `static` (and nested classes carry the instance test methods) because the outer holds only static helpers; this satisfies CA1052 without suppressions and is invisible to xUnit discovery, which finds tests on the nested classes as `AgentWorkflowBuilderTests.SequentialTests.*` etc. Validation: `dotnet build` clean on both target frameworks; all 547 tests in Microsoft.Agents.AI.Workflows.UnitTests pass on net10.0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: introduce OutputTag, Futures, and tag-aware WorkflowBuilder API Phase 2 of the .NET Workflows outputs overhaul. Additive code change only - no observable runtime behavior change. The runner still uses the legacy bypass for AgentResponse / AgentResponseUpdate payloads, and the new `Futures.EnableAgentResponseOutputTaggingAndFiltering` flag defaults to false. Phase 3 will wire the flag into the runner; this commit only introduces the types and the builder API. New public surface: * `OutputTag` (readonly struct): wraps a string Value with ordinal equality (IEquatable, GetHashCode, == / !=) so it can participate as a HashSet element. Internal ctor closes the set. One public singleton: `OutputTag.Intermediate`. Terminal / regular outputs carry no tag (empty Tags set). JSON-serialized as a bare string via [JsonConverter(typeof(OutputTagJsonConverter))], with the converter rehydrating to the well-known singleton on read. * `Futures` (static class): hosts opt-in pre-GA behavior switches. First flag is `EnableAgentResponseOutputTaggingAndFiltering`; XML doc captures the v2.0.0 obsoletion / v3.0.0 removal lifecycle. * `WorkflowOutputEvent.Tags`: `HashSet<OutputTag>` exposed directly (concrete collection, matches the JSON-serialization convention used for `WorkflowInfo.OutputExecutorIds`). Never null; empty for legacy / terminal events. New ctors take a single `OutputTag` or `IEnumerable<OutputTag>?`; the existing (data, executorId) ctor remains and produces an untagged event. `HasTag(OutputTag)` helper. `AgentResponseEvent` and `AgentResponseUpdateEvent` gain matching tag-accepting ctors forwarding to the base. * `WorkflowOutputEventExtensions.IsIntermediate(this WorkflowOutputEvent)`: extension method returning `evt.HasTag(OutputTag.Intermediate)`. The preferred way to ask "is this an intermediate output?" without reaching into the Tags set. * `WorkflowBuilder.WithOutputFrom(IEnumerable<ExecutorBinding>, OutputTag)` and `WorkflowBuilder.WithOutputFrom(ExecutorBinding, OutputTag)`: forward-looking tagged overloads. The IEnumerable form is the primary tagged surface; the single-executor form is a convenience for the common one-executor case. Currently usable for the `OutputTag.Intermediate` singleton; will become the primary surface once the `OutputTag` constructor is opened to user-defined tags in a future release. Callers in this release should prefer the intent-specific `WithIntermediateOutputFrom` extension for the intermediate case. Tags accumulate across repeated calls; same tag repeated dedupes via the HashSet. * `WorkflowBuilderExtensions.WithIntermediateOutputFrom(this WorkflowBuilder, IEnumerable<ExecutorBinding>)`: helper that forwards to `WithOutputFrom(executors, OutputTag.Intermediate)`. Takes an IEnumerable (matching the tagged WithOutputFrom shape) - callers pass collection literals: `builder.WithIntermediateOutputFrom([a, b])`. XML doc remarks call out the Futures-flag interaction and the AIAgent-payload forwarding contract. Internal shape changes: * `WorkflowBuilder._outputExecutors`: HashSet<string> -> Dictionary< string, HashSet<OutputTag>>. The value set is empty for executors designated only via the untagged WithOutputFrom; contains Intermediate (and possibly future tags) otherwise. * `Workflow.OutputExecutors`: HashSet<string> -> Dictionary<string, HashSet<OutputTag>>. * `OutputFilter.CanOutput`: `Contains(id)` -> `ContainsKey(id)`. * `WorkflowInfo.OutputExecutorIds`: HashSet<string> -> Dictionary< string, HashSet<OutputTag>>, with a custom JsonConverter that reads both the new map shape (`{id: ["intermediate", ...]}`) and the legacy array shape (`[id1, id2]`, where each id is treated as an untagged output). Always writes the map shape. IsMatch updated to compare per-id tag sets. Tests landing in this commit (per the test-with-feature principle): * `OutputTagTests.cs` (6 tests): KnownValues, EqualityIsOrdinalOnValue, DefaultStructValueIsDistinct (default(OutputTag) does not collide with the Intermediate singleton in a HashSet), GetHashCodeMatchesEquals, JsonConverter_RoundtripsValueAsString, ConstructorIsInternal (reflection-based assertion that the (string) ctor is `internal`). * `WorkflowBuilderTests.cs` adds 7 new tests pinning the builder API contract: RegistersWithEmptyTagSet, AddsIntermediateTag, MultipleExecutorsAllUntagged, ThenIntermediate_AccumulatesTags, RepeatedDedupes, OnlyRegistersWithoutPriorWithOutputFrom, TracksExecutorBinding. * `BackwardsCompatibility/JsonCheckpointSerializationTests.cs` (new folder + file, 5 tests): event-level ctor contract tests (single-tag, no-tag, multi-tag — the last with a custom tag); IsIntermediate() asserted; load-bearing JSON BC tests for `WorkflowInfo.OutputExecutorIds` - `WorkflowOutputExecutorsReadsLegacyArrayShape` (legacy ids map to empty tag sets) and `WorkflowOutputExecutorsWritesMapShape`. The plan's three JSON round-trip tests for `WorkflowOutputEvent.Tags` were dropped: `WorkflowEvent` is not currently a serialized checkpoint shape (see the comment in WorkflowsJsonUtilities.cs about events not being persisted), so there is no real back-compat surface to pin through JSON. They are substituted with in-process ctor/property round-trip tests that exercise the `Tags` / `HasTag` / `IsIntermediate` contract. Validation: full `Microsoft.Agents.AI.Workflows.UnitTests` suite runs green on net10.0 (565 passing, 0 failing). Core library builds clean on net472, netstandard2.0, net8.0, net9.0, and net10.0. Test project builds clean on net472 + net10.0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: route AgentResponse(Update) through the output filter under a Futures flag `InProcessRunnerContext.YieldOutputAsync` historically special-cased AgentResponse and AgentResponseUpdate payloads: it built the typed event subclass and emitted it directly, bypassing the output filter. Rewrites the method so that: - When `Futures.EnableAgentResponseOutputTaggingAndFiltering` is `false` (the current default), AgentResponse(Update) keep the legacy bypass — emitted as AgentResponseEvent / AgentResponseUpdateEvent with no tags. Existing callers see no behavior change. - When the flag is `true`, AIAgent payloads flow through the output filter just like every other payload type: undesignated sources are dropped, and the emitted event carries the source's tag set (empty for terminal `WithOutputFrom`, `{Intermediate}` for `WithIntermediateOutputFrom`, the set union when both designations apply). Non-AIAgent (POCO) outputs also now carry the source's tag set on the emitted WorkflowOutputEvent unconditionally — additive, since no existing assertion inspected Tags. Subclass events (`AgentResponseEvent` / `AgentResponseUpdateEvent`) continue to be emitted under both modes so `switch (evt) { case AgentResponseEvent: ... }` consumer code keeps matching. Adds `OutputFilter.TryGetTags` as the tag-aware lookup used by the runner. `OutputFilter.CanOutput` is kept (still used by the existing sync tests in `OutputFilterTests.cs`). Tests ----- - `Futures/Futures.AgentResponseOutputFilteringAndTaggingTests.cs` (new): the F1–F13 matrix from the plan, covering every combination of `(flag on/off) × (designation) × (payload shape)`. Uses a `FuturesScope` IDisposable + a `FuturesSerial` xUnit collection (DisableParallelization = true) to keep the process-global flag from leaking across parallel tests. - `OutputFilterTests.cs`: four new `Test_OutputFilter_…` cases for the `TryGetTags` surface (empty-tag-set for terminal designation, `{Intermediate}` for intermediate designation, union for accumulated designation, `false` for unregistered). 582/582 unit tests pass on net10.0 (565 baseline + 17 new). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: tag-aware defaults and designation API on orchestration builders Aligns the .NET orchestration builders with Python's output / intermediate-output distinction. Each builder either applies a Python-aligned default designation set or replays the user's explicit `WithOutputFrom` / `WithIntermediateOutputFrom` calls, never both. Static `AgentWorkflowBuilder.BuildSequential` / `BuildConcurrent` apply defaults unconditionally (no user-facing fluent surface to take control through): - Sequential: terminal `end` + every agent designated intermediate. - Concurrent: terminal `end` + every agent and per-agent accumulator designated intermediate. The three fluent instance builders memoize agent-typed designation calls in a `Dictionary<AIAgent, HashSet<OutputTag>>` (empty set = terminal-only, non-empty = intermediate tag(s)) so repeated calls dedupe naturally. They replay the entries at `Build()` time, suppressing defaults when any call has been made: - `HandoffWorkflowBuilder` / `HandoffWorkflowBuilderCore<TBuilder>` (also picked up by the obsolete `HandoffsWorkflowBuilder` via inheritance). Default: terminal `HandoffEnd` + every handoff agent intermediate. (Bug fix: legacy code relied on `WithOutputFrom(end)` to bind `HandoffEnd`. The new explicit-designation path bypasses that, so `Build()` now calls `BindExecutor(end)` unconditionally to keep validation happy.) - `GroupChatWorkflowBuilder` — default: terminal host + every participant intermediate. - `MagenticWorkflowBuilder` — default: terminal orchestrator + every team member intermediate. Designating a non-participant agent throws `InvalidOperationException`. The bare `WorkflowBuilder` default is unchanged — only the orchestration-style builders gain implicit defaults, matching the plan's non-goal. Tests ----- - `AgentWorkflowBuilder.SequentialTests` / `.ConcurrentTests`: one default-spec assertion each. - `GroupChatWorkflowBuilderTests`: defaults-match-spec, explicit-replaces-defaults, non-participant throws. - `HandoffWorkflowBuilderTests` (new file): same three. - `MagenticWorkflowBuilderTests` (new file): same three. 593/593 unit tests pass on net10.0 (582 baseline + 11 new). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: WorkflowHostAgent forwards AgentResponseEvent unconditionally under Futures-on Aligns the .NET Workflow-as-Agent surface with Python `as_agent`. Under `Futures.EnableAgentResponseOutputTaggingAndFiltering = true`, `WorkflowSession.InvokeStageAsync` now forwards `AgentResponseEvent` unconditionally — joining `AgentResponseUpdateEvent` in ignoring the host's `includeWorkflowOutputsInResponse` switch. That switch keeps governing the generic `WorkflowOutputEvent` path for non-AIAgent payloads, where it is further short-circuited by an `IsIntermediate()` check (tagged intermediate outputs always surface). Under Futures-off the legacy asymmetry is preserved: `AgentResponseUpdateEvent` always forwarded, `AgentResponseEvent` gated by `includeWorkflowOutputsInResponse`. Back-compat: with `Futures.EnableAgentResponseOutputTaggingAndFiltering` left at its default `false`, observable behavior is identical to before. `Futures` documentation gains a remark explaining the `Workflow.AsAIAgent()` interaction in both flag states. Runner fix ---------- `InProcessRunnerContext.YieldOutputAsync` now skips `Executor.CanOutput` for AgentResponse-shaped payloads under both Futures branches. `AIAgentHostExecutor` doesn't declare AgentResponse(Update) in its `Yields` set, so the historical legacy bypass had silently skipped the check; Phase 3's Futures-on path was running it and would reject AIAgent payloads. AIAgent-shaped payloads are now always a valid output shape, matching the legacy bypass semantics. Phase 4 follow-on ----------------- Switched the three orchestration-builder designation-replay loops to iterate `Dictionary.Keys` with a value lookup instead of constructing/destructuring `KeyValuePair<,>`. Cleaner shape and avoids the netstandard2.0 / net472 `KeyValuePair<,>.Deconstruct` unavailability that surfaced when this branch multi-TFM-built. Tests ----- `WorkflowHostSmokeTests.IntermediateForwarding` (new nested class, 6 tests): - intermediate AgentResponse forwarded past the include-outputs gate (Futures on) - terminal AgentResponse forwarded unconditionally (Futures on) - terminal AgentResponse gated by include flag (Futures off, legacy) - undesignated AIAgent executor emits no AgentResponseEvent under Futures-on - legacy bypass still emits AgentResponseEvent under Futures-off - intermediate tag is observable via `update.RawRepresentation` The class joins the `FuturesSerial` xUnit collection so the process-global flag is serialized against other Futures-toggling tests. 599/599 unit tests pass on net10.0 (593 baseline + 6 new). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: SequentialWorkflowBuilder and ConcurrentWorkflowBuilder, OrchestrationBuilderBase Promotes the Sequential and Concurrent orchestration shapes to first-class fluent builder classes, matching Handoff / GroupChat / Magentic. Users can call `WithOutputFrom(agents)` / `WithIntermediateOutputFrom(agents)` to control which agents are designated output / intermediate sources; when no designation call is made, the Python-aligned defaults apply (terminal aggregator output + every agent intermediate; Concurrent also tags per-agent accumulators). `AgentWorkflowBuilder.BuildSequential(...)` and `BuildConcurrent(...)` are kept and now delegate to the new builders; observable behavior unchanged. Five static factories now mirror each other: - `AgentWorkflowBuilder.CreateSequentialBuilderWith(params IEnumerable<AIAgent>)` - `AgentWorkflowBuilder.CreateConcurrentBuilderWith(params IEnumerable<AIAgent>)` - `AgentWorkflowBuilder.CreateHandoffBuilderWith(AIAgent)` (already existed) - `AgentWorkflowBuilder.CreateGroupChatBuilderWith(Func<...>)` (already existed) - `AgentWorkflowBuilder.CreateMagenticBuilderWith(AIAgent)` (new) OrchestrationBuilderBase ------------------------ New abstract `OrchestrationBuilderBase<TBuilder>` unifies the shared fluent surface across all five orchestration builders: `WithName`, `WithDescription`, `WithOutputFrom`, `WithIntermediateOutputFrom`, and the `ApplyOutputDesignations(builder, agentMap, kind, applyDefaults)` helper that either replays the user's designations or invokes the orchestration-specific defaults. Removes ~150 LOC of duplicated designation-management code from the four non-Handoff builders, plus the equivalent from `HandoffWorkflowBuilderCore`. Tests ----- - New `SequentialWorkflowBuilderTests.cs` / `ConcurrentWorkflowBuilderTests.cs` (replace the old `AgentWorkflowBuilder.{Sequential,Concurrent}Tests.cs` nested-class files). Method names normalized to `Test_<BuilderType>_<Scenario>[Async]`. - Shared helpers (`DoubleEchoAgent`, `DoubleEchoAgentWithBarrier`, `WorkflowRunResult`, `RunWorkflow*`) moved from the old `AgentWorkflowBuilderTests` partial class into a new `OrchestrationTestHelpers` static class in `OrchestrationTestHelpers.cs`. Downstream test files (Group Chat, Handoff, Sequential, Concurrent) updated to qualify with `OrchestrationTestHelpers.*`. - A new `AgentWorkflowBuilderTests.cs` covers the static surface directly: `BuildSequential` / `BuildConcurrent` invariants and aggregator wiring, plus null-rejection + round-trip checks for every `Create*BuilderWith` factory. - New AsAgent intermediate-suppression tests on a nested `AsAgentForwarding` class for each of Sequential and Concurrent: build with only the terminal agent designated via `WithOutputFrom`, run via `AsAIAgent(...)`, assert via `AgentResponseUpdate.AuthorName` that intermediate agents do not surface. Both join the `FuturesSerial` collection. - New `Test_<Builder>_WithDescriptionPropagatesToWorkflow` smoke tests on Sequential and Concurrent (newly available via the base class). 625/625 unit tests pass on net10.0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: dotnet format * fixup: encoding * fixup: charset * fixup: Updates for PR feedback * fixup: format * fixup: merge issue * Fix intermediate filtering on .AsAgent() * fix filter logic * fix: Revert logic change and add comments --------- Co-authored-by: Jacob Alber <jalber@lokitoth.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
d2f79930d5 |
.NET: feat: Update GroupChatManager semantics to match other Orchestration patterns (#6140)
* Refactor group chat workflow to prevent message echoing and enhance checkpointing - Updated GroupChatWorkflowBuilder to disable forwarding incoming messages to prevent duplicates. - Enhanced RoundRobinGroupChatManager with checkpointing support to preserve state across executions. - Modified GroupChatHost to maintain a history of messages and track the current speaker for message broadcasting. - Implemented broadcasting logic to ensure participants receive messages from others while excluding their own responses. - Added comprehensive unit tests for group chat orchestration, including scenarios for tool approval and function calls. - Introduced a new ApprovalHarness for testing tool invocation and approval workflows. * fixup: format * Add JSON serialization support for GroupChatManagerState and RoundRobinGroupChatManagerState --------- Co-authored-by: Jacob Alber <jalber@lokitoth.com> |
||
|
|
945647a065 |
.NET: feat: Bring Handoff Orchestration to parity with Python (#6138)
* feat: implement autonomous mode and termination conditions in handoff workflow * fixup: format * feat: enhance autonomous mode with per-agent configurations and add unit tests * fixup: remove empty file --------- Co-authored-by: Jacob Alber <jalber@lokitoth.com> |
||
|
|
2ef20cd0aa |
.NET: Add Magentic E2E workflow coverage (#5833)
* Add E2E test plan for Magentic orchestrator Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/96d76349-1ffd-482b-a3ee-ed208778b1bb Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add MagenticOrchestrationTests.cs scaffold for Magentic E2E tests Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/44a4fd8a-3828-40e5-9435-90381aeffdb8 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Fix MagenticOrchestrator output declaration and add first E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/322c9e2d-59bc-42ad-9a1e-f6fd4c866b26 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add plan review test and event emission tests Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/322c9e2d-59bc-42ad-9a1e-f6fd4c866b26 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add next speaker validation test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/322c9e2d-59bc-42ad-9a1e-f6fd4c866b26 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add Magentic E2E implementation review Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/b2c60ce7-4d05-4a0d-b05d-d4284f5b7bb3 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add PlanSignoff_Disabled_Proceeds_Immediately E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/6e8bca46-448d-4f21-a7e9-240179571970 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add NextSpeaker_Empty_Falls_Back_To_First E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/6e8bca46-448d-4f21-a7e9-240179571970 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add Task_Completes_After_Multiple_Rounds E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/6e8bca46-448d-4f21-a7e9-240179571970 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add PlanReview_Revised_Triggers_Replan E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/6e8bca46-448d-4f21-a7e9-240179571970 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add MaxRoundLimit_Terminates_Workflow E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/6e8bca46-448d-4f21-a7e9-240179571970 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add MaxStallCount_Triggers_Reset E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/6e8bca46-448d-4f21-a7e9-240179571970 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Update MagenticE2E_ImplementationReview.md with full coverage status Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/6e8bca46-448d-4f21-a7e9-240179571970 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Rewrite Magentic E2E implementation review Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/1f878ef4-61b0-410a-a8bc-ebf618b3e5de Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add MaxResetLimit_Terminates_Workflow E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/aba19507-7c7e-40dd-850d-d1fabb5dfa65 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add PlanReview_On_Stall_Replan E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/aba19507-7c7e-40dd-850d-d1fabb5dfa65 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add Instruction_Message_Sent_When_Present E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/aba19507-7c7e-40dd-850d-d1fabb5dfa65 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Update ImplementationReview.md to reflect 14 tests Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/aba19507-7c7e-40dd-850d-d1fabb5dfa65 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Rewrite Magentic E2E implementation review Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/6fe88a80-2e05-40d5-9539-ca7c59b9022b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add ProgressLedger_Retry_On_Parse_Failure E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/125f6628-6b3b-4c51-9a51-ae84baece6bb Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add ProgressLedger_Max_Retries_Triggers_Reset E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/125f6628-6b3b-4c51-9a51-ae84baece6bb Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add Stall_NoProgress_Increments_StallCount E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/125f6628-6b3b-4c51-9a51-ae84baece6bb Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add PlanReview_Multiple_Revisions E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/125f6628-6b3b-4c51-9a51-ae84baece6bb Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Update ImplementationReview.md to reflect 18 tests and new coverage Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/125f6628-6b3b-4c51-9a51-ae84baece6bb Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Rewrite Magentic E2E implementation review Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/21f3b1ae-183e-4fea-99ad-14efc19f084d Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Preserve IsStalled on stall-triggered plan review requests Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/1b9e74e8-69e1-43f2-8467-c5ba963c2622 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Rename isStalled parameter to replanAfterStall for clarity Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/1b9e74e8-69e1-43f2-8467-c5ba963c2622 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add Task_Delegates_To_Correct_Agent E2E test with multi-participant routing assertion Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/9b34e409-61b8-4650-ae55-34efad034ed0 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add Progress_Made_Decrements_StallCount E2E test verifying stall count decrement avoids reset Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/9b34e409-61b8-4650-ae55-34efad034ed0 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add Consecutive_Stalls_Trigger_Reset E2E test for multi-stall threshold reset Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/9b34e409-61b8-4650-ae55-34efad034ed0 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Magentic E2E: preserve IsStalled on stall-triggered plan reviews, add routing/stall tests Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/9b34e409-61b8-4650-ae55-34efad034ed0 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Fix replan-on-every-turn: skip plan on agent return; align StallCount to > (match Python) Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/43e46b0d-4263-4353-856a-c3730abb1734 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Update implementation review doc for replan-fix and stall threshold alignment Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/43e46b0d-4263-4353-856a-c3730abb1734 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Rewrite Magentic E2E implementation review Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/3d15763b-3a68-488e-9412-3fa280e083c0 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Update stall docs to use > semantics, skip checkpoint-state tests, simplify NextSpeaker fallback test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/cc9ea5a8-84d8-4b6d-bb60-ac9619824d81 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Rewrite Magentic implementation review Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/ed87670a-bf4d-4ba5-a2f3-395a2eead9de Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add empty-team validation to MagenticWorkflowBuilder.Build() and E2E test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/e490fdf7-f107-4fde-ba1f-efdfd9a729c6 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add IsTerminated guard to TakeTurnAsync and post-termination rejection test Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/e490fdf7-f107-4fde-ba1f-efdfd9a729c6 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Rewrite ImplementationReview.md with final 23-test status Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/e490fdf7-f107-4fde-ba1f-efdfd9a729c6 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add PR description markdown Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/df9b4579-10c3-4bfb-927e-da3a0e70009e Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Remove temporary markdown files Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/b3e67553-a3a3-4282-98f2-afd8ad7a6b5d Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Fix IDE1006: add Async suffix to async test methods in MagenticOrchestrationTests Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/629fcc07-865e-4832-9e59-ea13df561c5a Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Update error messages per review comments in MagenticOrchestrator and MagenticWorkflowBuilder Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/053e5ded-81e3-4e56-acf1-2a8a939a04b0 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Escape JSON string values in CreateProgressLedgerResponse test helper Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/ec610c61-0a14-44e2-82fd-1cf35e85d6cc Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> Co-authored-by: Jacob Alber <jaalber@microsoft.com> |
||
|
|
3256550c55 |
.NET: fix: allow naming handoff workflows (#5799)
* fix: allow naming handoff workflows * Only set name/description if not NullOrWhitespace Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Jacob Alber <jalber@fernir.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jacob Alber <jaalber@microsoft.com> |
||
|
|
190ca75b6a |
.NET: Add Workflow Builder Specialized Edge tests (#5826)
* Add workflow builder edge tests Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/3c3d5324-cdcd-4a38-8c67-94e4e78e29c5 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Strengthen workflow edge helper tests Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/af831ee2-0a99-4427-9ffd-a3b5022c1b3b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Normalize edge helper bad input validation Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/af831ee2-0a99-4427-9ffd-a3b5022c1b3b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Clarify edge helper target validation Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/af831ee2-0a99-4427-9ffd-a3b5022c1b3b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Use explicit target parameter names Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/af831ee2-0a99-4427-9ffd-a3b5022c1b3b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Document workflow edge test helpers Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/af831ee2-0a99-4427-9ffd-a3b5022c1b3b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Clarify null element validation messages Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/af831ee2-0a99-4427-9ffd-a3b5022c1b3b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add repeated chain executor coverage Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/af831ee2-0a99-4427-9ffd-a3b5022c1b3b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Preserve Throw helper validation style Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/af831ee2-0a99-4427-9ffd-a3b5022c1b3b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Cover empty switch case targets Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/af831ee2-0a99-4427-9ffd-a3b5022c1b3b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Relax builder null assertion parameter checks Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/af831ee2-0a99-4427-9ffd-a3b5022c1b3b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Inline ValidateTargets into call sites Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/cb9a6a6a-02c7-41a8-a4b4-da16ad62ef86 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Refactor ForwardExcept with TFM-specialized TryGetNonEnumeratedCount Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/b081f61f-93ce-45dc-abbd-82c465395470 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Use TFM-specialized count check: TryGetNonEnumeratedCount for NET6+, ICollection pattern for NETFX Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/8ec28a43-e7b7-456e-8d8e-921511b4accc Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Apply TFM-specialized count check to ForwardMessage as well Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/9238ea32-a3e8-4b83-9683-484ad400071f Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Address review feedback: simplify Throw.IfNull in SwitchBuilder per westey-m suggestion Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/299950fd-4457-47f3-a373-f65d601b7ea5 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Use indexed parameter name in SwitchBuilder Throw.IfNull: executors[index] Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/c5655707-5b0b-44f3-98a9-5f3961e32cfe Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Revert #if NET6_0_OR_GREATER back to #if NET; inline executorIndex++ Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/c5655707-5b0b-44f3-98a9-5f3961e32cfe Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Add comment explaining unusual Throw.IfNull use for null elements inside collection Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/c5655707-5b0b-44f3-98a9-5f3961e32cfe Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> Co-authored-by: Jacob Alber <jaalber@microsoft.com> |
||
|
|
981726cc15 |
.NET: feat(evals): add ground_truth/expected_output support for workflow evaluation (#5755)
* .NET: feat(evals): add ground_truth/expected_output support for workflow eval Brings .NET to parity with Python PR #5234 for issue #5135: - Add expectedOutput parameter to Run.EvaluateAsync (workflow) and stamp on the overall EvalItem.ExpectedOutput. - Map EvalItem.ExpectedOutput -> ground_truth in the Foundry JSONL payload, item_schema, and data_mapping for similarity. - Add GroundTruthEvaluators set (currently builtin.similarity) and a FindMissingGroundTruthEvaluators helper. - Fail fast with InvalidOperationException when a ground-truth evaluator is selected but no item provides an ExpectedOutput, instead of surfacing a remote provider error. - Add tests in FoundryEvalConverterTests and WorkflowEvaluationTests. - Add Evaluation_WorkflowExpectedOutputs sample (workflow + Foundry similarity). Fixes microsoft/agent-framework#5135 (.NET side). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review: relax BuildOverallItem events to IReadOnlyList<WorkflowEvent> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Sample: disable per-agent breakdown when using reference-based evaluator Per-agent EvalItems are intentionally left without ExpectedOutput, so the new fail-fast validation in FoundryEvals would throw when Similarity is invoked for per-agent items. Pass includePerAgent: false in the workflow + similarity sample, and document this gotcha in the EvaluateAsync XML doc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix BuildOverallItem: fall back to last ExecutorCompletedEvent AgentResponseEvent is only emitted when AIAgentHostOptions.EmitAgentResponseEvents is enabled, which is not the default for WorkflowBuilder(agent).AddEdge(...). When it is absent, fall back to the last non-internal ExecutorCompletedEvent whose Data is an AgentResponse / ChatMessage / string so the overall EvalItem (and any expectedOutput) is produced. Without this, samples wired up the standard way returned 0 evaluation items. Update test to cover the fallback path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Sample: enable EmitAgentResponseEvents; eval throws clear error when no overall response found Root cause of '0 results': AIAgentHostExecutor only emits AgentResponseEvent when AIAgentHostOptions.EmitAgentResponseEvents is true (default false). For ordinary AIAgent executors the runtime's ExecutorCompletedEvent.Data is null, so the prior fallback couldn't find a final response either. Sample now builds executors with EmitAgentResponseEvents=true via BindAsExecutor(hostOptions). EvaluateAsync now throws InvalidOperationException with a remediation hint when the user supplies expectedOutput but no overall final response can be located, instead of silently returning 0/0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Guard against null sample/error/usage/datasource_item in ParseDetailedItem Foundry eval responses can have these properties present with JSON null or non-object values, which caused JsonElement.TryGetProperty to throw 'requires Object, has Null'. Check ValueKind == Object before drilling in. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: reorder expectedOutput, tighten ground-truth check, add fail-fast test * WorkflowEvaluationExtensions.EvaluateAsync: move 'expectedOutput' to after 'splitter' so the original positional contract of (splitter, cancellationToken) is preserved for existing callers. * FoundryEvals: require ALL items to carry ExpectedOutput when a ground-truth evaluator is selected (e.g. similarity), not just any. Reference-based evaluators score per-item, so a single missing GT would still surface as a provider-side validation error. Updated fail-fast message accordingly. * WorkflowEvaluationTests: add EvaluateAsync_WithExpectedOutputButNoFinalResponse_ThrowsAsync to verify the InvalidOperationException is thrown (and that the message mentions EmitAgentResponseEvents). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fail-fast on missing overall item regardless of expectedOutput; harden BuildOverallItem default * EvaluateAsync now throws InvalidOperationException whenever 'includeOverall' is requested but BuildOverallItem cannot produce an item, instead of only when 'expectedOutput' is supplied. Same misconfiguration (agents not bound with EmitAgentResponseEvents) used to silently return empty results — now it surfaces a clear, actionable error in both cases. * BuildOverallItem switch default now throws instead of returning null. The preceding for-loop already constrains Data to AgentResponse/ChatMessage/ string, so reaching default would indicate a contract drift; throw to make the bug visible. * Test renamed and broadened to verify the throw fires without expectedOutput. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: alliscode <25218250+alliscode@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
9b9604ce18 |
fix: avoid mutating handoff message roles (#5808)
Co-authored-by: Jacob Alber <jaalber@microsoft.com> |
||
|
|
818ae65b77 |
fix: declare Magentic protocol messages (#5778)
Co-authored-by: Jacob Alber <jaalber@microsoft.com> |
||
|
|
41d6c61f81 |
.NET fix: Synthesized Handoff FunctionResult is never sent to agent (#5718)
* test: Split out Handoff Orchestration tests * fix: Synthesized Handoff FunctionResult is never sent to agent When we receive a handoff request from the agent, we need to service it outside of the Agent Loop to terminate the loop. What this means is that we take ownership of terminating the call by feeding the result back into the agent on a subsequent invocation. When we refactored Handoff to support HITL and make use of AgentSession, we inadvertantly removed this step, causing subsequent invocations to the Handoff agent to fail (first works, but breaks the state). The fix is to be more precise about the agent's bookmark when concatenating the result of agent invocation to the shared conversation history. * test: Add unit tests for Handoff FunctionCall/Result matching fix |
||
|
|
27324a8013 |
.NET: Mark Magentic Orchestration Experimental (#5704)
* fix: Mark Magentic Orchestration Experimental * Apply [Experimental] to all public Magentic types and suppress MAAIW001 in project Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/957a07c1-a805-40eb-989d-bd3425d4c0af Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> |
||
|
|
ce70ca1a9f |
.NET: feat: Implement Magentic Orchestration for .NET (#5595)
* feat: Implement Magentic Orchestration for .NET * fixup: Update for review comments * fix: Fix FenceJsonRegexPattern * fix: Format * fix: Updates for PR feedback * fix: Add missing serialized types to source gen for trimming * fix: Address PR Comments |
||
|
|
9f3f7fd03b |
fix: JSON Serialization issue with MultiPartyConversation (#5653)
When MultiPartyConversation gets saved during checkpointing, the data for the chat history is not persisted, resulting in failures to deserialize after. The fix is to make the history visible to the source generated serialization code. |
||
|
|
162985f2a3 |
.NET: feat: Implement message filtering to exclude non-portable content typ… (#5410)
* feat: Implement message filtering to exclude non-portable content types before forwarding Co-authored-by: Copilot <copilot@github.com> * Added unit tests to cover forwarded message filtering within AI Agent executors Co-authored-by: Copilot <copilot@github.com> * Update dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: Disable forwarding of incoming messages in AIAgentHostExecutor tests Co-authored-by: Copilot <copilot@github.com> --------- Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jacob Alber <jaalber@microsoft.com> |
||
|
|
4b5a8478de |
.NET: Hosting updates to declarative workflows (#5589)
* Make DeclarativeWorkflowExecutor ChatProtocol-compatible for AsAIAgent hosting Extends the existing DeclarativeWorkflowExecutor<TInput> root executor with additional ChatProtocol-compatible input routes (string, ChatMessage, IEnumerable<ChatMessage>, ChatMessage[], TurnToken) so that workflows built via DeclarativeWorkflowBuilder.Build<TInput>(...) work both for direct invocation and when hosted via Workflow.AsAIAgent(...). - Each input message advances the declarative graph immediately; the TurnToken that the host sends after the message batch is treated as a no-op since the message has already been processed. - Conversation id resolution now prefers persisted workflow system state, then DeclarativeWorkflowOptions.ConversationId, then a newly created conversation. This makes multi-turn invocations reuse the prior conversation rather than creating a fresh one each turn. - The separate DeclarativeChatProtocolStartExecutor and DeclarativeWorkflowBuilder.BuildChatProtocol overloads introduced earlier are removed; callers continue to use Build<TInput>(...). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use DeclarativeWorkflowContext when reading workflow conversation id GetWorkflowConversation() requires a DeclarativeWorkflowContext (it calls ReadState which dynamic-casts via the DeclarativeContext helper). The chat-protocol auxiliary handlers receive a BoundWorkflowContext, so calling the extension on the raw IWorkflowContext throws `Invalid workflow context: BoundWorkflowContext`. Use the wrapped declarativeContext that we already constructed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: surface ExecutorFailedEvent as ErrorContent in AsAIAgent response WorkflowSession.InvokeStageAsync only converted WorkflowErrorEvent into an ErrorContent payload. ExecutorFailedEvent fell through to the default branch which emits an empty AgentResponseUpdate carrying the event in RawRepresentation. OutputConverter then mapped that to a workflow_action item with status=failed and dropped the exception entirely, so callers got status=completed and error=null even when an executor threw. - WorkflowSession.cs: add ExecutorFailedEvent case mirroring WorkflowErrorEvent. Honors _includeExceptionDetails. - OutputConverter.cs: when an update carries both a WorkflowEvent in RawRepresentation and non-empty Contents, fall through to content processing so the unwrapped error (or any future content payload from a workflow event) is actually emitted. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * improve: walk inner exceptions when surfacing ExecutorFailedEvent DeclarativeActionExecutor wraps inner exceptions in DeclarativeActionException with a generic `Unhandled workflow failure` message, hiding the real cause. Walk InnerException so the response shows the full chain (e.g. the underlying HTTP 400 / auth error). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Surface declarative SendActivity output as chat content SendActivityExecutor now emits AgentResponseEvent in addition to MessageActivityEvent so chat protocols (e.g. AsAIAgent) receive the formatted activity text. The existing MessageActivityEvent is preserved for DevUI/observability. Also extend WorkflowSession.WorkflowOutputEvent handling to accept AgentResponse payloads, mapping them to their constituent ChatMessages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Persist hosted-agent sessions to disk; fix System.LastMessageText Adds FileSystemAgentSessionStore that writes the serialized AgentSession JSON (which already embeds the workflow's in-memory checkpoint manager) to a per- conversation file under /.checkpoints when running in a Foundry hosted env or {cwd}/.checkpoints locally. Mirrors the python foundry_hosting._responses FileCheckpointStorage pattern so multi-turn workflow state survives process restarts without requiring callers to wire up storage themselves. AddFoundryResponses now defaults to FileSystemAgentSessionStore.CreateDefault() instead of InMemoryAgentSessionStore; callers can still override via DI. Also fixes {System.LastMessageText} resolving empty: DeclarativeWorkflowExecutor .AdvanceAsync was passing the message rehydrated from CreateMessageAsync to SetLastMessageAsync, but ResponseItem -> ChatMessage round-trip drops the .Text extension content. Use the original input ChatMessage (which still has the user-supplied text) and copy the server-assigned MessageId across when present. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Close multi-modal input parity gaps with python foundry_hosting InputConverter now mirrors the python _responses.py content handling: - ComputerScreenshotContent maps to UriContent/HostedFileContent (was dropped). - Plain TextContent and SummaryTextContent map to MEAI TextContent. - MessageContentReasoningTextContent maps to MEAI TextReasoningContent. - input_file with text/* file_data data URIs is decoded inline into TextContent with a [File: name] prefix, matching python _convert_file_data so {System.LastMessageText} surfaces the file body. Non-text data URIs and hosted/url file references preserve filename as AdditionalProperties. Image/file extraction logic is extracted into shared AppendImageContent and AppendFileContent helpers used by both the fresh-input and history-replay switches. Existing 37 InputConverter tests still pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Foundry hosting: round-trip tool-approval (HITL) content as mcp_approval_request/response Closes the gap where Microsoft.Agents.AI.Foundry.Hosting silently dropped MEAI ToolApprovalRequestContent/ToolApprovalResponseContent in both directions. We now serialize them onto the wire as the standard Responses API mcp_approval_request/mcp_approval_response items with server_label='agent_framework', and parse the symmetric inbound shapes back into MEAI content. Wire format: - The Responses API only standardizes mcp_approval_* as the approval primitive. We declare AF as a virtual MCP server via the server_label field, which is honest for AF's server-side tool-call holding pattern. - The SDK enforces a strict {prefix}_{50hex} wire-id format, so we hash the AF RequestId and persist a wireId<->afRequestId mapping in AgentSession.StateBag so a later mcp_approval_response can be matched back to the originating workflow request. Coexists with the existing ConsentAwareMcpClientAIFunction flow (AgentFrameworkResponseHandler.cs) which emits mcp_approval_request from a side-channel, not via OutputConverter's content switch. Known follow-up: python (foundry_hosting/_responses.py) has the same output-side gap (ToolApprovalRequestContent emission). Out of scope here. Tests: +9 unit tests covering both fresh-input and history-replay shapes, StateBag mapping resolution, and the non-FunctionCallContent skip path. Existing 108 converter tests still pass; full suite 370/370. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review feedback for hosted-declarative-dotnet FileSystemAgentSessionStore reliability/scoping: - Bound Sanitize() stackalloc at 256 chars, fall back to ArrayPool for longer ids so a long conversationId can no longer crash the hosting process with StackOverflowException. - Use a Guid-suffixed temp file (\{path}.{guid}.tmp\) so concurrent SaveSessionAsync calls on the same conversation can no longer race on the same temp file. Best-effort temp cleanup on failure. - Bucket session files by agent.Name when set so two keyed agents that happen to share a conversationId no longer overwrite each other's persisted state. Single-agent / unnamed-agent cases keep the original flat layout (Python parity). DeclarativeWorkflowExecutor chat-protocol routing: - ConfigureChatProtocolRoutes uses IsAssignableFrom rather than exact type equality so a broader TInput (object, base interfaces) does not have its inherited inputTransform shadowed by handlers we register here. - HandleChatMessagesAsync / HandleChatMessageArrayAsync now advance through every message in the batch instead of keeping only the trailing one, so multi-message turns and replayed history are no longer silently truncated. AdvanceAsync gains a finalizeTurn flag so only the last message in the batch sends the result. Tests: - New FileSystemAgentSessionStoreTests covering constructor, fresh-session fallback for missing/empty files, root-directory creation, save/get round-trip, agent-Name scoping isolation, long conversationId, invalid-character sanitization, and concurrent-save behavior. - New InputConverterTests covering AppendFileContent: text/* data URI decode (with and without filename prefix), non-text data URI passthrough, malformed data URI fallback, and filename propagation onto UriContent / HostedFileContent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add tests for remaining PR review feedback (C2, D1, E1) C2: InputConverter — add 9 tests covering SDK content types that previously had no coverage: - SdkTextContent → TextContent (input + output paths) - SummaryTextContent → TextContent (input + output paths) - MessageContentReasoningTextContent → TextReasoningContent (input + output) - ComputerScreenshotContent (HTTP URL → UriContent, data: URI → DataContent, output path → UriContent) D1: OutputConverter — add 2 tests for the WorkflowEvent + Contents fall-through: - WorkflowEvent in RawRepresentation with text Contents must flow through the content-processing path (text-delta event emitted). - WorkflowEvent + ErrorContent must produce a failed event rather than be swallowed by the workflow branch. E1: SendActivityExecutor — extend CaptureActivityAsync to assert that the executor emits an AgentResponseEvent carrying the activity text with the correct ExecutorId and ChatRole.Assistant role. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Defense-in-depth: neutralize dot-segments in Sanitize and cap TryDecodeTextDataUri input size Addresses claude-opus-4.6 security review on PR #5589: - FileSystemAgentSessionStore.Sanitize now replaces all-dot segments (., .., ...) with underscores so a developer-controlled agent.Name cannot escape the root directory on Linux (where Path.GetInvalidFileNameChars only contains NUL and '/'). - InputConverter.TryDecodeTextDataUri rejects encoded payloads larger than 16 MiB before calling Convert.FromBase64String, preventing a single oversized data URI from triggering a multi-megabyte allocation. - Adds unit tests covering both fixes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Linux-only failure in SaveSessionAsync_SanitizesInvalidPathCharactersAsync '?' is in Path.GetInvalidFileNameChars only on Windows, not on Linux/macOS, so the test failed on Ubuntu in CI. Use Path.GetInvalidFileNameChars()[0] (skipping NUL) to pick a guaranteed-invalid character for the running OS, and assert the result no longer contains it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address claude-opus-4.6 security/reliability review feedback WorkflowSession.cs: - ExecutorFailedEvent handler no longer leaks the internal executor ID in error messages. Mirror the WorkflowErrorEvent pattern: surface the exception's Message when _includeExceptionDetails is true, fall back to the generic 'An error occurred while executing the workflow.' otherwise. This also resolves the failing WorkflowHostSmokeTests assertions. FileSystemAgentSessionStore.cs: - GetSessionPath no longer has a write side effect. Directory.CreateDirectory for the per-agent bucket is now performed only on the SaveSessionAsync path, so a read miss on GetSessionAsync no longer leaves an empty directory on disk. - Adds GetSessionAsync_NoExistingFile_DoesNotCreateAgentDirectoryAsync to lock in the no-side-effect-on-read contract. OutputConverterTests.cs: - Strengthen ConvertUpdatesToEventsAsync_ToolApprovalRequest_NonFunctionToolCall_SkippedAsync to assert exactly one event (the terminal ResponseCompletedEvent) so a spurious output-item-added/-done leak would now fail the test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: clean up comments and rename TryParseArguments - Remove Python-codebase references from C# XML docs and inline comments. - Drop fix-history comments referring to previously-resolved issues. - Drop `Defense-in-depth:` prefixes; keep the concrete `what & why`. - Drop `previously we kept only the trailing message` comment in DeclarativeWorkflowExecutor; just describe current loop behavior. - Rename InputConverter.TryParseArguments to ParseFunctionArgumentsObject to make the intent obvious at the call site. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: collision-free Sanitize, MAF-style refactors - FileSystemAgentSessionStore.Sanitize now percent-encodes invalid chars (and `%` itself) instead of replacing them with `_`, eliminating collisions like `foo/bar` vs `foo_bar` mapping to the same bucket. All-dot segments encode every dot so Windows trailing-dot trimming cannot reintroduce a navigable name. - AddFoundryResponses XML doc updated to accurately describe the default store root (/.checkpoints when hosted, {cwd}/.checkpoints locally). - DeclarativeWorkflowExecutor.ConfigureChatProtocolRoutes now uses exact type equality instead of IsAssignableFrom so a broad TInput (e.g. object) does not skip registering IEnumerable<ChatMessage>, which ChatProtocolExtensions.IsChatProtocol requires verbatim. - SendActivityExecutor uses context.YieldOutputAsync(response) instead of manually constructing AgentResponseEvent, so the activity will participate in any future OutputFilter coverage. - WorkflowSession handles AgentResponseEvent in its own switch case, avoiding the second typecheck against output.Data. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(workflows): bridge declarative HITL through Foundry hosting via IExternalRequestEnvelope Introduce a new public interface IExternalRequestEnvelope in Microsoft.Agents.AI.Workflows that lets the runtime peek through a declarative-layer envelope without taking a circular reference back into the declarative package. ExternalInputRequest (declarative) implements it; ExternalInputResponse is constructed via the request's CreateResponse factory. WorkflowSession unwraps inner AIContent on the request side and rewraps the client's ChatMessage reply into an ExternalInputResponse on the response side. PortableValue cannot deserialize directly into an interface, so TryGetRequestEnvelope resolves the concrete type via RequestPortInfo.RequestType (TypeId -> Type.GetType) before casting. Public WorkflowHarness contract preserved: InvokeFunctionToolExecutor and WorkflowActionVisitor are unchanged from upstream, so public InvokeToolWorkflowTest scenarios continue to drive ExternalInputRequest / ExternalInputResponse directly through the harness. AgentFrameworkResponseHandler: skip prior conversation history replay when an existing session is being resumed (workflow checkpoint already holds the prior messages). WorkflowSession: when includeExceptionDetails is opted in, also unwrap DeclarativeActionException so HITL failures are debuggable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
69adf6d97e |
.NET: Fix off-thread RunStatus race where GetStatusAsync can return Running after ResumeAsync halts (#5412)
* Fix off-thread RunStatus race where GetStatusAsync can return Running after ResumeAsync halts * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Simplify test comment. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> |
||
|
|
267351b760 |
.NET: Expand Workflow Unit Test Coverage (#5390)
* refactor: remove dead code * refactor: remove ignore YieldsMessageAttribute - the correct one to use is YieldsOutputAttribute - fixes a comment that mistakenly refers to `.YieldsMessage()` which does not exist. * fix: ChatForwardingExecutor does not use correct role for string messages - make ChatForwardingExecutor use its configured role for string messages rather than always use ChatRole.User - add ChatForwardingExecutor tests * fixup: remove unused attribute * test: Add tests for failure when .AsAgent used on a non-ChatProtocol workflow * test: Add FunctionExecutor tests - also fixes Send and YieldOutput type registration for synchronous output-returning delegates * test: Suppress CodeCoverage for obsolete names * fix: Re-add Obsolete attributes - avoid hard-breaking change - properly notify users that these attributes get ignored |
||
|
|
d5777bc546 |
fix: Duplicate CallIds cause Handoff Message Filtering to fail (#5359)
Some providers, e.g. Gemini, do not use the CallId mechanism to disambiguate simultaneous function calls. This can result in message lists containing multiple turn to fail to filter properly. The fix is to take advantage of the expectation that Handoff Orchestration is a "single-speaker" flow, which only has a single active AIAgent per "turn" and an agent's turn is not finished until all outstanding function calls are finished. This allows us to expect that any ambiguous-CallId FunctionCallContent are either in separate turns or will have had a response before the next issued call with the same Id. |
||
|
|
5777ed26e6 |
.NET: fix: Add session support for Handoff-hosted Agents (#5280)
* fix: Add session support for Handoff-hosted Agents In order to better support using `Workflows` hosted as `AIAgents` inside of Handoff workflows, we need to make proper use of AgentSession. This causes potential issues around checkpointing and making sure that we properly compute only the new incoming messages for each agent invocation. * fix: AgentSession checkpointing using AIAgent's Serialize/Deserialize methods We cannot rely on implicit serialization through `HandoffHostState` because we are missing type information. * fix: Thread safety issue in `MultiPartyConversation.AllMessages` * fix: Enable unwrapping of FunctionResultContent when ExternalRequest was wrapped into FunctionCallContent |
||
|
|
dbf935b4e3 |
.NET: fix: Foundry Agents without description in Handoff (#5311)
* fix: Foundry Agents without description in Handoff Foundry Agents without a description set will return an empty string (rather than null) for the description. This was breaking the fallback logic for `handoffReason`. * test: Add unit tests |
||
|
|
aee1acbf8b |
.NET: Foundry Evals integration for .NET (#4914)
* Foundry Evals integration for .NET - Core evaluation framework: EvalItem, LocalEvaluator, FunctionEvaluator, EvalChecks - IAgentEvaluator interface with MeaiEvaluatorAdapter bridge - AgentEvaluationExtensions for agent.EvaluateAsync() overloads - FoundryEvals wrapping MEAI quality/safety evaluators - ConversationSplitters (LastTurn, Full) and IConversationSplitter - EvalItem.PerTurnItems() for multi-turn decomposition - HasImageContent for multimodal content detection - WorkflowEvaluationExtensions for per-agent workflow evaluation - 7 eval samples mirroring Python parity: 02-agents/Evaluation: SimpleEval, ExpectedOutputs, Multimodal 03-workflows/Evaluation: WorkflowEval 05-end-to-end/Evaluation: FoundryQuality, MixedProviders, ConversationSplits - Comprehensive unit tests (1958 passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rewrite FoundryEvals to use real Foundry Evals API Replace MEAI evaluator shim with actual OpenAI EvaluationClient protocol methods. FoundryEvals now creates eval definitions, submits runs, polls for completion, and fetches per-item results server-side. - New constructor: FoundryEvals(AIProjectClient, model, evaluators) - Add FoundryEvalConverter for MEAI ChatMessage -> Foundry JSON format - Add EvalId, RunId, ReportUrl to AgentEvaluationResults - All 20 built-in evaluator constants now work (agent, tool, quality, safety) - Remove Microsoft.Extensions.AI.Evaluation.Quality/Safety dependencies - Update all samples for new constructor (no more ChatConfiguration) - Replace BuildEvaluators tests with ResolveEvaluator tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add response output to CustomEvals and ExpectedOutputs samples Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review: pagination, validation, error handling, tests FoundryEvals fixes: - Add pagination for output items (has_more/after cursor) - Add guard clauses for pollIntervalSeconds/timeoutSeconds <= 0 - Fix double TryGetProperty for passed field parsing - Throw on all-tool-evaluators with no tool definitions - Fix XML doc (default 300s, not 180s) New tests (30 added, 1989 total): - EvalChecks: NonEmpty, ContainsExpected (pass/fail/skip/case), HasImageContent, ToolCallsPresent - FoundryEvalConverter: ConvertMessage (text, image, function call, function results fan-out, empty fallback, mixed content), ConvertEvalItem, BuildTestingCriteria (quality/agent/tool/groundedness data mappings), BuildItemSchema Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix review: null-refs, Data.ToString() bug, ContainsExpected, add tests - Fix NullReferenceException in sample Response display (pattern matching) - Fix WorkflowEvaluationExtensions Data?.ToString() producing type names instead of message text (pattern-match ChatMessage/AgentResponse/list) - Change EvalChecks.ContainsExpected to return Passed=false when no ExpectedOutput (was silently passing, masking misconfiguration) - Add EvalItem constructor tests with LastTurn/Full/null splitters - Add FoundryEvalConverter.ConvertMessage DataContent (base64 image) test - Add ExtractAgentData tests with ChatMessage, list, and AgentResponse data Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix review: conversation fidelity, eval caching, fallback tests - WorkflowEvaluationExtensions: preserve full response messages (tool calls, intermediate) instead of synthetic 2-message conversation. Cast completed Data to AgentResponse and use Messages when available, fallback to text. - FoundryEvals: cache evalId per schema shape (hasContext, hasTools) so subsequent EvaluateAsync calls create runs under the same eval definition. - MeaiEvaluatorAdapter: code already correctly passes queryMessages (not full conversation) to IEvaluator — no change needed, verified by inspection. - Add tests: AgentResponse full messages preservation, unknown object ToString() fallback for ExtractAgentData. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename AzureAI→Foundry: move eval files, update references - Move FoundryEvals.cs and FoundryEvalConverter.cs from Microsoft.Agents.AI.AzureAI to Microsoft.Agents.AI.Foundry - Update namespace from AzureAI to Foundry in both files - Add explicit usings required by Foundry project (no implicit usings) - Move FoundryEvalConverter tests to Foundry.UnitTests project (avoids ReplacingRedactor type conflict from dual project refs) - Update all sample csproj references and using statements - Remove Foundry project reference from AI UnitTests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * PR review round 4: wire up tool extraction, remove eval cache, fix null safety - BuildEvalItem: extract tools from agent via GetService<ChatOptions>() into EvalItem.Tools (Python parity) - FoundryEvals: remove eval ID cache - each call creates fresh definition (matches Python behavior) - FoundryEvals: replace null-forgiving operators with descriptive InvalidOperationException - MixedProviders sample: remove unnecessary explicit PackageReferences (transitively provided) - FoundryEvalConverter: document that tool results take precedence over text content - Add LocalEvaluator zero-checks test documenting 0 metrics = failed behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python-dotnet parity: 9 feature gaps filled New checks: - ToolCallArgsMatch() — verify tool call names + argument subset match - ToolCalledCheck(ToolCalledMode.Any, ...) — match any of the specified tools - ToolCalledMode enum (All/Any) FoundryEvals enhancements: - Default evaluators now [Relevance, Coherence, TaskAdherence] (was Relevance, Coherence) - Auto-add ToolCallAccuracy when items have tool definitions - EvaluateTracesAsync — evaluate by response_ids, trace_ids, or agent_id - EvaluateFoundryTargetAsync — evaluate deployed Foundry targets Result type enrichment: - AgentEvaluationResults: added Status, Error, PerEvaluator, DetailedItems - New EvalItemResult/EvalScoreResult/PerEvaluatorResult types - FoundryEvals populates all new fields from API responses Workflow fix: - Skip internal executors (_*, input-conversation, end-conversation, end) Tests: 8 new tests covering ToolCallArgsMatch, ToolCalledMode.Any, internal executor filtering Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add MeaiEvaluatorAdapter and PerTurnItems edge case tests - 3 tests for MeaiEvaluatorAdapter: query message forwarding, synthetic response fallback, multiple items aggregation - 3 tests for EvalItem.PerTurnItems: empty conversation, no user messages, system+assistant only - StubEvaluator and StubChatClient test helpers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Blocking link check for outdated package in DevUI. * Replace Dictionary<string, object> payloads with typed wire models Introduce internal FoundryEvalWireModels.cs with compile-time-safe types for the OpenAI Evals API wire format. The OpenAI .NET SDK (2.9.1) only provides protocol-level methods with BinaryContent/ClientResult — no typed request models. These internal models replace scattered dictionary literals with [JsonPropertyName]-annotated classes, giving: - Compile-time safety (typos become build errors) - Single point of change when the API evolves - IntelliSense discoverability - Cleaner serialization via JsonPolymorphic for content items Models: WireContentItem hierarchy (text, image, tool_call, tool_result), WireMessage, WireEvalItemPayload, WireTestingCriterion, WireItemSchema, WireCreateEvalRequest, WireCreateRunRequest, and data source variants. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Skip metric when Foundry returns neither score nor passed When an evaluator returns no score and no passed value, the previous code created BooleanMetric(name, false), which falsely failed items via ItemPassed. Now we skip the MEAI metric entirely for indeterminate results — the raw data remains available in DetailedItems for diagnostics. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #4914 review comments: fix tool evaluator bug and add tests - Fix duplicate ToolCallAccuracy: resolve evaluator names before checking against ToolEvaluators set (Comment 2) - Make FilterToolEvaluators internal for testability; add tests for the ArgumentException edge case when all evaluators are tool-type (Comment 3) - Add CancellationToken test for LocalEvaluator (Comment 4) - Add EvaluateAsync integration test on Run with sequential workflow and per-agent SubResults verification (Comment 5) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address Peter's review comments on PR #4914 - Add trailing newline to Evaluation_FoundryQuality.csproj (Comment 6) - Make evaluator name lookups case-insensitive: switch BuiltinEvaluators, ToolEvaluators, AgentEvaluators, and ResolveEvaluator's StartsWith check from Ordinal to OrdinalIgnoreCase (Comment 7) - Add Trace.TraceWarning when Foundry returns fewer results than submitted items, indicating expected vs actual count before padding (Comment 8) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add Microsoft.Extensions.AI.Evaluation packages to Directory.Packages.props These were removed in #5269 as unused, but are needed by the Foundry and core evaluation integration added in this PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
87a8fa2a9d |
.NET: Fix intermittent checkpoint-restore race in in-process workflow runs (#5134)
* Improve workflow unit tests * Update test name prefix for clarity. * Update tests to surface any errors. * fix check-point restore-time race in off-thread workflow event stream * Fixes an intermittent checkpoint-restore race in in-process workflow runs. |
||
|
|
76fe7319e0 |
.NET: feat: Refactor Handoff Orchestration and add HITL support (#5174)
* feat: Refactor Handoff Orchestration and add HITL support * Change HandoffAgentExecutor to use factory-based instantiation * Extract shared request collection logic in AIAgentUnservicedRequestsCollector * Refactor HandoffAgentExecutor to use the "ContinueTurn" pattern as in AIAgentHostExecutor * fix: Remove '$' from exception strings |
||
|
|
79afda1a6c | Samples fixes (#5169) | ||
|
|
d30103fee6 |
.NET: Fix input signal issue during checkpoint restoration (#5085)
* Improve workflow unit tests * Update test name prefix for clarity. * Update tests to surface any errors. * fix check-point restore-time race in off-thread workflow event stream |
||
|
|
55ae57c0ed |
.NET: Add Message Delivery Callback Overloads to Executor (#5081)
* feat: Implement Executor Message Delivery Event callbacks * fix: ResumeAsync does not run pending steps * fix: address review comments |
||
|
|
c798cb7a2e | release: Mark Handoff Orchestrations Experimental (#5065) | ||
|
|
524c0216e4 |
.NET: Update release versions (#5059)
* Update release versions * Fix versioning issue * Change ga wording to released * Update suppression file * Remove unecessary workflows suppression file * Remove another unnecessary suppression file. * Fix suppressions file |
||
|
|
281661e409 |
.NET: Remove timeout from InputWait in OffThread execution (#4996)
* fix: Remove Timeout from InputWait in StreamingRunEventStream * fix: Race condition when the workflow executes to halt before TakeEventStream * test: Make the OffThread Delay test more nimble * fix: Remove slight window where runStatus could be stale |
||
|
|
38de991481 |
.NET: Fix RequestInfoEvent lost when resuming workflow from checkpoint (#4955)
* Fix RequestInfoEvent lost when resuming workflow from checkpoint * Fix streaming run double disposal in tests and lockstep republishing before Started event is emitted. * Fix bug to remove messages after sending to avoid losing messages on send failure. * Fix declarative test harness |
||
|
|
18f7ba8632 |
.NET: Add API breaking change validation for RC packages (#4977)
* Add API breaking change validation for RC packages Enable .NET Package Validation for release candidate packages to detect API breaking changes in CI. This follows the same pattern used by Semantic Kernel, centralized through nuget-package.props. Changes: - Enable EnablePackageValidation for IsReleaseCandidate packages - Update PackageValidationBaselineVersion to 1.0.0-rc4 (latest published) - Generate CompatibilitySuppressions.xml for existing known API changes in 5 packages (AI, AzureAI, OpenAI, Workflows, Workflows.Declarative.AzureAI) - Opt out Workflows.Declarative.Mcp (not yet published to NuGet) - Add breaking changes guidance to CONTRIBUTING.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review feedback - Remove unnecessary empty PackageValidationBaselineVersion override in Workflows.Declarative.Mcp.csproj (EnablePackageValidation=false is sufficient) - Tighten CONTRIBUTING.md wording to clarify opt-out possibility Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Enable package validation for GA packages (no VersionSuffix) Expand the EnablePackageValidation condition to also cover future GA packages that have no VersionSuffix, not just RC packages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix EnablePackageValidation GA condition to check PackageVersion The previous condition VersionSuffix=='' matched all packages (preview included) since VersionSuffix defaults to empty. Now uses two separate conditions: one for RC, one for true GA (PackageVersion == VersionPrefix). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add IsGeneralAvailable flag for package validation Replace fragile PackageVersion condition with explicit IsGeneralAvailable property, following the same per-project self-declaration pattern as IsReleaseCandidate. - Directory.Build.props: Add IsGeneralAvailable=false default - nuget-package.props: EnablePackageValidation on RC OR GA - CONTRIBUTING.md: Update docs to mention both flags When packages go GA, they set IsGeneralAvailable=true in their .csproj. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename IsGeneralAvailable to IsGenerallyAvailable Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
5530bc536b |
.NET: feat: Implement return-to-previous routing in handoff workflow (#4356)
* feat: Implement return-to-previous routing in handoff workflow - Also obsoletes HandoffsWorkflowBuilder => HandoffWorkflowBuilder (no "s") * refactor: Remove instance-shared current agent tracking in handoffs Because the tracker was instance-shared between the start and end executors, it would be shared between all sessions, resulting in incorrect behaviour. The corect way to do this is to keep the data in a shared executor scope, which is per-session. * fix: Fix test logic for Handoff to correctly use checkpointing for multiturn |
||
|
|
0bdcaa5c07 | fix: Re-enable the "retrieve object" check in StateManager (#1881) | ||
|
|
35f44e854e |
.NET: fix: HandoffAgentExecutor does not output any response when non-streaming (#4745)
* fix: HandoffAgentExecutor does not output any reponse when non-streaming * fix: Ensure Workflow outputs persisted in chat history when hosted AsAgent * fix: Remove duplicate history entry creation and ad test * test: Add streaming tests for AsAgent to smoke tests * feat: Add output configurability to Handoffs |
||
|
|
0756c45702 |
.NET: [BREAKING] Update type names and source generator to reduce conflicts (#4903)
* refactor: [BREAKING] Config => ExecutorConfig Make the Config name less likely to collide with other classes by renaming to ExecutorConfig. Makes Configured and related classes internal as they do not need to be part of the public surface. * fix: Make RouteBuilder explicit in SourceGen to avoid conflicts |
||
|
|
23921c0f6e |
.NET: Pass through external input request and handle response conversion for workflow as agent scenario (#4361)
* Handle external input request and response conversion for workflow as agent scenario * Remove unnecessary test comment * Fix PR comments * Updated to fix edge cases, and add more tests. * Update pending requests to use typed properties instead of relying on StateBag. replying to PR feedback. * Fixed external response de-dup and updated possible brittle test. * Address PR comments on sending turn token for normal messages and handle contentId collision by source agent * Remove unnecessary serialization element and address pr comment on intercepted outgoing requests * Updated MEAI changes for UserInput request and response abstractions. |
||
|
|
a9db40886e |
fix: FS Checkpoint storage special character support (#4730)
The `sessionId`, an optional parameter when starting a new session when running a workflow is an arbitrary string. This allows consumers to support whatever ids are needed by other systems, but can result in errors when an OS special or forbidden character is included. The fix is to escape the paths, in a 1:1 manner. We rely on EncodeDataString to do this. * Also modifies the index file to make it easier to determine what the name of the file on disk is for a given `sessionId`. |
||
|
|
88ea9d08c7 |
.NET: Update to OpenAI 2.9.1, Azure.AI.OpenAI 2.9.0-beta.1, Microsoft.Extensions.AI 10.4.0, and Azure.AI.Projects 2.0.0-beta.2 (#4613)
* Initial plan * Update code for Microsoft.Extensions.AI.Abstractions 10.4.0 breaking changes - Rename FunctionApprovalRequestContent → ToolApprovalRequestContent - Rename FunctionApprovalResponseContent → ToolApprovalResponseContent - Rename UserInputRequestContent → ToolApprovalRequestContent - Rename UserInputResponseContent → ToolApprovalResponseContent - Update .FunctionCall property → .ToolCall with FunctionCallContent casts where needed - Update .Id property → .RequestId on the renamed types - Rename FunctionApprovalRequestEventGenerator → ToolApprovalRequestEventGenerator - Rename FunctionApprovalResponseEventGenerator → ToolApprovalResponseEventGenerator Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update OpenAI 2.9.1, ME.AI 10.4.0, fix breaking API changes Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> * Fix remaining ME.AI 10.4.0 breaking changes: MCP approval types, .Output→.Outputs Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> * Use pattern matching with `when` for ToolApprovalRequestContent/FunctionCallContent Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> * Update Azure.AI.OpenAI to 2.9.0-beta.1 Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> * Fix remaining GetResponsesClient(model) build failures for Azure.AI.OpenAI 2.9.0-beta.1 Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> * Address review feedback: remove redundant type checks in TestRequestAgent.cs and fix error message in AIAgentHostExecutor.cs Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> * Update Azure.AI.Projects to 2.0.0-beta.2 with namespace migration - Azure.AI.Projects 2.0.0-beta.1 → 2.0.0-beta.2 - Azure.AI.Projects.OpenAI → Azure.AI.Extensions.OpenAI (transitive) - Agent types moved to Azure.AI.Projects.Agents namespace - AgentRecord.Versions.Latest → AgentRecord.GetLatestVersion() - OpenAPIFunctionDefinition → OpenApiFunctionDefinition - BingCustomSearchToolParameters → BingCustomSearchToolOptions - MemorySearchPreviewTool.UpdateDelay → UpdateDelayInSecs - Azure.Identity 1.17.1 → 1.19.0 - Microsoft.Identity.Client.Extensions.Msal 4.78.0 → 4.83.1 Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com> * Fix remaining type renames for Azure.AI.Projects 2.0.0-beta.2 - BrowserAutomationToolParameters → BrowserAutomationToolOptions - MemoryUpdateOptions.UpdateDelay stays as UpdateDelay (not renamed) - WaitForMemoriesUpdateAsync parameter order: pollingInterval before options - AIProjectAgentsOperations → AgentsClient Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com> * Fix format errors and OpenTelemetry test for ME.AI 10.4.0 - Remove unused 'using Azure.AI.Extensions.OpenAI' and fix import ordering in Agent_With_AzureAIProject/Program.cs - Update OpenTelemetryAgentTests: gen_ai.tool.definitions is now always emitted regardless of EnableSensitiveData per ME.AI 10.4.0 change (dotnet/extensions#7346). Tool definitions are not considered sensitive. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix GetRepoFolder() to work in git worktrees Use 'workflow-samples' directory as repo root marker instead of '.git', which fails in worktrees (.git is a file) and also matches too early when a '.github' folder exists in subdirectories. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix formatting: remove unused usings and fix import ordering dotnet format applied across 59 impacted projects. Primarily removes unnecessary 'using Azure.AI.Projects' where Azure.AI.Projects.Agents provides all needed types, and fixes import ordering per editorconfig. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Disable AzureAIAgentsPersistent integration tests (#4769) Azure.AI.Agents.Persistent 1.2.0-beta.9 references McpServerToolApprovalResponseContent which was removed in ME.AI 10.4.0 (renamed to ToolApprovalResponseContent), causing TypeLoadException at runtime. Mark all 6 test classes with IntegrationDisabled trait until Persistent ships a version targeting ME.AI 10.4.0+. Upstream fix: https://github.com/Azure/azure-sdk-for-net/pull/56929 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add README with compatibility note for AzureAI.Persistent (#4769) Documents that Azure.AI.Agents.Persistent 1.2.0-beta.9 is only compatible with ME.AI ≤10.3.0 and OpenAI ≤2.8.0 due to type renames in ME.AI 10.4.0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix file encoding: restore UTF-8 BOM on Persistent test files Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Mark AzureAI.Persistent as IsPackable=false (#4769) Prevent shipping until Azure.AI.Agents.Persistent targets ME.AI 10.4.0+. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Moving IsPackable after import --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com> |
||
|
|
c74b1b08eb |
.NET: Fix race condition issue in FanInEdge while processing messages. (#4662)
* Fix race condition issue in FanInEdge while processing messages. * refactored to limit the code segment under lock. * Remove extra materialization of the result. * Added comment to clarify future changes if process message is made async. |
||
|
|
cbcdb2d29e |
.NET: Add durable workflow support (#4436)
* .NET: [Feature Branch] Add basic durable workflow support (#3648) * Add basic durable workflow support. * PR feedback fixes * Add conditional edge sample. * PR feedback fixes. * Minor cleanup. * Minor cleanup * Minor formatting improvements. * Improve comments/documentation on the execution flow. * .NET: [Feature Branch] Add Azure Functions hosting support for durable workflows (#3935) * Adding azure functions workflow support. * - PR feedback fixes. - Add example to demonstrate complex Object as payload. * rename instanceId to runId. * Use custom ITaskOrchestrator to run orchestrator function. * .NET: [Feature Branch] Adding support for events & shared state in durable workflows (#4020) * Adding support for events & shared state in durable workflows. * PR feedback fixes * PR feedback fixes. * Add YieldOutputAsync calls to 05_WorkflowEvents sample executors The integration test asserts that WorkflowOutputEvent is found in the stream, but the sample executors only used AddEventAsync for custom events and never called YieldOutputAsync. Since WorkflowOutputEvent is only emitted via explicit YieldOutputAsync calls, the assertion would fail. Added YieldOutputAsync to each executor to match the test expectation and demonstrate the API in the sample. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix deserialization to use shared serializer options. * PR feedback updates. * Sample cleanup * PR feedback fixes * Addressing PR review feedback for DurableStreamingWorkflowRun - Use -1 instead of 0 for taskId in TaskFailedException when task ID is not relevant. - Add [NotNullWhen(true)] to TryParseWorkflowResult out parameter following .NET TryXXX conventions. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: [Feature Branch] Add nested sub-workflow support for durable workflows (#4190) * .NET: [Feature Branch] Add nested sub-workflow support for durable workflows * fix readme path * Switch Orchestration output from string to DurableWorkflowResult. * PR feedback fixes * Minor cleanup based on PR feedback. * .NET: [Feature Branch] Add Human In the Loop support for durable workflows (#4358) * Add Azure Functions HITL workflow sample Add 06_WorkflowHITL Azure Functions sample demonstrating Human-in-the-Loop workflow support with HTTP endpoints for status checking and approval responses. The sample includes: - ExpenseReimbursement workflow with RequestPort for manager approval - Custom HTTP endpoint to check workflow status and pending approvals - Custom HTTP endpoint to send approval responses via RaiseEventAsync - demo.http file with step-by-step interaction examples * PR feedback fixes * Minor comment cleanup * Minor comment clReverted the `!context.IsReplaying` guards on `PendingEvents.Add`/`RemoveAll` and `SetCustomStatus` in `ExecuteRequestPortAsync`. The guards broke fan-out scenarios where parallel RequestPorts need to be discoverable after replay. `SetCustomStatus` is idempotent metadata that doesn't affect replay determinism.eanup * fix for PR feedback * PR feedback updates * Improvements to samples * Improvements to README * Update samples to use parallel request ports. * Unit tests * Introduce local variables to improve readability of Workflows.Workflows access patter * Use GitHub-style callouts and add PowerShell command variants in HITL sample README * Add changelog entries for durable workflow support (#4436) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump Microsoft.DurableTask.Worker to 1.19.1 to fix version downgrade Microsoft.Azure.Functions.Worker.Extensions.DurableTask 1.13.1 requires Microsoft.DurableTask.Worker >= 1.19.1 via its transitive dependency on Microsoft.DurableTask.Worker.Grpc 1.19.1. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix broken markdown links in durable workflow sample READMEs - Create Workflow/README.md with environment setup docs - Fix ../README.md -> ../../README.md in ConsoleApps 01, 02, 03, 08 - Fix SubWorkflows relative path (3 levels -> 4 levels up) - Fix dead Durable Task Scheduler URL Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix build errors from main merge: Throw conflict, ExecuteAsync rename, GetNewSessionAsync rename - Remove InjectSharedThrow from DurableTask csproj (uses Workflows' internal Throw via InternalsVisibleTo) - Update ExecuteAsync -> ExecuteCoreAsync with WorkflowTelemetryContext.Disabled - Update GetNewSessionAsync -> CreateSessionAsync Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Move durable workflow samples to 04-hosting/DurableWorkflows Aligns with main branch sample reorganization where durable samples live under 04-hosting/ (alongside DurableAgents/). - Move samples/Durable/Workflow/ -> samples/04-hosting/DurableWorkflows/ - Add Directory.Build.props matching DurableAgents pattern - Update slnx project paths - Update integration test sample paths - Update README cd paths and cross-references Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix build errors: remove duplicate base class members, update renamed APIs - Remove duplicate OutputLog, WriteInputAsync, CreateTestTimeoutCts, etc. from ConsoleAppSamplesValidation (already in SamplesValidationBase) - Update AddFanInEdge -> AddFanInBarrierEdge in workflow samples - Update GetNewSessionAsync -> CreateSessionAsync in workflow samples - Update SourceId -> ExecutorId (obsolete) in workflow samples Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix dotnet format issues: add UTF-8 BOM and remove unused using - Add UTF-8 BOM to 20 .cs files across DurableTask, AzureFunctions, unit tests, and workflow samples - Remove unnecessary using directive in 07_SubWorkflows/Executors.cs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix typo PaymentProcesser -> PaymentProcessor and garbled arrows in README Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix GetExecutorName to handle agent names with underscores Split on last underscore instead of first, and validate that the suffix is a 32-char hex string (sanitized GUID) before stripping it. This prevents truncation of agent names like 'my_agent' when the executor ID is 'my_agent_<guid>'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Align DurableTask.Client.AzureManaged to 1.19.1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump DurableTask and Azure Functions extension package versions - DurableTask.* packages: 1.19.1 -> 1.22.0 - Functions.Worker.Extensions.DurableTask: 1.13.1 -> 1.16.0 - Functions.Worker.Extensions.DurableTask.AzureManaged: 1.0.1 -> 1.5.0 (telemetry bug fix) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump DurableTask SDK packages to 1.22.0 - DurableTask.Client: 1.19.1 -> 1.22.0 - DurableTask.Client.AzureManaged: 1.19.1 -> 1.22.0 - DurableTask.Worker: 1.19.1 -> 1.22.0 - DurableTask.Worker.AzureManaged: 1.19.1 -> 1.22.0 - Azure Functions extensions kept at original versions (1.13.1/1.0.1) due to host-side DurableTask.Core 3.7.0 incompatibility with newer extensions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update Microsoft.Azure.Functions.Worker.Extensions.DurableTask to "1.16.0" * Add the local.settings.json files to the sample which were previously ignored. This aligns with our other samples. * Increase timeout for tests as CI has them failing transiently. * increaset timeout value for azure functions integration tests. * Add YieldsOutput(string) to workflow shared state sample executors ValidateOrder and EnrichOrder call YieldOutputAsync with string messages, but only their TOutput (OrderDetails) was in the allowed yield types. This caused TargetInvocationException in the WorkflowSharedState sample validation integration test. * Downgrade the durable packages to 1.18.0 * Downgrading Worker.Extensions.DurableTask to 1.12.1 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
aa2ff672fb |
.NET: Fix to emit WorkflowStartedEvent during workflow execution (#4514)
* Fix bug to emit WorkflowStartedEvent during workflow execution * Updated based on PR comments |
||
|
|
2f8fd5f82f |
.NET: Add FinishReason to AgentResponses (#4617)
* Add FinishReason to AgentResponses * Address PR comments |
||
|
|
a3bfad4791 |
.NET: Added support for polymorphic type as workflow output (#4485)
* Added support for polymorphic type as workflow output * Update Linq expression to avoid unnecessary allocations. * Added caching as per PR comment |
||
|
|
d5da6e05d8 |
.NET: [BREAKING] Change *Provider StateKey to list of StateKeys (#4395)
* Change *Provider StateKey to list of StateKeys * Add more statekey validation tests * Address PR comments |
||
|
|
945933c351 |
[BREAKING] Add response filter for store input in *Providers (#4327)
* Add response filter for store input for *Providers * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Address feedback * Apply suggestions from code review Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> |
||
|
|
d932947ba5 | Add Name and Description support for GroupChat workflow builder (#4334) | ||
|
|
db48f8ce09 |
.NET: Fixing issue with invalid node Ids when visualizing dotnet workflows. (#4269)
* Fix Mermaid rendering errors in WorkflowVisualizer.ToMermaidString Fix two bugs in the Mermaid diagram output: 1. Use safe node aliases (node_0, node_1, ...) instead of raw executor IDs as Mermaid node identifiers. Raw IDs containing spaces, dots, or non-ASCII characters (e.g. Japanese) caused Mermaid parse errors. 2. Fix conditional edge arrow syntax from '.--> ' (invalid) to '.-> ' (valid Mermaid dotted arrow syntax). Fixes #1406 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Use recognizable sanitized IDs for Mermaid node identifiers\n\nReplace generic node_0/node_1 aliases with IDs derived from the original\nexecutor names. ASCII letters, digits, and underscores are preserved;\nother characters become underscores (collapsed, trimmed). Leading digits\nget an n_ prefix. Collisions are resolved with a numeric suffix.\n\nThis keeps node IDs readable in the Mermaid source while the display\nlabels continue to show the full original names." * Remove issue number references from test names and comments" * Address PR review feedback from Copilot\n\n- Add Throw.IfNull(id) guard to SanitizeMermaidNodeId\n- Add safety limit (10,000) to collision resolution loop\n- Restore missing edge assertions (middle1/middle2 --> end)\n- Fix comment to show actual sanitized ID (n_1_User_input)\n- Use stricter regex in Unicode test (must start with letter/underscore)" * Address second round of PR review feedback\n\n- Escape node display labels via EscapeMermaidLabel to handle quotes,\n brackets, and newlines in executor IDs\n- Fix XML doc on SanitizeMermaidNodeId to accurately describe that\n existing consecutive underscores in input are preserved\n- Restore specific edge assertion (mid --> end) in conditional edge test\n- Restore fan-in routing assertions (s1/s2 through intermediate node,\n no direct edges to t) in fan-in test" --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
425f27f989 |
.NET: Fixing issue where OpenTelemetry span is never exported in .NET in-process workflow execution (#4196)
* 1. Add reproduction test for issue #4155: workflow.run Activity never stopped in streaming OffThread path The WorkflowRunActivity_IsStopped_Streaming_OffThread test demonstrates that the workflow.run OpenTelemetry Activity created in StreamingRunEventStream.RunLoopAsync is started but never stopped when using the OffThread/Default streaming execution. The background run loop keeps running after event consumption completes, so the using Activity? declaration never disposes until explicit StopAsync() is called. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> 2. Fix workflow.run Activity never stopped in streaming OffThread execution (#4155) The workflow.run OpenTelemetry Activity in StreamingRunEventStream.RunLoopAsync was scoped to the method lifetime via 'using'. Since the run loop only exits on cancellation, the Activity was never stopped/exported until explicit disposal. Fix: Remove 'using' and explicitly dispose the Activity when the workflow reaches Idle status (all supersteps complete). A safety-net disposal in the finally block handles cancellation and error paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add root-level workflow.session activity spanning run loop lifetime\n\nImplements two-level telemetry hierarchy per PR feedback from lokitoth:\n- workflow.session: spans the entire run loop / stream lifetime\n- workflow_invoke: per input-to-halt cycle, nested within the session\n\nThis ensures the session activity stays open across multiple turns,\nwhile individual run activities are created and disposed per cycle.\n\nAlso fixes linkedSource CancellationTokenSource disposal leak in\nStreamingRunEventStream (added using declaration)." * Address Copilot review: fix Activity/CTS disposal, rename activity, add error tag\n\n1. LockstepRunEventStream: Remove 'using' from Activity in async iterator\n and manually dispose in finally block (fixes #4155 pattern). Also dispose\n linkedSource CTS in finally to prevent leak.\n2. Tags.cs: Add ErrorMessage (\"error.message\") tag for runtime errors,\n distinct from BuildErrorMessage (\"build.error.message\").\n3. ActivityNames: Rename WorkflowRun from \"workflow_invoke\" to \"workflow.run\"\n for cross-language consistency.\n4. WorkflowTelemetryContext: Fix XML doc to say \"outer/parent span\" instead\n of \"root-level span\".\n5. ObservabilityTests: Assert WorkflowSession absence when DisableWorkflowRun\n is true.\n6. WorkflowRunActivityStopTests: Fix streaming test race by disposing\n StreamingRun before asserting activities are stopped.\n7. StreamingRunEventStream/LockstepRunEventStream: Use Tags.ErrorMessage\n instead of Tags.BuildErrorMessage for runtime error events." * Review fixes: revert workflow_invoke rename, use 'using' for linkedSource, move SessionStarted earlier\n\n- Revert ActivityNames.WorkflowRun back to \"workflow_invoke\" (OTEL semantic convention contract)\n- Use 'using' declaration for linkedSource CTS in LockstepRunEventStream (no timing sensitivity)\n- Move SessionStarted event before WaitForInputAsync in StreamingRunEventStream to match Lockstep behavior" * Improve naming and comments in WorkflowRunActivityStopTests" * Prevent session Activity.Current leak in lockstep mode, add nesting test Save and restore Activity.Current in LockstepRunEventStream.Start() so the session activity doesn't leak into caller code via AsyncLocal. Re-establish Activity.Current = sessionActivity before creating the run activity in TakeEventStreamAsync to preserve parent-child nesting. Add test verifying app activities after RunAsync are not parented under the session, and that the workflow_invoke activity nests under the session." * Fix stale XML doc: WorkflowRun -> WorkflowInvoke in ObservabilityTests --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |