Commit Graph

122 Commits

  • .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
  • 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.
  • .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>
  • .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>
  • .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>
  • .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
  • 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.
  • .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
  • .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
  • .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>
  • .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.
  • .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
  • .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
  • .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
  • .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
  • .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
  • .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
  • .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>
  • .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
  • .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
  • .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
  • .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.
  • 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`.
  • .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>
  • .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.
  • .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>
  • .NET: Fix to emit WorkflowStartedEvent during workflow execution (#4514)
    * Fix bug to emit WorkflowStartedEvent during workflow execution
    
    * Updated based on PR comments
  • .NET: Add FinishReason to AgentResponses (#4617)
    * Add FinishReason to AgentResponses
    
    * Address PR comments
  • .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
  • .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
  • [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>
  • .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>
  • .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>
  • .NET: [BREAKING] Workflows API Review Naming Changes (Part 1?) (#4090)
    * refactor: Normalize Run/RunStreaming with AIAgent
    
    * refactor: Clarify Session vs. Run -level concepts
    
    * Rename RunId to SessionId to better match Run/Session terminology in AIAgent
    * [BREAKING]: Will break existing checkpointed sessions in CosmosDb due to field rename
    
    * refactor: Rename and simplify interface around getting typed data out of ExternalRequest/Response
    
    * Also adds hints around using value types in PortableValue
    
    * refactor: Rename AddFanInEdge to AddFanInBarrierEdge
    
    This will prevent a breaking change later when we introduce a programmable FanIn edge, analogous to the FanOut edge's EdgeSelector.
    
    The goal, in the long run is to support a number of different FanIn scenarios, with naive FanIn (no barrier) by default, similar to FanOut.
    
    * refactor: AsAgent(this Workflow, ...) => AsAIAgent(...)
    
    * misc - part1: SwitchBuilder internal
    
    ---------
    
    Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
  • .NET: Remove FunctionCalls and Tool Messages from Handoff passed messages (#3811)
    * Fix handoff orchestration not passing user message to handoff target agent (#3161)
    
    Filter out internal handoff function call and tool result messages before
    passing conversation history to the target agent's LLM. These messages
    confused the model into ignoring the original user question.
    
    * Add handoff tool call filtering behavior and enhance workflow builder
    
    - Introduced HandoffToolCallFilteringBehavior enum to specify filtering behavior for tool call contents in handoff workflows.
    - Updated HandoffsWorkflowBuilder to support customizable handoff instructions and tool call filtering behavior.
    - Enhanced HandoffAgentExecutor to utilize new filtering options for improved message handling during agent handoffs.
    
    * Enhance handoff message filtering logic and add unit tests for filtering behaviors
    
    * Refactor HandoffMessagesFilter to remove unused handoff function names and enhance filtering logic for non-handoff function calls
    
    * Refactor HandoffMessagesFilter to streamline FilterCandidateState initialization and improve clarity
    
    * Refactor HandoffMessagesFilter to improve filtering logic and add integration tests for handoff workflows
    
    * fix: HandoffAgentExecutor tests
  • .NET: Updated package versions for RC release (#4067)
    * Updated package versions for RC release
    
    * Resolved comment
    
    * Resolved comments
  • [BREAKING] .NET: Decouple Checkpointing from Run/StreamAsync APIs (#4037)
    * [BREAKING] refactor: Decouple Checkpointing and Execution APIs
    
    With this change, Checkpointing becomes an property of an IWorkflowExecutionEnvironment. This lets environments that are tightly-coupled to their CheckpointManager avoid needing to present APIs that would not work (e.g. taking in an InMemory CheckpointManager for Durable Tasks, for example)
    
    * refactor: Normalize IsCheckpointingEnabled naming
  • Fix CheckpointInfo.Parent always null in InProcessRunner (#3796) (#3812)
    Track the last CheckpointInfo in InProcessRunner so that newly created
    checkpoints reference their parent. When resuming from a checkpoint,
    the resumed-from checkpoint becomes the parent of the next checkpoint.
    
    Adds tests verifying:
    - First checkpoint has null parent
    - Subsequent checkpoints chain parents correctly
    - Checkpoint after resume references the resumed-from checkpoint
  • .NET: [BREAKING] Implement Polymorphic Routing (#3792)
    * feat: Implement Polymorphic Routing
    
    * feat: Add support for Send/Yield annotations with basic Executor
    
    * Adds annotations to Declarative workflow executors
    
    * fix: Address PR Comments
    
    * Implicit filter in collection loops
    * Remove debug / usused / superfluous code
    * Fix ProtocolBuilder implicit output registrations
    * Fix logic error in ExecuteRouteGeneratorTests.ClassWithManualConfigureProtocol_DoesNotGenerate
    
    * fix: Solidify type checks and send/yield type registrations
    
    * fix: Suppress generation of TurnTokens out of AggregateTurnMessagesExecutor
    
    * Fixes an issue where ConcurrentEndExecutor is not expecting TurnTokens.
    
    * fix: Add ProtocolBuilder support for chained-delegation
    
    * Updates Declarative pacakge to rely on chained-delegation Send/Yield registration
    * Renames DeclarativeActionExectuor's new ExecuteAsync to ExecuteActionAsync to avoid colliding with Executor.ExecutoeAsync
    
    * fix: Address PR Comments
    
    * Fixes type mapping in FanInEdgeRunner
    * Fixes and expalins send/yield type registration in FunctionExecutor
    
    * fixup: build-break
    
    * fix: Add missing SendsMesage declaration to InvokeAzureAgentExecutor
  • .NET: BREAKING: Unify AgentResponse[Update] events as WorkflowOutputEvents (#3441)
    * Rename WorkflowOutputEvent.SourceId to ExecutorId for Python consistency
    
    - Rename SourceId property to ExecutorId in WorkflowOutputEvent
    - Add [Obsolete] SourceId property for backward compatibility
    - Update all test usages to use ExecutorId
    
    Resolves part of #2938
    
    * Unify AgentResponse events with WorkflowOutputEvent (#2938)
    
    - Change AgentResponseEvent and AgentResponseUpdateEvent to inherit from
      WorkflowOutputEvent instead of ExecutorEvent
    - Update AIAgentHostExecutor and HandoffAgentExecutor to use YieldOutputAsync()
      instead of AddEventAsync() for agent outputs
    - Add special-casing in InProcessRunnerContext.YieldOutputAsync() to create
      specific event types for AgentResponse and AgentResponseUpdate, bypassing
      OutputFilter for backwards compatibility
    - Update TestRunContext and TestWorkflowContext with same special-casing
    - Add regression tests in AgentEventsTests
    
    * refactor: Seal AgentResponse events
  • .NET: Improve session cast error message quality and consistency (#3973)
    * Improve session cast error messge consistency
    
    * Update changelog
  • .NET: [BREAKING] Refactor providers to move common functionality to base (#3900)
    * Move common functionality to provider base classes
    
    Co-Authored-By: Copilot <175728472+Copilot@users.noreply.github.com>
    
    * Address PR comments.
    
    ---------
    
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
  • .NET: [BREAKING] Add session StateBag for state storage and support multiple providers on the Agent (#3806)
    * .NET: [BREAKING] Add session statebag to use for state storage instead of inside providers (#3737)
    
    * Add a StateBag to AgentSession and pass Agent and AgentSession to AIContextProvider and ChatHistoryProviders
    
    * Convert all AIContextProviders to use the statebag
    
    * Update InMemoryChatHistoryProvider to use StateBag
    
    * Update Comsos and Workflow ChatHistoryProviders
    
    * Update 3rd party chat history storage sample.
    
    * Remove serialize method from providers
    
    * Replacing provider factories with properties
    
    * Remove Providers from Session and flatten state bag serialization
    
    * Update samples to use getservice on agent
    
    * Updated additional session types to serialize statebag
    
    * Fix regression
    
    * Address PR comments
    
    * Address PR comments.
    
    * Fix formatting
    
    * Fix unit tests
    
    * Remove InMemoryAgentSession since it is not required anymore.
    
    * Address PR comments
    
    * Convert sessions for A2AAgent, ChatClientAgent, CopilotStudioAgent and GithubCopilotAgent to use regular json serialization.
    
    * Fix durable agent session jso usgae
    
    * Add jso to InMemory and Workflow ChatHistoryProviders
    
    * Update InMemoryChatHistoryProvider to use an options class for it's many optional settings.
    
    * Apply suggestions from code review
    
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
    
    * Address PR feedback
    
    * Fix verification bug.
    
    * Improve state bag thread safety
    
    * Address PR comments and fix unit tests
    
    * Address PR comments
    
    * Fix unit test
    
    ---------
    
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
    
    * Add a public StateKey property to providers (#3810)
    
    * .NET: [BREAKING] Update providers in such a way that they can participate in a pipeline (#3846)
    
    * Make providers pipeline capable
    
    * Fix unit tests
    
    * Move source stamping to providers from base class
    
    * Also update samples.
    
    * Address PR comments
    
    * Rename AsAgentRequestMessageSourcedMessage to WithAgentRequestMessageSource
    
    * .NET: [BREAKING] Add consistent message filtering to all providers. (#3851)
    
    * Add consistent message filtering to all providers.
    
    * Remove old chat history filtering classes
    
    * Fix merge issues
    
    * Fix unit test
    
    * Enforce non-nullable property
    
    * Fix merging bug and make troubleshooting source info easier by adding tostring implementation
    
    * .NET: [BREAKING] Add support for multiple AIContextProviders on a ChatClientAgent (#3863)
    
    * Add support for multiple AIContextProviders on a ChatClientAgent
    
    * Address PR comments and fix tests
    
    * Address PR comments.
    
    * .NET: [BREAKING]Delay AIContext Materialization until the end of the pipeline is reached. (#3883)
    
    * Delay AIContext Materialization until the end of the pipeline is reached.
    
    * Address PR comments.
    
    * Address PR comments
    
    * Modify InvokedContext to be immutable (#3888)
    
    * .NET: Address Feedback on StateBag feature branch PR (#3910)
    
    * Address Feedback on statebag feature branch PR
    
    * Update dotnet/src/Microsoft.Agents.AI.DurableTask/CHANGELOG.md
    
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
    
    * Address PR comments
    
    ---------
    
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
  • .NET: [BREAKING] Change SerializeSession to be Async (#3879)
    * Change SerializeSession to be Async
    
    * Update Changelog
  • .NET: Fix: Checkpoint Deserialization breaks when JSON metadata properties are out of order (#3442)
    * Fix checkpoint JSON deserialization with out-of-order metadata properties (#2962)
    
    * Simplify: propagate AllowOutOfOrderMetadataProperties from incoming JsonSerializerOptions