Commit Graph

669 Commits

Author SHA1 Message Date
Peter Ibekwe 0d5c0f8fa0 .NET: Add language and prompt customization to Magentic orchestration (#7263)
* Add language and prompt customization to Magentic orchestration

* Update default prompts formatting
2026-07-23 18:19:12 +00:00
Ben Thomas bfc73a5b14 .NET: Fix declarative autosend output (#7217)
* Fix declarative workflow auto-send output

Restore completed responses for workflow-conversation agents while preventing hosted workflow adapters from materializing streamed responses twice.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c2d86826-ead0-40bc-b84b-a513ac4d325f

* Correlate streamed workflow responses by message

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c2d86826-ead0-40bc-b84b-a513ac4d325f

* Handle empty streaming message IDs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c2d86826-ead0-40bc-b84b-a513ac4d325f

* Restore workflow conversation auto-send

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c2d86826-ead0-40bc-b84b-a513ac4d325f

* Address workflow response review feedback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c2d86826-ead0-40bc-b84b-a513ac4d325f

* Ignore whitespace workflow message IDs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c2d86826-ead0-40bc-b84b-a513ac4d325f

* Correlate all content-bearing agent updates

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c2d86826-ead0-40bc-b84b-a513ac4d325f

---------

Co-authored-by: Ben Thomas <25218250+alliscode@users.noreply.github.com>
2026-07-22 15:11:59 +00:00
Roger Barreto 1f1da1bddb .NET: [BREAKING] Hosting OpenAI Responses protocol helpers and optional execution state (#7000)
* .NET: Add OpenAI Responses protocol helpers and optional execution state (ADR-0032)

* Fix netstandard2.0/net472 build; harden helpers and workflow checkpoint key per review

* .NET: Migrate hosting Responses samples to Azure.AI.Projects and fix workflow resume

Migrate HostingResponsesAgent and HostingResponsesWorkflow samples from
Azure.AI.OpenAI to Azure.AI.Projects (AIProjectClient.AsAIAgent), using the
FOUNDRY_PROJECT_ENDPOINT/FOUNDRY_MODEL convention.

Fix HostedWorkflowState.RunOrResumeAsync: on subsequent turns, restore the
session's latest checkpoint and run the workflow forward with the new turn's
input (mirroring the Python hosting host's restore-then-run semantics) instead
of resuming a halted run with no input, which waited on input indefinitely.
Add round-trip resume tests and update ADR-0032/spec-003 wording.

* .NET: Fix HostedWorkflowState resume hang on unserviced external requests

On resume, HostedWorkflowState.RunOrResumeAsync drained the workflow with the
blocking WatchStreamAsync overload, so a workflow that halts at an unserviced
RequestInfoEvent (human-in-the-loop / approval) blocked forever — asymmetric
with the first-turn RunAsync path, which returns at the same halt. Break the
drain when a superstep completes with HasPendingRequests, restoring symmetry
with turn 1. Add a HITL approval-gate workflow and a resume-does-not-block test.

* .NET: Warn when a HostedWorkflowState resume makes no progress

Add an optional ILoggerFactory to HostedWorkflowState and log a warning when a
resumed turn produces no events, mirroring the Python host's zero-event restore
warning (a stale checkpoint or an input that does not match the workflow's
expected type leaves session state unprogressed). Add a non-chat string workflow
helper, a capturing logger, and a red/green test.

* .NET: Resume HostedWorkflowState from durable checkpoint on cursor miss

Add CheckpointManager.GetLatestCheckpointAsync(sessionId) and have
HostedWorkflowState fall back to it when its in-memory head cursor misses, so a
durable CheckpointManager resumes a session across a process restart or a new
holder instead of restarting from the workflow's start executor. Mirrors the
Python host's per-turn get_latest read-through. Add a counting workflow that
proves resume-vs-fresh via accumulated state, plus a red/green test, and update
ADR-0032/spec-003 and the XML remarks.

* .NET: Serialize HostedWorkflowState turns through a workflow lock

A single workflow instance backs the holder and workflow instances do not
support concurrent runs (the runner throws "already owned by another runner"),
so concurrent turns could fault or race the head cursor. Serialize all turns
through one SemaphoreSlim (mirroring the Python host's workflow lock) and make
HostedWorkflowState IDisposable to own it. Add a gated workflow and a
deterministic concurrency red/green test.

* .NET: Cover non-chat resume and multi-turn checkpoint advance

Add tests for HostedWorkflowState resuming a non-chat-protocol workflow (no
TurnToken) and for a third turn continuing to advance the head checkpoint,
closing the coverage gaps the parity review flagged.

* .NET: Add streaming workflow resume path and stream the workflow sample

Add HostedWorkflowState.RunOrResumeStreamingAsync, which yields the turn's
WorkflowEvents as they occur (fresh run or checkpoint resume) under the same
serialization lock and records the head checkpoint after the stream drains,
keeping the blocking and streaming workflow paths in lockstep with the Python
host. Honor stream:true in the HostingResponsesWorkflow sample by projecting
AgentResponseUpdateEvent updates over the Responses SSE wire. Add a streaming
resume test and update the README/spec.

* .NET: Cover Responses input adaptation to a typed workflow start executor

Demonstrate that HostedWorkflowState's generic RunOrResumeAsync<TInput> is the
input-adaptation seam (parity with Python's ResponsesChannel run hook): the app
adapts the Responses input into the workflow start executor's own type at the
call site. Add a typed-brief workflow and a test, and note the seam in spec-003.

* .NET: Drain workflow resume non-blocking to prevent hang and truncation

The resume drain used a SuperStepCompletedEvent{HasPendingRequests} proxy over
the blocking public WatchStreamAsync. That proxy (a) truncated a resumed turn
when a superstep both emitted a request and queued downstream work, and (b)
could fail to fire at all — re-introducing the indefinite hang — when a resume
input drove no superstep (e.g. a rejected non-chat input).

Make StreamingRun.WatchStreamAsync(bool blockOnPendingRequest, CancellationToken)
public and drain both the blocking and streaming resume paths with
blockOnPendingRequest:false, exactly matching the first-turn RunAsync semantics
(Run.RunToNextHaltAsync). Add guard tests: resume with a rejected input does not
hang, and a resume superstep with a request plus downstream work is not
truncated (verified red against the old proxy).

* .NET: Return file-store checkpoint index in commit order

CheckpointManager.GetLatestCheckpointAsync takes the last entry of a store's
index as the head checkpoint. FileSystemJsonCheckpointStore backed its index
with a HashSet, whose enumeration order is not contractual: after a rollback
frees and reuses a slot, enumeration can diverge from commit order, so the
durable read-through could resume a stale checkpoint. Mirror the HashSet with an
insertion-ordered list and enumerate it from RetrieveIndexAsync so 'latest' is
reliable. Add a CheckpointManager.GetLatestCheckpointAsync contract test over the
file store.

Note: the HashSet disorder is only reachable via the internal rollback path, so
the test locks the ordering contract rather than reproducing the rare disorder.

* .NET: Advance cursor when a streaming resume is abandoned

RunOrResumeStreamingAsync recorded the head checkpoint only after the stream was
fully enumerated. If an SSE consumer disconnected mid-turn after supersteps had
committed, the in-memory cursor kept the previous turn's head; because the next
turn is then a cursor hit, durable read-through could not self-heal, so it
resumed pre-disconnect state. Record the run's last committed checkpoint in a
finally so an abandoned stream still advances the cursor. Add a red/green test.

* .NET: Stream only the final agent's updates in the workflow sample

ExtractUpdates streamed every agent's updates, so the sequential Writer->Reviewer
sample streamed the intermediate draft and the final answer over SSE, differing
from the non-streaming response (final message only). Filter the streamed updates
to the final agent so streaming and non-streaming produce the same response.
Live-verified against Foundry: one output item streamed instead of two.

* .NET: Isolate the holder lock in the concurrency test

The concurrency test asserted the second same-session turn did not enter the
workflow, which also passes via the engine's concurrent-run ownership guard
(which faults) rather than the holder lock (which waits). Assert instead that the
second turn is not completed while the first holds the lock: a fault would
complete the task, so a pending task isolates the holder lock from the engine
guard. Verified red with the lock removed.

* Fix IDE1006 naming in tests; address review feedback and add hosting/live tests

* Document commit-order contract for ICheckpointStore.RetrieveIndexAsync

* Restructure hosting samples under af-hosting with client/server split matching Python parity

* Clarify hosting sample README wording and drop Python comparisons

* Make AgentSessionStore.DeleteSessionAsync abstract and rename session id parameter to sessionStoreId

* Rename OpenAIResponses id helpers and parse the request once for id extraction

* Reclaim per-session locks in HostedAgentState and demonstrate session locking in the agent sample

* Internalize per-session locking in HostedAgentState (automatic, on by default) and remove mirroring-Python wording from code and spec

* Remove HostedAgentState; app-owned routes use AgentSessionStore directly

HostedAgentState only bundled an AIAgent with an AgentSessionStore and, after
the per-session lock was removed, its GetOrCreateSessionAsync/SaveSessionAsync/
DeleteSessionAsync were pass-throughs that just bound the agent argument.
Create-on-miss already lives in the store (unlike Python, whose get/set-only
SessionStore justifies its AgentState holder), so the type earned its place
only via the lock.

Each AgentSessionStore.GetSessionAsync now returns an independent session
instance per call, so concurrent gets fork the same stored state (e.g.
branching from previous_response_id or managing several conversation ids)
without sharing an instance. The store does no cross-call locking; serializing
concurrent runs against the same id is the application's concern.

- Delete HostedAgentState and its unit tests.
- Rewire the local_responses sample and the OpenAI hosting unit/integration
  tests to call AgentSessionStore (GetSessionAsync/SaveSessionAsync) directly.
- Update ADR-0032, spec-003, and the af-hosting sample READMEs.

* Isolate hosted session snapshots and distinguish conversation vs response continuation

Mirrors the Python hosted-session isolation work: a hosted session read must be
an independent copy, and the app-owned route must persist under the right
continuation key depending on how the caller continued the thread.

- AgentSessionStore.GetSessionAsync: document the isolation invariant (each
  call returns an independent AgentSession so concurrent branches from one
  previous_response_id do not observe each other's mutations or alter stored
  state); fix the stale "or null if not found" wording (in-box stores return a
  fresh created session on miss). The in-box stores already satisfy this via a
  serialize/deserialize snapshot round-trip.
- local_responses sample + hosting unit-test route: choose the save key by
  channel. A stable conversation id is a mutable head (write back under the
  same id; app owns single-writer coordination). A previous_response_id
  continuation or first turn is an immutable snapshot (save under the new
  response id so branches from the same prior response stay independent).
- Add regression tests: independent get returns a distinct instance
  (InMemoryAgentSessionStore); previous_response_id supports independent
  branches ([1,2,2,3,3]); conversation id advances the mutable head ([1,2]).
- Update the sample README and ADR-0032 wording.

* Add workflow-factory support to HostedWorkflowState for concurrent sessions

HostedWorkflowState backed every session with one shared Workflow instance and
serialized all turns through a lock, so independent sessions could not run
concurrently. Add a workflow-factory constructor and remove the run lock.

- New constructor HostedWorkflowState(Func<CancellationToken, ValueTask<Workflow>>
  workflowFactory, ..., bool cacheWorkflow = false):
  - cacheWorkflow: false (default) builds a fresh instance per run, so independent
    sessions run in parallel. A resume rehydrates a fresh instance from the
    session's checkpoint in the shared store.
  - cacheWorkflow: true builds the workflow once, lazily on first use, and reuses
    it (a deferred, cached target that, like a shared instance, cannot run
    concurrent turns).
- Remove the internal SemaphoreSlim run lock and IDisposable; the instance
  constructor is unchanged in behaviour (one shared instance still cannot run
  concurrent turns). Turns are no longer serialized by the holder; a single
  writer per session is the application's responsibility.
- Switch the local_responses_workflow sample to the factory constructor with an
  explicit cacheWorkflow: false, and document the option.
- Add tests: parallel independent sessions (factory), fresh-instance resume,
  cached factory builds once and reuses, uncached factory builds per run.
- Update ADR-0032, spec-003, and the sample README.

* Clarify in ADR-0032 how .NET covers AgentState factory and async-setup via DI

* Rebuild cached workflow after a faulted build and add checkpoint index dedup tests
2026-07-22 10:32:44 +00:00
Roger Barreto f6a3c43e9a .NET: Add source-type-agnostic consent regression test for a2a_preview (#7229) 2026-07-21 15:08:06 +00:00
westey c033adb1f4 .NET: [BREAKING] Graduate HarnessAgent (#7119)
* Graduate HarnessAgent

* Switch harness project to released and remove unreleased shell dependency

* Address PR comments.
2026-07-21 14:24:19 +00:00
Roger Barreto 09473fa7ed .NET: [BREAKING] Bind tool-approval responses to surfaced approval requests (#7111)
* .NET: Bind tool-approval responses to surfaced approval requests

Harden the tool-approval flow so an approved tool call always matches the
request the framework surfaced for approval.

Add ApprovalResponseBindingChatClient as the outermost decorator above
FunctionInvokingChatClient. It records each model-originated
ToolApprovalRequestContent in the session state and, on the next request,
binds every ToolApprovalResponseContent to its recorded request: the
response tool call is rebound to the recorded call, matched entries are
consumed for one-time use, and only approvals tied to a framework-issued
request take effect.

Apply the same binding in the ToolApprovalAgent harness by tracking the
requests it surfaces and binding collected responses to them during a
queue cycle.

Add ChatClientAgentOptions.DisableApprovalResponseBinding (default off) and
a UseApprovalResponseBinding builder extension for custom chat client stacks.
Includes unit tests for the decorator and the harness.

* .NET: Bind approval responses once per turn and avoid re-enumeration

Address review feedback on the approval-response binding decorator:
consume a matched request from the per-turn lookup so a duplicate response
with the same request id in one turn is honored only once, and return the
materialized message list instead of the original enumerable so a single-use
sequence is not enumerated twice. Rename the local pending list to
pendingRequests for clarity. Adds a duplicate-response regression test.

* .NET: Snapshot recorded approval requests and consume duplicates in the harness

Address review feedback on ToolApprovalAgent:
store a snapshot of each surfaced/pending approval request (cloned tool call
with a copied arguments dictionary) so a later mutation of the caller-visible
instance cannot change the recorded call used to bind the response, and consume
a surfaced request on match so a duplicate response with the same request id in
one pass is honored only once. Apply both symmetrically in the harness and the
ApprovalResponseBindingChatClient decorator. Adds regression tests for the
snapshot and duplicate-response cases.

* .NET: Address review feedback on approval-response binding

- Harness: store surfaced approval requests in a dictionary and consume matches directly, drop the extra hashset and the redundant record-time dedup; replace clear-on-resolution with a debug assert.
- Harness pipeline: add UseApprovalResponseBinding() as the outermost decorator in HarnessAgent (it uses UseProvidedChatClientAsIs) behind a new DisableApprovalResponseBinding option, with tests.
- Decorator: avoid message/content allocations when nothing changes, keep the original content when a response already matches the recorded call, clear pending each inbound turn, and shorten helpers.

* .NET: Compare tool calls by fields instead of serializing

Replace the JSON-serialization comparison in the approval-response binding
decorator with a direct field comparison. Fast-path FunctionCallContent by
comparing CallId, Name, and arguments field by field; any other tool call
shape rebinds. The comparison only skips an allocation (the call is always
rebound to the recorded request otherwise), so a miss just triggers a safe
rebuild. Adds a test that a matching response is forwarded unchanged.

* .NET: Bind approval responses against requests present in history

Fix a merge-queue regression where AG-UI mixed server/client tool invocation
stopped executing the server tool. The binding decorator validated approval
responses only against its own recorded pending state, so a matched approval
request/response pair replayed from conversation history was treated as
unbound and dropped, and the auto-approved server tool never ran.

Treat known requests as the recorded pending state plus any approval requests
already present in the current messages, and stop dropping approval requests
(a request in history is the pairing authority). A response with no known
request anywhere is still dropped, so a forged approval cannot execute.

Also address review feedback: return the mutable contents buffer from a
helper instead of a null-forgiving operator, and use clearer naming
(PrepareMutableContentsBuffer / mutableContentsBuffer). Adds regression tests
for a request in history and a response bound to a history request with empty
pending state.
2026-07-21 14:23:48 +00:00
安妮的心动录 9cf5143321 .NET: Populate AgentResponse metadata in CopilotStudioAgent (#6791)
* .NET: Populate AgentResponse metadata in CopilotStudioAgent

Map CreatedAt, FinishReason, RawRepresentation and AdditionalProperties onto
AgentResponse and AgentResponseUpdate, and map the activity timestamp and
properties onto ChatMessage, so Copilot Studio agents expose the same metadata
surface as other AIAgent implementations. Streaming sets the finish reason on
the terminal update while still emitting already-received content if the source
faults. Add unit tests covering the metadata mapping.

* fix: add Async suffix to async test methods (IDE1006)
2026-07-20 21:38:24 +00:00
Marco Minerva 3ab2630243 .NET: Refactor Workflows MessageMerger to preserve message order and structure (#6826)
* Refactor MessageMerger to preserve message order

Refactored MessageMerger to delegate update grouping and merging to M.E.AI, preserving the correct order and structure of assistant messages, especially for reasoning content without message IDs. Removed per-message bucketing and CreatedAt-based sorting. Added tests to verify message order and correct merging of reasoning and text updates.

* Set CreatedAt from merged responses preservation of original message timestamps during merging.

* Set merged message CreatedAt to current UTC time

Removed logic for tracking unique creation times and now always assign DateTimeOffset.UtcNow to the merged response's CreatedAt property. This simplifies timestamp handling during message merging.

* Refactor MessageMerger id-less folding logic

Refactored MessageMerger to fold identifierless reasoning segments into the following id'd message at the flattened-message level, ensuring correct merging across response buckets (fixes #6329). Updated ComputeMerged to merge id-less messages with the next message of the same role. Removed redundant per-bucket folding logic. Added unit tests to verify correct folding behavior and role matching.

* Remove unused property

 Removed the unused Role property from MessageMergeState for code cleanliness.

* Refactor MessageMerger to iterate backward for merging

Changed MessageMerger to iterate messages in reverse order, ensuring all consecutive messages without IDs preceding a message with an ID are merged correctly. Updated merging logic, index handling, and comments to reflect this new approach.

* Update code comment to better reflect its behavior.

---------

Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
2026-07-17 17:10:14 +00:00
ssccinng d5f2c77b35 .NET: Honor terminal workflow outputs in Workflow.AsAIAgent responses (#6212)
* Fix workflow agent terminal output responses

* Address workflow agent response review feedback

---------

Co-authored-by: Peter Ibekwe <109177538+peibekwe@users.noreply.github.com>
2026-07-17 15:36:26 +00:00
Eduard van Valkenburg 5282c158aa .NET: Fix LocalCodeAct validation and package checks (#7138)
* Fix LocalCodeAct validation and package checks

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: aecf332f-b940-41a7-ac3a-6fbbe9892141

* Address LocalCodeAct alias review feedback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: aecf332f-b940-41a7-ac3a-6fbbe9892141
2026-07-16 15:17:52 +00:00
feiyun0112 dde7635760 .NET: [Feature]: .NET Improve ChatClientAgentSession constructor (#7142)
* .NET: [Feature]: .NET Improve ChatClientAgentSession constructor

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* test: make deserialize test actually reproduce issue #7109

VerifyDeserializeWithWhenWritingNullOptions passed against both the old
and the fixed constructor, so it did not guard against the regression.

The bug only reproduces when required constructor parameters are respected
(the issue uses RespectRequiredConstructorParametersDefault=true). With
WhenWritingNull a null conversationId is omitted from the JSON, and STJ then
throws 'missing required properties including: conversationId' because the
constructor parameter had no default value.

Adding RespectRequiredConstructorParameters = true to the test options makes
the test red against the parameter-without-default constructor and green with
the default-valued constructor parameters, so it now protects the fix.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com>
2026-07-16 15:06:37 +00:00
King Star 85c00fc55b .NET: preserve HeadTailBuffer UTF-8 order (#7128)
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
2026-07-16 10:03:43 +00:00
Peter Ibekwe 05834b56e3 Fix message ordering in workflow-hosted agents (#7123) 2026-07-15 19:40:47 +00:00
westey b3f2e53923 .NET: [BREAKING] Graduate ToolApprovalAgent and add ToolAutoApprovalRuleContext (#7107)
* Graduate ToolApprovalAgent and introduce tool auto approval context

* Address PR comments
2026-07-15 09:21:12 +00:00
Rince Yuan 47cd0a508d docs/.NET: fix typos in XML doc comments, ADR docs, and test comments (#7085)
- Fix double period in AnthropicClientExtensions.cs XML param docs (lines 23, 77)
- Fix double period in IScopedContentProcessor.cs XML param doc (line 20)
- Fix 'similar the the' -> 'similar to the' in ADR 0009 (line 1092)
- Fix 'reponse' -> 'response' in ADR 0001 (line 142)
- Fix 'retreive' -> 'retrieve' in ChatClientAgentTests.cs (line 467)
- Remove leftover template placeholder from ADR 0001 and 0006 frontmatter

Co-authored-by: j-zhangyiyuan <j-zhangyiyuan@microsoft.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
Co-authored-by: Giles Odigwe <79032838+giles17@users.noreply.github.com>
2026-07-14 17:06:46 +00:00
westey d93fc2dd74 .NET: [BREAKING] Harness: Switch FileAccess to opt-in (#7093)
* Switch FileAcessProvider on Harness to opt-in

* Address PR comment

---------

Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
2026-07-14 07:08:33 +00:00
Nick Brady 54617557e6 Update Foundry branding (#6999)
Replace user-facing Azure AI Foundry branding with Microsoft Foundry across docs, samples, comments, and display text while preserving technical identifiers.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
2026-07-14 06:44:26 +00:00
westey e57f046d8a Graduate mode and todo providers (#7052) 2026-07-13 13:47:58 +00:00
westey beb65b21a8 .NET: [BREAKING] Graduate message injection out of experimental (#7044)
* Remove experiemental flags for MessageInjection component

* Improve locking on message injection.
2026-07-13 11:26:01 +00:00
Peter Ibekwe 737042fc93 Fix workflow session bug (#7032) 2026-07-10 16:56:57 +00:00
Patrick Woo-Sam e677ccc3b1 .NET: Fix CompactionMessageIndex.IsSummaryMessage (#7042)
* Fix CompactionMessageIndex.IsSummaryMessage

* Add more robust JsonElement value checking and tests cases
2026-07-10 15:03:26 +00:00
Theo van Kraay d9c0c36379 Fix CosmosChatHistoryProvider: omit ttl when MessageTtlSeconds is null (#6992) (#7030) 2026-07-10 13:01:59 +00:00
Peter Ibekwe 3f4ffc6c2c .NET: Fix declarative InvokeAzureAgent failing on non-object JSON agent output (#7002)
* Fix declarative InvokeAzureAgent failing on non-object JSON agent output

* Fix PR comments.
2026-07-09 17:10:51 +00:00
westey 76f2c1a0c9 .NET: [BREAKING] Graduate per-service-call persistence and approval-not-required function bypassing (#6970)
* Remove experimental flags for RequirePerServiceCallChatHistoryPersistence and DisableApprovalNotRequiredFunctionBypassing

* Address PR comments

* Fix failing test
2026-07-08 09:31:33 +00:00
Evan Mattson 12b029858e Build(deps): consolidate Dependabot dependency updates (#6984)
* Consolidate Dependabot dependency updates

* Restore method assignment suppression
2026-07-08 09:09:03 +00:00
Javier Calvarro Nelson 3d17615b6e .NET: Replace MAF AG-UI abstractions with the AG-UI C# SDK abstractions (#6653)
* .NET: Replace internal AG-UI implementation with external ag-ui packages

Remove the in-tree Microsoft.Agents.AI.AGUI sources and consume the external
AG-UI .NET SDK packages (AGUI.Abstractions, AGUI.Formatting, AGUI.Protobuf,
AGUI.Client, AGUI.Server) at 0.1.0-preview instead.

- Microsoft.Agents.AI.Hosting.AGUI.AspNetCore keeps its own ASP.NET glue
  (MapAGUI / AddAGUI / SSE result) layered over the framework-agnostic
  AGUI.Server primitives (ToChatRequestContext / AsAGUIEventStreamAsync).
- Migrate call sites to the options-based AGUIChatClient constructor and recover
  the originating AG-UI input via ChatOptions.TryGetRunAgentInput.
- Multi-turn continuation flows through parentRunId + threadId on
  RawRepresentationFactory; shared state flows through RunAgentInput.State and is
  surfaced as StateSnapshotEvent raw representations.
- Update samples, hosting/unit/integration tests, and central package versions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add migration README for removed Microsoft.Agents.AI.AGUI package

Keep the package folder in place with a README explaining that the in-tree AG-UI protocol abstractions moved to the external AGUI.* NuGet packages, with a mapping of old namespaces to the new packages and a migration guide.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
2026-07-07 20:09:53 +00:00
westey 757a832dbf .NET: Add OpenTelemetry Chat Client to harness stack (#6961)
* Add OpenTelemetry Chat Client to harness stack

* Address PR comments
2026-07-07 14:14:26 +00:00
Tamir Dresher cc20093da1 .NET: fix: bump GitHub.Copilot.SDK to 1.0.5 to resolve strong-naming mismatch (#6949)
* fix: bump GitHub.Copilot.SDK to 1.0.5 to resolve strong-naming mismatch

SDK 1.0.5 introduced strong-naming (PublicKeyToken=cc7b13ffcd2ddd51).
The adapter was compiled against the unsigned SDK (PublicKeyToken=null),
causing CS0012 for any consumer referencing both packages.

Fixes #6948

* fix: update tests and extension for SDK 1.0.5 namespace changes

- Add 'using GitHub.Copilot;' to CopilotClientExtensions.cs
- Change extension namespace to Microsoft.Agents.AI.GitHub.Copilot
- Update test files for new SDK types and removed APIs
- Add #pragma to suppress GHCP001 experimental warnings in tests
- All 45 tests pass across net8.0, net9.0, net10.0

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* style: run dotnet format to fix linting issues

Remove unnecessary using directives (IDE0005) and fix file encoding (CHARSET).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix: revert CopilotClientExtensions namespace to GitHub.Copilot

Per reviewer feedback, extension methods should live in the namespace
of the type they extend (CopilotClient). This follows .NET team guidance.
The original namespace was GitHub.Copilot.SDK which was renamed to
GitHub.Copilot in SDK 1.0.5.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* refactor: narrow tools parameter from AITool to AIFunctionDeclaration

Since SessionConfig.Tools only accepts AIFunctionDeclaration, change the
constructor and extension method parameters to accept IList<AIFunctionDeclaration>
instead of the more general IList<AITool>. This makes the API honest about what
it actually uses and avoids silently discarding non-AIFunctionDeclaration tools.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix: sync Directory.Packages.props with upstream main

Take upstream's package versions (including MessagePack 3.1.7 pin
that fixes NU1902/NU1903 vulnerability warnings) while keeping
GitHub.Copilot.SDK at 1.0.5 which is the purpose of this PR.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-07 14:09:28 +00:00
Tao Chen 5ac5038545 .NET: Add defense-in-depth for MCP cross origin request (#6871)
* Add defense-in-depth for MCP cross origin request

* Address comments
2026-07-06 17:37:36 +00:00
Roger Barreto c09408cbd6 .NET: Fix flaky OpenTelemetryAgentTests via thread-safe activity collector (#6935)
* .NET: Fix flaky OpenTelemetryAgentTests via thread-safe activity collector

The Ctor_NullOrWhitespaceSourceName test subscribed a process-global TracerProvider to the shared default source Experimental.Microsoft.Agents.AI and exported into a plain List<Activity>. That source is also used by CompactionTelemetry, and xUnit runs the Compaction test classes in parallel, so a compaction span could be appended from another thread mid-assertion, throwing 'Collection was modified'.

Add a thread-safe ConcurrentActivityList collector (locked Add plus snapshot enumeration) for all InMemoryExporter collectors in the file, and scope the shared-source test to its own invoke_agent TraceId after ForceFlush so parallel compaction spans cannot affect the count or source-name checks.

* .NET: Assert ForceFlush result in OpenTelemetryAgentTests default-source test

Assert the boolean returned by TracerProvider.ForceFlush(timeout) so a flush timeout surfaces as a clear test failure instead of silently snapshotting incomplete activities.
2026-07-06 16:11:11 +00:00
westey ccba1fbbef .NET: [BREAKING] Align ShellPolicy allow/deny semantics with Python (#6906)
* Align dotnet shell policy with python implementation to support deny if not allowed semantics.

* Address PR comments.

* Address PR comments
2026-07-03 18:09:35 +00:00
Roger Barreto 2c7aadce4e .NET: Validate Foundry toolbox name is a single path segment before building the proxy URL (#6890)
* Validate Foundry toolbox name is a single path segment before building the proxy URL

Reject toolbox name/identifier inputs that carry path separators or relative-path segments (including their percent-encoded forms) before they are interpolated into the toolbox MCP proxy request URL, so a caller-influenced marker cannot alter the request target. Validation runs both at per-request marker resolution and at the shared open choke point, and is covered by red-to-green unit tests.

* Reject residual percent-encoding in toolbox name validation

After the bounded percent-decode loop, also reject a name that still contains a percent sign, so encoding nested deeper than the decode cap cannot survive validation. Dispose the service via await using in the rejection test. Adds a deeply-encoded coverage case.

* Validate toolbox name by request-target effect instead of a character list

Replace the character/decoding checks with an effect-based check: build the proxy URL and confirm the name resolves to a single, intact path segment between 'toolboxes' and 'mcp' with the scheme, authority, path shape, and fragment unchanged, and that the segment round-trips back to the name. This forgives characters that stay inside the segment (for example ':' , '@' , parentheses) while still rejecting names that would move the request target, including '?' and '#' and their percent-encoded forms. Adds coverage for the delimiter cases and for the newly-allowed names.
2026-07-03 17:00:26 +00:00
Roger Barreto 8be157e2a1 Return 404 for a response created against a nonexistent conversation (#6892)
When a create-response request references a conversation id that does not
exist, validate its existence up front and return a clean not-found error
mapped to HTTP 404, consistent with the Conversations API, instead of failing
mid-execution and surfacing a generic server error.

Centralize the responses validation error codes and their HTTP status mapping
in a single ResponseErrorCodes type so handlers translate a code to a 404 or
400 without ad-hoc string comparisons. Add unit and HTTP integration tests.
2026-07-03 17:00:00 +00:00
SergeyMenshykh 331d17c5a1 .NET: fix: Require explicit TokenCredential in AddFoundryToolboxes (#6877)
* fix: require explicit TokenCredential in AddFoundryToolboxes

The AddFoundryToolboxes extension methods now require callers to
pass a TokenCredential explicitly rather than relying on an
internally-created default credential. This makes the credential
choice intentional and avoids non-deterministic credential probing
in production environments.

Breaking change (experimental API):
- AddFoundryToolboxes(IServiceCollection, params string[]) becomes
  AddFoundryToolboxes(IServiceCollection, TokenCredential, params string[])
- AddFoundryToolboxes(IServiceCollection, Action?, params string[]) becomes
  AddFoundryToolboxes(IServiceCollection, TokenCredential, Action?, params string[])
- Azure.Identity package dependency removed from Foundry.Hosting library.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: simplify redundant generic type argument (IDE0001)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: avoid duplicate FoundryToolboxService registration

Inject the AddFoundryToolboxes credential directly into the
FoundryToolboxService factory and fail early if the service was
already registered. This avoids registering TokenCredential in the
host DI container while preserving a single toolbox service instance
for both request handling and hosted startup.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-02 15:44:56 +00:00
westey 48436f8ab6 .NET: Make default-approval harness features configurable + customizable shell tool (#6880)
* Dotnet: Allow devs to opt-out of file-access approvals

* Address PR comments
2026-07-02 14:57:59 +00:00
Roger Barreto 551b44f04f .NET: Bump Azure.AI.Projects to 2.1.0-beta.4 (#6795)
* .NET: Bump Azure.AI.Projects to 2.1.0-alpha.20260629.1

Bumps Azure.AI.Projects beta.3 to alpha.20260629.1 and aligns transitive deps (System.ClientModel 1.14.0, Azure.Core 1.59.0, Msal 4.84.2). Adapts to renamed AgentSessionFiles APIs (Upload/GetAll/Delete, scoped GetAgentSessionFiles, SizeInBytes), AgentToolboxes (CreateVersion/Delete), and strongly typed toolbox tools (WebSearchToolboxTool, MCPToolboxTool). Adds azure-sdk public dev feed for prerelease restore.

* Use positional arg for AgentSessionFiles.DeleteAsync cleanup

* Move to Azure.AI.Projects 2.1.0-beta.4 (released beta)

Swaps the alpha daily build for the published 2.1.0-beta.4. Drops the azure-sdk public dev feed since beta.4 and its deps are on nuget.org. Beta.4 requires Azure.Core 1.60.0, which cascades the 10.0.8 servicing packages (Microsoft.Bcl.AsyncInterfaces, System.Diagnostics.DiagnosticSource, System.Text.Json, System.Threading.Channels, Microsoft.Extensions.DependencyInjection.Abstractions, Microsoft.Extensions.Logging.Abstractions) to 10.0.9.

* Reconcile Azure.Core 1.60.0 bump with merged main

Reverts the over-eager System.Threading.Channels 10.0.9 bump back to 10.0.8 (it was not part of the Azure.Core 1.60.0 cascade and caused a net472 MSB3277 conflict against the 10.0.8 that Microsoft.Extensions.AI pulls). Drops the now-obsolete Azure.Core VersionOverride=1.59.0 in HostedWorkflowHandoff (added on main to satisfy AgentServer while the central pin was lower); the central pin is now 1.60.0 which already satisfies the >=1.59.0 floor, and the override was downgrading this project below sibling projects (CS1705).
2026-07-02 14:40:03 +00:00
Roger Barreto 62f0024707 .NET: Foundry Hosting gracefully tolerates lacking user identity when run locally (#6870)
* .NET: Make Foundry Hosting resilient to missing user identity in local runs

AgentFrameworkResponseHandler threw InvalidOperationException (surfaced as a
500 on every request) when the isolation-key provider returned null, which
always happens locally because the platform x-agent-user-id header is absent.
Running a hosted image outside Foundry therefore failed out of the box.

The handler now branches on FoundryEnvironment.IsHosted: hosted stays strict
(null identity is still a hard error), but non-hosted (local docker run /
dotnet run) tolerates a null identity - per-user isolation is simply not
triggered, the request proceeds with userId null (no partition), and no
hosted context is stamped or validated.

Because local runs no longer need a fallback, the sample-side
DevTemporaryLocalUserIdProvider and AddDevTemporaryLocalContributorSetup are
removed from Hosted_Shared_Contributor_Setup and all sample Program.cs files.
To simulate distinct users locally, send an x-agent-user-id request header;
the default provider reads it exactly as it reads the platform-injected value.
The Memory sample smoke script now drives alice/bob against one container via
that header. AGENT_NAME defaults added to Hosted-ChatClientAgent and
Hosted-MemoryAgent so a hosted deploy (where AGENT_* is a reserved env var)
does not crash at startup.

Updates the two affected unit tests to assert the local-success path and
amends ADR 0031.

* Address review: correct isolation-guarantee and Memory-sample local docs

- AgentFrameworkResponseHandler: note the null/local case is unscoped/shared,
  not fully partitioned per user.
- HostedSessionIsolationKeyProvider XML docs: phrase the non-null UserId rule as
  a constraint on the returned-context case, since null is now allowed locally.
- Hosted-MemoryAgent: the PerUser() memory scope requires a resolved user, so a
  local run needs an x-agent-user-id header; corrected the Program.cs comment
  and README (removed the inaccurate "shared bucket locally" claim).
- Test: assert absence of any u-* per-user directory via a wildcard search
  rather than checking for a literal "u-" directory.
2026-07-02 09:32:22 +00:00
westey 300dfa7e36 .NET: [BREAKING] Refactor OpenAI Hosting OptionsMapping to disallow passing options by default (#6855)
* Refactor OptionsMapping to disallow passing options by default

* Address PR comments

* Address PR comment
2026-07-01 15:05:53 +00:00
westey e56f34c521 .NET: [BREAKING] Add file editing tools and align FileAccess/FileMemory store API (#6807)
* Add support for editing to file access and memory plus renames

* Address PR comments

* Address PR comments
2026-07-01 13:35:48 +00:00
SergeyMenshykh 51c05fc862 .NET: Add skill approval options (#6843)
* .NET: Add skill approval options

Add per-tool options for disabling approval on skills provider tools and cover the behavior with unit tests.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* .NET: Document mixed approval behavior

Document the non-approval bypass requirement and update tests to avoid file-discovery dependency.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: SergeyMenshykh <SergeMenshikh@outlook.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-01 12:46:08 +00:00
SergeyMenshykh b7fc23c61f .NET: Consolidate skill-source caching and make skill sources disposable (#6827)
* .NET: Consolidate skill-source caching and make skill sources disposable

Move all caching into the generic CachingAgentSkillsSource decorator and
remove the duplicate inline cache from AgentMcpSkillsSource, so a single
cache layer governs skill fetching. Add RefreshInterval-based expiry to
CachingAgentSkillsSourceOptions.

Make AgentSkillsSource (and its decorators) IDisposable so pipelines can
release owned resources, and give AgentSkillsProvider an ownsSource flag
controlling whether it disposes the source it wraps. Provider convenience
constructors and the builder set ownsSource: true.

Serialize ArchiveEntryLoader's reconcile/extract/read of the shared on-disk
directory with a per-instance lock to prevent concurrent corruption.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* .NET: Fix IDE0032 by using an auto-property in test source

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* .NET: Make cancellation cache test deterministic

Ensure the first caller owns the fetch before the second caller queues, so
the cancellation-restart assertion is no longer race-prone.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* .NET: Throw ObjectDisposedException from CachingAgentSkillsSource after disposal

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* .NET: Document AgentSkillsProviderBuilder source ownership and single-build contract

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* .NET: Update API compatibility suppressions for AgentSkillsProvider ctor change

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* .NET: Add test asserting archive skill updates are observed after reconcile

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: SergeyMenshykh <SergeMenshikh@outlook.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-01 12:46:07 +00:00
Roger Barreto f9b2fbb676 .NET: Foundry Hosting per-user session isolation and Responses v2 protocol fast-fail (#6832)
* Add per-agent and per-user session storage isolation for Foundry Hosting

Partitions hosted session and checkpoint files as {root}/a-{agentName}/u-{userId}/c-{contextId}.json so a container that serves multiple agents and multiple users cannot leak state across tenants. The user layer collapses to a-{agent}/c-{conv}.json when no x-agent-user-id is present (raw local). Adds a reject-style path-traversal guard (CWE-22) for the untrusted user id plus a resolve-and-assert-under-root containment check, and keeps the strict-resume 403 identity check as a second defense layer.

AgentSessionStore.GetSessionAsync/SaveSessionAsync take a required (nullable) userId so a caller can never silently persist a session unscoped; the handler resolves the user id before loading the session and threads it to both. Tool approvals ride in the session checkpoint (ToolApprovalIdMap to AgentSessionStateBag), so the partitioned path covers them and no separate approval store is needed. Renames the sample HOSTED_USER_ISOLATION_KEY env var to HOSTED_USER_ID and DevTemporaryLocalSessionIsolationKeyProvider to DevTemporaryLocalUserIdProvider. Documents the design in ADR 0031. Adds handler-driven multi-agent/multi-user file-system tests and store-level traversal/isolation tests.

* Fail fast with a clear 501 when hosted container is served responses protocol 1.0.0

A 2.0.0-only hosted image served container protocol 1.0.0 (no x-agent-foundry-call-id
header) previously threw and surfaced an opaque 500 on every request. It now returns a
clear 501 "unsupported_container_protocol_version" naming the required protocol.

* HostedProtocolCompatibility gate keyed on FoundryEnvironment.IsHosted plus
  PlatformContext.CallId (the 2.0.0 exclusive marker); invoked before isolation resolution
* HostedProtocolCompatibilityTests unit coverage; AgentFrameworkResponseHandlerTests note
  clarifies the non-hosted path
* UnsupportedProtocolHostedAgentTests integration test deploys a dedicated
  it-unsupported-protocol agent as 1.0.0 and asserts the 501 (validated live on cace)
* TestContainer recognizes the unsupported-protocol scenario
* it-bootstrap-agents.ps1 placeholder default raised to responses 2.0.0 and adds the
  it-unsupported-protocol agent; HostedAgentFixture protocol version is overridable

* Address PR review: whitespace protocol gate and InMemory store agent keying

* HostedProtocolCompatibility treats a whitespace-only x-agent-foundry-call-id as
  absent (IsNullOrWhiteSpace) so a proxy injecting whitespace cannot bypass the gate;
  unit test covers empty, spaces and tab
* InMemoryAgentSessionStore keys sessions by agent.Name (omitting the agent segment
  when Name is unset), mirroring FileSystemAgentSessionStore, so session continuity
  survives a recreated or transient agent rather than keying on the per-instance agent.Id
2026-06-30 19:30:46 +00:00
SergeyMenshykh 09fbccfb20 .NET: Add AgentSkillsSourceContext to AgentSkillsSource.GetSkillsAsync (#6797)
* Add AgentSkillsSourceContext to AgentSkillsSource.GetSkillsAsync

Pass agent/session context through the skills retrieval pipeline so
sources, filters, and caching can make context-aware decisions.

- AgentSkillsSourceContext (Agent, Session) is built by AgentSkillsProvider
  from the InvokingContext and flows through all sources and decorators.
- FilteringAgentSkillsSource predicate now receives an AgentSkillFilterContext
  bundling the skill and the source context.
- CachingAgentSkillsSource supports per-key isolation via
  CachingAgentSkillsSourceOptions.CacheIsolationKeySelector; a null selector
  preserves the shared-cache behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Make AgentSkillsSourceContext constructor public and harden cache key

- Make the AgentSkillsSourceContext constructor public so external callers
  can invoke AgentSkillsSource.GetSkillsAsync directly; drop the
  Mcp.UnitTests InternalsVisibleTo entry it required.
- Use a dedicated sentinel cache key for the shared bucket so an isolation
  selector returning an empty string gets its own bucket.
- Document cache-key cardinality guidance and baseline the experimental
  API breaking changes in CompatibilitySuppressions.xml.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Drop AgentSkillFilterContext in favor of a two-argument filter predicate

Replace the AgentSkillFilterContext bundle with a
Func<AgentSkill, AgentSkillsSourceContext, bool> predicate in
FilteringAgentSkillsSource and AgentSkillsProviderBuilder.UseFilter, and
update the tests accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: SergeyMenshykh <SergeMenshikh@outlook.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-30 13:01:51 +01:00
Roger Barreto 0d53d11bc6 .NET: [BREAKING] Bump Azure.AI.AgentServer to 2.0.0 protocol and migrate Foundry.Hosting (#6800)
* .NET: Bump Azure.AI.AgentServer to 2.0.0 protocol and migrate Foundry.Hosting

Bumps Core .25->.26, Invocations .4->.5, Responses .5->.6 and adopts the 2.0.0 container protocol.

Breaking change: IsolationContext (UserIsolationKey + ChatIsolationKey) is replaced by PlatformContext (UserIdKey from x-agent-user-id, CallId from x-agent-foundry-call-id). The per-chat key is gone; HostedSessionContext is now user-only and the per-request CallId is forwarded outbound to Foundry first-party services (toolbox/MCP).

Also fixes a real call-id egress bug: AsyncLocal writes inside the streaming response iterator are reverted across yield boundaries, so the call id was dropped before the toolbox/MCP egress ran. The handler now re-applies HostedCallContext.CallId before each egress point.

Adds HostedConversationKey to map a request to a stable MAF AgentSession via conversation_id, else the partition key embedded in previous_response_id, else the minted response id. This keeps store=false previous_response_id chains and conversation_id forks on a single hosted MAF session without using the container session id.

Sample manifests bump the responses protocol to 2.0.0 (invocations stays 1.0.0). Integration tests split store/session semantics into HostedResponsesStoreConfigTests with its own scenario, read stored responses through the per-agent endpoint client, and inject the model deployment into the container.

* Pin Azure.Core 1.59.0 for Hosted-Workflow-Handoff sample

AgentServer 1.0.0-beta.26 (pulled transitively via Foundry.Hosting) requires Azure.Core 1.59.0. This sample disables transitive pinning and references Azure.Core directly, so override just this project to the SDK-required version without moving the solution-wide central pin.

* Add guard test for request-scoped call-id cleanup

Asserts HostedCallContext.CallId does not leak into the caller's execution context after CreateAsync's stream completes, while confirming the agent run still observed the call id. Documents the request-scoped contract and guards against stale-header leakage across requests handled on the same thread.

* Refresh hosting READMEs for AgentServer 2.0 migration

Updates stale docs to match the shipped code: the MemoryAgent README now describes the x-agent-user-id user-identity header (chat isolation key removed) feeding HostedSessionContext.UserId; the IntegrationTests README corrects the scenario count (six to eleven), adds the missing memory scenario row, and stops claiming all scenarios are skipped now that several are validated and active.

* Add ADR 0030 superseding 0026 for AgentServer 2.0 platform context

Documents the migration from ResponseContext.Isolation (UserIsolationKey/ChatIsolationKey) to ResponseContext.PlatformContext (UserIdKey/CallId): user-only HostedSessionContext, the request-scoped HostedCallContext call-id forwarded on egress, HostedConversationKey session keying, and removal of the PerChat/PerUserAndChat memory scopes. Marks ADR 0026 as superseded.

* Add breaking-change v2.0-only disclaimer to package metadata

Augments the package Description and adds PackageReleaseNotes stating this release targets the Foundry Responses container protocol v2.0 only, is not compatible with v1, and directs consumers to a previous release for the v1 protocol definition.

* Address review comments: dead chat-key surface and weak test assertions

Fixes the automated review findings: the MemoryAgent/AgentSkills .env.example now say one variable (only HOSTED_USER_ISOLATION_KEY remains); the MemoryAgent smoke script drops the unused ChatKey parameter and its call-site arguments; HostedConversationKey null test now exercises a real null (and whitespace); and the reuse-one-session test asserts an exact SessionCount of 1 instead of <= 1.
2026-06-29 16:39:54 -07:00
SergeyMenshykh cb8cef3ef6 .NET: Improve proxy target validation in DevUI aggregator (#6771)
* Improve proxy target validation in DevUI aggregator

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fail closed on malformed proxy target URIs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add direct coverage for proxy target validation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Apply arrange-act-assert structure to aggregator tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix formatting in aggregator tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-28 18:32:01 +00:00
Giles Odigwe d5c5fb9d3d .NET: Enforce ApprovalRequiredAIFunction in GitHub Copilot provider via OnPreToolUse hook (#6674)
* .NET: Enforce ApprovalRequiredAIFunction in GitHub Copilot provider

The GitHub Copilot SDK owns the tool-calling loop and invokes registered
custom functions directly, so the standard FunctionInvokingChatClient
approval round-trip never runs for this provider. As a result a tool wrapped
in ApprovalRequiredAIFunction (only a marker) could execute without any
Agent Framework approval.

Add an agent-level onFunctionApproval callback and wrap approval-required
tools in an ApprovalGatedAIFunction that enforces approval before invoking
the underlying function. Secure-by-default: with no callback, or when the
callback denies or throws, execution is denied. The gate forwards tool
metadata (including the Copilot skip_permission flag) so it stays
transparent to the SDK. This mirrors the Python provider's behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* .NET: Propagate cancellation from GitHub Copilot approval callback

Let OperationCanceledException propagate from the approval callback instead
of swallowing it into a denial, so cooperative cancellation is honored.
Other callback failures still deny by default. Added a unit test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* .NET: Enforce ApprovalRequiredAIFunction via Copilot SDK OnPreToolUse hook

Replace the custom approval enforcement (ApprovalGatedAIFunction wrapper +
onFunctionApproval callback) with the GitHub Copilot SDK's native OnPreToolUse
hook, which the SDK already provides for pre-execution gating.

When a tool wrapped in ApprovalRequiredAIFunction is registered and the caller
hasn't supplied their own OnPreToolUse hook, the agent installs a default hook
that returns "ask" for those tools (routing the decision to OnPermissionRequest)
and defers (null) for all other tools, preserving today's behavior for
non-approval tools. If the caller supplies their own OnPreToolUse hook, it takes
precedence and they own approval handling; the agent logs a warning naming any
approval-required tool that will not be auto-gated, and the behavior is
documented. Adds an optional ILoggerFactory parameter for the warning.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* .NET: Address PR review feedback on GitHub Copilot approval hook

- Build the approval-required tool-name HashSet directly instead of via an
  intermediate List.
- Remove the redundant MEAI001 NoWarn suppression (tests already suppress it via
  .editorconfig and the source project builds clean without it).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-27 01:22:47 +00:00
SergeyMenshykh 846c963e85 .NET: Add description attribute to resource and script elements in skill body (#6759)
Include the optional description attribute on <resource> and <script>
elements within <available_resources> and <available_scripts> blocks,
aligning .NET with the Python implementation. The description is emitted
only when non-null/non-empty and is XML-escaped.

Co-authored-by: Marco Minerva <marco.minerva@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-26 22:46:56 +00:00
SergeyMenshykh e0274b764e .NET: Extract caching from AgentSkillsProvider into CachingAgentSkillsSource (#6768)
Move the cache-once-then-replay logic out of AgentSkillsProvider into a
new CachingAgentSkillsSource decorator following the DelegatingAgentSkillsSource
pattern used by DeduplicatingAgentSkillsSource and FilteringAgentSkillsSource.

- Add internal CachingAgentSkillsSource (lock-free, thread-safe; clears on failure)
- AgentSkillsProviderBuilder applies caching after aggregation, before filter/dedup
- Add builder DisableCaching() opt-out method
- Convenience constructors wrap with CachingAgentSkillsSource before dedup
- Remove DisableCaching from AgentSkillsProviderOptions
- Add CachingAgentSkillsSourceTests

Co-authored-by: SergeyMenshykh <SergeMenshikh@outlook.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-26 22:29:35 +00:00
SergeyMenshykh d09451408f Disable failing DurableTask and AzureFunctions integration tests (#6774)
Skip the following tests that are persistently failing in CI:

DurableTask - AgentEntityTests:
- EntityNamePrefixAsync
- RunAgentMethodNamesAllWorkAsync
- OrchestrationIdSetDuringOrchestrationAsync

DurableTask - ExternalClientTests:
- SimplePromptAsync
- CallFunctionToolsAsync
- CallLongRunningFunctionToolsAsync

DurableTask - WorkflowConsoleAppSamplesValidation:
- ConcurrentWorkflowSampleValidationAsync
- WorkflowAndAgentsSampleValidationAsync

DurableTask - ConsoleAppSamplesValidation:
- SingleAgentSampleValidationAsync
- SingleAgentOrchestrationChainingSampleValidationAsync
- MultiAgentConcurrencySampleValidationAsync
- MultiAgentConditionalSampleValidationAsync

AzureFunctions - SamplesValidation:
- SingleAgentSampleValidationAsync
- MultiAgentOrchestrationConcurrentSampleValidationAsync
- MultiAgentOrchestrationConditionalsSampleValidationAsync
- LongRunningToolsSampleValidationAsync
- AgentAsMcpToolAsync

AzureFunctions - WorkflowSamplesValidation:
- WorkflowAndAgentsSampleValidationAsync
- ConcurrentWorkflowSampleValidationAsync

Related to: microsoft/agent-framework#6732

Co-authored-by: SergeyMenshykh <SergeMenshikh@outlook.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-26 21:31:08 +00:00
Tommaso Stocchi daac8c15f3 .NET: Prefer HTTPS backends in Aspire DevUI (#6772)
Prefer allocated HTTPS endpoints when resolving Aspire DevUI backends and fall back to HTTP for existing services. Update the DevUI Aspire sample so WriterAgent exercises HTTPS redirection.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-26 18:15:51 +00:00