main
29 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e6536fb459 |
Python: Align AG-UI run continuity (#7662)
* Python: Align AG-UI run continuity Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: aadad05d-2646-405f-8c62-a7a223abfc92 * Python: Refine AG-UI continuation ownership Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: aadad05d-2646-405f-8c62-a7a223abfc92 * Python: Persist AG-UI checkpoint ownership Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: aadad05d-2646-405f-8c62-a7a223abfc92 --------- Copilot-Session: aadad05d-2646-405f-8c62-a7a223abfc92 |
||
|
|
58da0cc253 |
Python: add MiddlewareFailure, a first-class fatal signal for function middleware (#7562)
* feat(core): first-class fatal signal (MiddlewareFailure) for function middleware The function-invocation loop converts every exception raised by function middleware into a tool-error result and keeps looping, so middleware that needs fail-closed semantics (enforcement layers, guardrails) had no loud escape: the agent-hooks feature simulated one by mutating shared run state, raising MiddlewareTermination, and re-raising the real failure two hops away at the run boundary. Introduce MiddlewareFailure (a MiddlewareException sibling of MiddlewareTermination) as the loop's explicit fail-closed escape: - _auto_invoke_function re-raises it (both the direct and the pipeline path) instead of absorbing it into a tool-error result; ordinary exceptions keep the absorb-and-continue contract. - A failing call fails the whole parallel batch: in-flight sibling tool tasks are cancelled and awaited before the failure propagates. - Every existing MiddlewareTermination absorb site (agent/chat pipelines, _execute_single_function_call, harness loop, purview) passes it through untouched by construction, and agent/chat middleware exceptions already propagate, so one exception type gives uniform fail-loud semantics across all three categories. Migrate the agent-hooks feature to the new signal: delete the _RunState.halted back-channel and its three run-boundary re-raise checks, drop the halted arm of the termination special case in the function middleware (the approval-request pass-through moves to the single approval check on the normal path), and fail partial installs loudly. Tool-seam host_error blocks keep surfacing as InterceptionBlocked at the run boundary via the exception cause chain (one deny surface at every seam, pinned by tests). Spec 004 gains the middleware-failure invariants and matrix rows. Closes #7522 Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com> * fix(core): harden tool-seam unwrap and pin review findings Review round follow-ups for the MiddlewareFailure feature: - Only agent-hooks' own tagged tool-seam halts (_ToolSeamBlockFailure) authorize re-raising the chained InterceptionBlocked at the run boundary; a third-party MiddlewareFailure with a crafted InterceptionBlocked cause now propagates as raised instead of laundering an attacker-shaped interception record into the feature's deny surface (regression test added, verified by mutation). - Document that middleware must not catch MiddlewareFailure (docstring and spec 004): swallowing it converts a fail-closed abort back into a running, possibly unguarded loop. - Pin the trailing termination re-raise in the agent-hooks function middleware: an inner short-circuit is bracketed and still propagates, skipping outer middleware post-code (test fails with the re-raise removed). Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com> * fix(core): acyclic tool-seam unwrap chain; document cooperative batch cancellation Address two automated-review findings on the MiddlewareFailure PR, both confirmed empirically: - _reraise_tool_seam_block created a two-object exception-chain cycle (block.__cause__ -> wrapper -> block) by re-raising the chained InterceptionBlocked `from` its transport wrapper. Detach the wrapper's back-links and re-raise bare, recording the wrapper as the block's __context__ — acyclic, both exceptions still visible in tracebacks. Regression test walks the chain and pins finiteness (verified to fail against the cyclic re-raise). - Batch cancellation is cooperative: a synchronous tool body already running in a worker thread (asyncio.to_thread) cannot be interrupted by task cancellation and may complete its side effects after the failure reached the caller; its result is discarded either way and propagation is not delayed behind it. Narrow the stated contract (MiddlewareFailure docstring, loop comment, spec 004) and pin it with a blocking-sync-sibling regression test. Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com> * fix(core): settle dangling calls on service-managed conversations on abort Address maintainer review on the MiddlewareFailure PR: - A MiddlewareFailure escaping a tool batch on a service-managed conversation left the hosted thread ending in unresolved function_call items: _update_continuation_state persists session.service_session_id when the model turn completes (before tool execution), and probe-verified the next run sends only the new user message against that conversation — OpenAI-style continuations reject such a request, so a routine policy abort left the session permanently stuck. Both loops now settle the thread before propagating: one error function_result per dangling call, submitted with tool_choice="none" in a single extra request whose response is discarded; a settlement failure never masks the abort, and runs without a service-managed conversation make no extra request. Pinned by three regression tests (non-streaming, streaming, and the no-conversation no-cost case); spec 004 and the MiddlewareFailure docstring updated. - Make the three tool-bracket escape tuples in the agent-hooks function middleware identical (MiddlewareTermination, MiddlewareFailure, CancelledError): a MiddlewareFailure raised inside the post/error-bracket emit bodies is unreachable today, but the uniform tuples remove the need to reason about why they would differ, and preserve the exact exception (including the private tool-seam tag) if the emitter ever surfaces one. Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com> * fix(core): advance settled continuation; settle approved-replay aborts Address maintainer review on the MiddlewareFailure settlement path, both probe-verified (branch rebased onto current main first): - Advance the persisted continuation to the settlement response. For response-ID continuations (OpenAI Responses store=True, where the response id is the continuation handle) the settlement response is the first endpoint whose chain includes the synthetic tool outputs; leaving session.service_session_id on the pre-settlement response made the settlement ineffective — the next run would continue from the still-unresolved turn. The settlement response now runs through _update_function_invocation_continuation_state (a no-op for stable conversation-object ids). Pinned by a regression test that fails with the advance removed. - Cover the approval-resolution phase: a MiddlewareFailure raised while an approved tool is replayed escapes loudly (probe-verified, already the case) but executed before the loops' settlement seams, leaving the original — already service-persisted — call unresolved. _resolve_approval_responses now takes a settle_dangling_calls callback invoked with the approved batch on abort; the settlement helper became a layer method taking explicit calls (approval-response wrappers unwrap to their underlying calls, hosted-tool approvals are left to their provider protocol) and carries its own best-effort containment. Pinned by deny-during- replay regression tests in both response modes, mutation-verified. Spec 004 invariants and matrix rows updated accordingly. Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com> --------- Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com> |
||
|
|
e289320027 |
Python: Add approval storage and improve truth checks (#7631)
* Add approval storage and improve truth checks * Address PR comments * Update spec * Revert changes to agui since it is already handled in another pr * Add missed change |
||
|
|
8c4da3c3b9 |
Python: Harden AG-UI approval lifecycle and resume semantics (#7594)
* Route local approvals through lifecycle owner Key decisions: - Add an internal typed approval lifecycle with pending, claimed, executing, and settled states. - Keep authorization separate from execution; only LocalPendingToolTransitionOwner invokes approved local calls. - Register server-owned occurrences before canonical ResumeDecision claims and retain one replayable result under the original call identity. Files changed: - packages/ag-ui/agent_framework_ag_ui/_approval_lifecycle.py - packages/ag-ui/agent_framework_ag_ui/_approval_state.py - packages/ag-ui/agent_framework_ag_ui/_agent_run.py - packages/ag-ui/tests/ag_ui/test_approval_lifecycle.py - packages/ag-ui/tests/ag_ui/test_approval_result_event.py - packages/ag-ui/tests/ag_ui/test_agent_wrapper_comprehensive.py Verification: - 952 AG-UI tests passed. - Focused lifecycle/public tracer passed with warnings treated as errors. - Ruff format/check and AG-UI Pyright passed. - git diff --check passed. Notes for next iteration: - The function-calling-loop scenario mapping is inaccessible under the organization content-exclusion policy and could not be updated. - The workspace Poe package fan-out is blocked by the pre-existing missing packages/durabletask/pyproject.toml; equivalent package-local checks were run. * Make approval batches occurrence-safe Key decisions: - Give each local approval a scoped logical occurrence identity and share one occurrence across trusted thread aliases. - Validate complete Resume Decision batches before applying claims, then account for accepted, rejected, and cancelled occurrences independently. - Preserve sibling authority and original result identity across failures, mixed decisions, and reused raw call IDs. Files changed: - packages/ag-ui/agent_framework_ag_ui/_approval_lifecycle.py - packages/ag-ui/agent_framework_ag_ui/_approval_state.py - packages/ag-ui/agent_framework_ag_ui/_agent_run.py - packages/ag-ui/tests/ag_ui/test_approval_lifecycle.py - packages/ag-ui/tests/ag_ui/test_agent_wrapper_comprehensive.py Verification: - 959 AG-UI tests passed with 90% lifecycle branch coverage. - 30 focused lifecycle/public tracer tests passed with warnings treated as errors. - Ruff format/check and AG-UI Pyright passed. - git diff --check passed. Notes for next iteration: - The function-calling-loop scenario mapping remains inaccessible under the organization content-exclusion policy. - Workspace typing fan-out remains blocked by the pre-existing missing packages/durabletask/pyproject.toml; package-local Pyright passed, while package-local MyPy retains three unrelated baseline errors. * Make approval resume retries idempotent Key decisions: - Retain terminal decisions and outcomes by scoped occurrence so identical accepted and rejected retries reproject results without granting execution authority again. - Reject conflicting names, arguments, decisions, wrong-scope lookups, and expired authority before an execution intent can reach the local transition owner. - Keep protocol normalization in the runner while using server-owned lifecycle context to canonicalize retries and preserve existing AG-UI wire aliases. Files changed: - packages/ag-ui/agent_framework_ag_ui/_approval_lifecycle.py - packages/ag-ui/agent_framework_ag_ui/_agent_run.py - packages/ag-ui/tests/ag_ui/test_approval_lifecycle.py - packages/ag-ui/tests/ag_ui/test_agent_wrapper_comprehensive.py - packages/ag-ui/tests/ag_ui/test_endpoint.py Verification: - 965 AG-UI tests passed with 90% approval lifecycle coverage. - 18 focused lifecycle, hostile-resume, wrong-thread, and endpoint retry tests passed with runtime and deprecation warnings treated as errors. - Ruff format/check and AG-UI package-local Pyright passed. - git diff --check passed. Notes for next iteration: - Terminal retention is process-local and unbounded until the later bounded-retention issue adds its explicit policy. - The function-calling-loop scenario mapping remains inaccessible under the organization content-exclusion policy. * Separate approval execution ownership Key decisions: - Carry explicit local, hosted, deferred in-run, or unavailable ownership on every approval occurrence and authorized intent. - Keep lifecycle authorization separate from execution; local calls execute only through the local adapter while hosted and setup-injected decisions forward through owner-specific adapters. - Leave declaration-only calls pending when no transition owner can act, and settle forwarded outcomes against the original occurrence without local fallback. Files changed: - packages/ag-ui/agent_framework_ag_ui/_approval_lifecycle.py - packages/ag-ui/agent_framework_ag_ui/_approval_state.py - packages/ag-ui/agent_framework_ag_ui/_agent_run.py - packages/ag-ui/tests/ag_ui/test_approval_lifecycle.py - packages/ag-ui/tests/ag_ui/test_endpoint.py Verification: - 967 AG-UI tests passed with 92% package coverage and 89% approval lifecycle coverage. - 94 focused lifecycle, hosted, deferred-owner, hostile-resume, and approval tests passed. - Ruff format/check and package-local Pyright passed. - git diff --check passed. Notes for next iteration: - Executing-without-outcome recovery remains for the indeterminate execution-window issue. - The function-calling-loop scenario mapping remains inaccessible under the organization content-exclusion policy. - Workspace Poe fan-out remains blocked by the pre-existing missing packages/durabletask/pyproject.toml; equivalent package-local checks passed. * Represent approval execution uncertainty Key decisions: - Distinguish reserved claims from execution windows that may have started an external side effect. - Recover non-idempotent execution failures as indeterminate and reject identical retries without another invocation. - Permit claim release only under an explicit safe policy and execution retry only with a predeclared idempotency key shared by local and forwarded owners. Files changed: - packages/ag-ui/agent_framework_ag_ui/_approval_lifecycle.py - packages/ag-ui/tests/ag_ui/test_approval_lifecycle.py - packages/ag-ui/tests/ag_ui/test_endpoint.py Verification: - 972 AG-UI tests passed with 92% line coverage and 89% package branch coverage. - 23 focused lifecycle, duplicate-resume, hosted-owner, and public settlement-window tests passed. - Package-local Ruff and Pyright passed; git diff --check passed. Notes for next iteration: - The function-calling-loop scenario mapping remains inaccessible under the organization content-exclusion policy. - Workspace Poe fan-out remains blocked by the pre-existing missing packages/durabletask/pyproject.toml; equivalent package-local checks passed. * Reconcile approval snapshots with lifecycle state Key decisions: - Keep Approval State authoritative and emit typed snapshot reconciliation keyed by logical occurrence identity. - Retire settled, rejected, cancelled, expired, indeterminate, and missing controls while preserving nonterminal authority. - Reconcile stale snapshots before hydration or resume, and retain lifecycle deduplication when snapshot saves fail. Files changed: - packages/ag-ui/agent_framework_ag_ui/_approval_lifecycle.py - packages/ag-ui/agent_framework_ag_ui/_agent_run.py - packages/ag-ui/agent_framework_ag_ui/_snapshot_session.py - packages/ag-ui/tests/ag_ui/test_approval_lifecycle.py - packages/ag-ui/tests/ag_ui/test_endpoint.py Verification: - 975 AG-UI tests passed with 92% package coverage and 89% approval lifecycle coverage. - Package-local Ruff and Pyright passed; git diff --check passed. Notes for next iteration: - The function-calling-loop scenario mapping remains inaccessible under the organization content-exclusion policy. - Workspace Poe fan-out remains blocked by the pre-existing missing packages/durabletask/pyproject.toml; equivalent package-local checks passed. * Bound process-local approval lifecycle state Key decisions: - Protect pending, claimed, executing, and indeterminate occurrences from eviction while retaining terminal outcomes for a configurable 15-minute process-local deduplication window. - Serialize complete approval batches by logical occurrence locks so aliases share atomic decisions and independent batches can progress concurrently. - Fail capacity, claim, and settlement conflicts explicitly, and emit redacted structured lifecycle telemetry without tool names, arguments, or approval payloads. - Remove legacy LRU eviction paths so active Approval State and middleware state are never silently discarded. Files changed: - packages/ag-ui/agent_framework_ag_ui/_approval_lifecycle.py - packages/ag-ui/agent_framework_ag_ui/_approval_state.py - packages/ag-ui/agent_framework_ag_ui/_agent_run.py - packages/ag-ui/tests/ag_ui/test_approval_lifecycle.py - packages/ag-ui/tests/ag_ui/test_approval_state.py Verification: - 982 AG-UI tests passed with 92% package coverage and 91% approval lifecycle coverage. - 34 focused lifecycle and storage tests passed with RuntimeWarning and DeprecationWarning treated as errors. - Package-local Ruff and Pyright passed; git diff --check passed. Notes for next iteration: - The function-calling-loop scenario mapping remains inaccessible under the organization content-exclusion policy. - Workspace Poe fan-out remains blocked by the pre-existing missing packages/durabletask/pyproject.toml; equivalent package-local checks passed. * Complete approval lifecycle cutover Key decisions: - Make ApprovalLifecycle the sole owner of trusted aliases, occurrence metadata, authority transitions, and retained outcomes. - Remove the parallel mutable pending-approval registry and route local, hosted, deferred, cancellation, replay, and snapshot reconciliation through lifecycle occurrences. - Encapsulate middleware Approval State behind copy-isolated store methods while keeping AG-UI protocol normalization and event projection in the runner. Files changed: - packages/ag-ui/AGENTS.md - packages/ag-ui/agent_framework_ag_ui/_agent.py - packages/ag-ui/agent_framework_ag_ui/_agent_run.py - packages/ag-ui/agent_framework_ag_ui/_approval_lifecycle.py - packages/ag-ui/agent_framework_ag_ui/_approval_state.py - packages/ag-ui/tests/ag_ui/test_agent_wrapper_comprehensive.py - packages/ag-ui/tests/ag_ui/test_approval_lifecycle.py - packages/ag-ui/tests/ag_ui/test_approval_result_event.py - packages/ag-ui/tests/ag_ui/test_approval_state.py - packages/ag-ui/tests/ag_ui/test_endpoint.py - packages/ag-ui/tests/ag_ui/test_run.py Verification: - 964 package-local AG-UI tests passed with 92% coverage and 90% approval lifecycle coverage. - 85 warning-strict focused approval tests passed. - Package-local Ruff and Pyright passed; git diff --check passed. Notes for next iteration: - The function-calling-loop scenario mapping remains inaccessible under the organization content-exclusion policy. - Workspace Poe fan-out remains blocked by the pre-existing missing packages/durabletask/pyproject.toml; equivalent package-local checks passed. * Align AG-UI approval resumes with protocol * Align workflow approvals with AG-UI resumes * Address AG-UI approval review findings * fix AG-UI test typing checks * fix AG-UI approval retention and cancellation retries |
||
|
|
5fafa18569 | Python: track agent-hooks feature usage (#7558) | ||
|
|
e926ad2859 |
Python: fix streaming transcript duplication with message injection and per-service-call persistence (#7605)
* Fix ordering issue when streaming with content injection and per-service-call persistence * Update spec * Address PR comment * revert uv.lock changes |
||
|
|
e85b3c8ba8 |
Python: Fix FHA session ID translation (#7608)
* Fix FHA session ID traslation * Fix tests * Address comments and fix tests * Fix typing * Show how to use user created sessions * Update README |
||
|
|
48e547506b |
Python: Make encrypted reasoning opt-in for Foundry chat (#7536)
* Python: Make Foundry encrypted reasoning opt-in * Python: Opt hosted replay test into encrypted reasoning |
||
|
|
c987529df3 |
.NET: [BREAKING] Rename to AgentIsolationKeyProvider (#7567)
* Update store isolation documentation Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 824a2e29-e79c-42aa-b28e-aa6c12ec3292 * Rename store isolation key provider Rename the shared session isolation abstraction to reflect its use for both session and task stores. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 824a2e29-e79c-42aa-b28e-aa6c12ec3292 * Rename to AgentIsolationKeyProvider per review feedback Drops the `Store` qualifier and keeps an `Agent` prefix so the type is not confused with generic isolation-key abstractions from other libraries, while leaving room for future non-store isolation (memory, retrieval). - StoreIsolationKeyProvider -> AgentIsolationKeyProvider - ClaimsIdentityStoreIsolationKeyProvider(+Options) -> ClaimsIdentityAgentIsolationKeyProvider(+Options) - GetStoreIsolationKeyAsync -> GetIsolationKeyAsync - UseClaimsBasedStoreIsolation -> UseClaimsBasedAgentIsolation XML docs now state that the `Agent` prefix identifies the hosting API domain and does not mean agent instances are isolated. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 824a2e29-e79c-42aa-b28e-aa6c12ec3292 * Update hosting spec for AgentIsolationKeyProvider rename Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 824a2e29-e79c-42aa-b28e-aa6c12ec3292 --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 824a2e29-e79c-42aa-b28e-aa6c12ec3292 |
||
|
|
5f3ca8f93c |
Python: Fix AG-UI approval resume at the protocol boundary (#7480)
* Python: Fix Ollama approval resume message handling * Python: Reject empty Ollama approval resume payload * Python: Keep AG-UI approval controls out of provider input * Python: Do not trust pending AG-UI tool results |
||
|
|
07511b80c9 |
Python: Prevent orphaned local approval responses (#7462)
* Python: Prevent orphaned local approval responses Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0efaca91-a0a7-46f4-9b81-022385607fe4 * Python: Clarify approval serialization boundaries Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0efaca91-a0a7-46f4-9b81-022385607fe4 --------- Copilot-Session: 0efaca91-a0a7-46f4-9b81-022385607fe4 |
||
|
|
28389df805 |
Python: Move SessionStore to core and persist Foundry Responses sessions (#7306)
* Python: Move session persistence into core Move SessionStore and durable msgspec-backed storage into core, restore sessions in Foundry Responses hosting with per-user isolation, and document the serialization design. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Python: Address session persistence review feedback Harden scoped file paths and corruption recovery, preserve session serialization compatibility, clarify dependency placement, and add reproducible benchmark evidence. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Python: Preserve session snapshot compatibility Deep-copy in-memory session writes and retain existing Telegram session keys so stored conversations continue resolving. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Python: Simplify Foundry session isolation Add experimental FoundrySessionStore backed by Agent Server request context, remove resolver plumbing, and centralize v2 user isolation for sessions, checkpoints, and approvals. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Python: Reduce Foundry session helper layering Inline the single-use request user accessor while keeping separate context validation, fingerprint, and directory helpers for their distinct callers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Python: Clarify Foundry request context validation Separate fail-fast request validation from context retrieval so Responses no longer appears to discard a returned context. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Python: Share Foundry request context helpers Move protocol validation and user-scope derivation into a dedicated request-context module, leaving the session-store module focused on storage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Restore Foundry checkpoint storage paths Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Simplify Foundry session storage paths Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Persist Foundry sessions under hosted home Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Make hosted path test platform independent Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Address session persistence review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Isolate Foundry session path handling Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Clarify Foundry session path terminology Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Align Foundry sessions with Responses continuity Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Finalize Foundry Responses session persistence Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Add session store feature usage telemetry Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c * Fix hosted per-call history persistence Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c --------- Copilot-Session: 3e5c81ad-75e8-4e92-a883-8bbd676c6c8c |
||
|
|
99dcf3c133 |
Python: Preserve declaration-only streaming metadata (#7409)
* Python: Preserve declaration-only streaming metadata Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 * Chore: retrigger PR checks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 * Python: Reconcile remaining function-loop spec gaps Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 |
||
|
|
95ec5b7d36 |
Python: Preserve approval decisions under OpenAI continuation (#7407)
* Python: Preserve approval decisions under OpenAI continuation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 * Chore: retrigger PR checks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 |
||
|
|
0937233d86 |
Python: Remove tool content returned after invocation limits (#7408)
* Python: Remove tool content returned after invocation limits Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 * Chore: retrigger PR checks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 * Python: Preserve provider-owned content after limits Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 * Python: Isolate post-limit spec update Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 |
||
|
|
572a9621bd |
Python: Keep call and result occurrences atomic in compaction (#7406)
* Python: Keep call and result occurrences atomic in compaction Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 * Python: Clarify ambiguous compaction reannotation Document why incremental reannotation retains all prior duplicate candidates and strengthen the regression that keeps ambiguous results unpaired without changing existing groups. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 * Python: Handle assistant-embedded compaction results Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 |
||
|
|
e344f456ae |
Python: Correlate AG-UI confirm_changes snapshots by call id (#7411)
* Python: Correlate AG-UI confirm_changes snapshots by call id Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 * Chore: retrigger PR checks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 * Python: Require real results for accepted confirmations Keep accepted confirm_changes snapshot payloads inert unless approval resolution produced a matching function result, while retaining explicit rejection cleanup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 |
||
|
|
e18a64569c |
Python: Defer provider-injected approvals to in-run execution (#7410)
* Python: Defer provider-injected approvals to in-run execution Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 * Python: Remove vacuous AG-UI approval test Drop the forged-approval test that was stripped by pending-approval validation; the real pause-approve-resume regression remains the authoritative provider-injected coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 |
||
|
|
5987a6791b |
Python: Improve function approval resume and replay (#7345)
* Python: Harden function approval resume and replay Make approval resume immutable and occurrence-aware, return grouped approved and rejected results consistently, preserve pending approval history without model-orphaned calls, and align streaming, non-streaming, and AG-UI result boundaries. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 * Python: Clarify function invocation orchestration Simplify approval-resolution setup and add phase-level comments around the key function invocation orchestration paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 EOF && git push origin python-approval-resume-contract --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1 |
||
|
|
5f84917f15 |
docs: ADR-0033 feature-usage bitmask in the User-Agent (#6500)
* docs: ADR-0027 feature-usage bitmask in the User-Agent Add an ADR, design spec, and per-language bit registry for a lightweight feature-usage signal: a 64-bit mask, emitted as a `(feat=vN.<hex>)` User-Agent comment, stamped per request on first-party (Azure/Foundry) clients only. - docs/decisions/0027-feature-usage-bitmask-user-agent.md — ADR (options-first, with Limitations, Open Questions, and v1->v2 migration) - docs/specs/002-feature-usage-telemetry.md — design spec + implementation plan - docs/specs/feature-usage-bit-registry.md — per-language bit tables + governance Granularity is per package with core broken out per feature (each orchestration pattern and built-in context/history provider). Registries are per language (decoder selects by the language already in the UA). OpenTelemetry emission is deferred (privacy). Docs only; no code changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: fix dead links to removed registry JSON in ADR-0027 The registry JSON was consolidated into feature-usage-bit-registry.md; point the ADR's two remaining links at the markdown instead of the deleted file (fixes markdown-link-check 404s). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: address review — drop JSON-parity wording, clarify per-language decode - ADR option J: the parity test compares the enum against the per-language table in the registry doc, not a (now-removed) JSON file. - Spec .NET mapping: the wire format is shared, but the mask is decoded per-language (select the table via the UA product token) — fixes the "decoded numbers mean the same thing in both SDKs" wording that conflicted with the per-language, non-synchronized bit indexes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: add dedicated mask-only opt-out env var (AGENT_FRAMEWORK_FEATURE_MASK_DISABLED) Re-introduce a dedicated opt-out that disables only the feature mask while keeping the base agent-framework-<lang>/{version} User-Agent, alongside the existing AGENT_FRAMEWORK_USER_AGENT_DISABLED (whole UA). Updates the spec accumulator gate, API surface, opt-out table and examples; the registry opt-out section; and the ADR (decision outcome, consequences, open questions -> decided). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: add prior-art comparison (AWS botocore m/, Stainless, Azure, etc.) Add a Prior art section to ADR-0027 surveying how comparable SDKs encode identity/usage in the User-Agent or sidecar headers, with citations: - AWS botocore `m/` feature-code list — the direct analog (per-request, usage-based feature flags in the UA); contrasts short-code set vs our hex bitmask. - OpenAI/Anthropic Stainless `X-Stainless-*` headers (static identity). - Azure azure-core UserAgentPolicy + AZURE_TELEMETRY_DISABLED. - Google x-goog-api-client; LangSmith version token + tracing opt-in. Also add an Open Question on honoring the cross-tool DO_NOT_TRACK convention. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: fold in botocore lessons; record accumulation-scope decision botocore's m/ feature list scopes features to a per-request contextvars set that resets between calls — clean per-call attribution, but it assumes every feature lives inside a service request. That holds for an SDK natively bound to its own services; it does not for us, where many features (agent/workflow/provider construction, session setup) are not bound to any request. - ADR: add Accumulation scope options — P (process-global monotonic, chosen) vs Q (botocore per-request set, rejected) with the request-binding rationale; reference P in the decision; reframe the "no per-call attribution" limitation as a deliberate scope choice. - ADR Prior art: bitmask gives bounded token size for free (vs botocore's 1024-byte cap + truncation); mechanism is private, wire format is the contract; fix a duplicated phrase. - Spec: note the mask is process-global, monotonic, never reset (intentional, lock/Interlocked.Or-safe), the token is safe-by-construction (no sanitization), and the helpers are private API. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: update feature mask ADR Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: refresh feature usage telemetry design Rebase the proposal on current main, renumber it to ADR-0033/SPEC-004, and reconcile the registry and implementation notes with current Python and .NET surfaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: expand feature usage mask to 128 bits Repartition the v1 registries with additional skill categories, define the bit-allocation tenet, and document the two-lane .NET accumulator and 128-bit decoder contract. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 346bf168-b668-4c4a-a8db-a67282ee5e5f * docs: tighten feature telemetry activation and scoping Require approved pipeline and actual-origin classification, preserve OpenAI transport defaults, use activation-based marking, and move index ownership into packages with parity and no-overlap validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 346bf168-b668-4c4a-a8db-a67282ee5e5f * docs: preserve SDK transport defaults for telemetry Record the transport-preservation requirement at the ADR decision level. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 346bf168-b668-4c4a-a8db-a67282ee5e5f * docs: split declarative agent and workflow usage Allocate separate adjacent v1 indexes for declarative agents and declarative workflows in Python and .NET, shifting later unreleased rows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 346bf168-b668-4c4a-a8db-a67282ee5e5f * docs: accept feature usage telemetry ADR Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 346bf168-b668-4c4a-a8db-a67282ee5e5f * docs: record feature telemetry ADR participants Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 346bf168-b668-4c4a-a8db-a67282ee5e5f * docs: expand feature telemetry ADR consultation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 346bf168-b668-4c4a-a8db-a67282ee5e5f * docs: clarify feature telemetry semantics Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 346bf168-b668-4c4a-a8db-a67282ee5e5f --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 346bf168-b668-4c4a-a8db-a67282ee5e5f |
||
|
|
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
|
||
|
|
a1f3e536bc |
Python: Add MCP hosting helpers (#7209)
* Python: Add MCP hosting helpers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607 * Python: Address MCP hosting review comments Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607 * renamed to AgentMCPTool |
||
|
|
b5e635ed4d |
Python: isolate hosted session snapshots (#7141)
* Python: isolate hosted session snapshots Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 75d26ffd-7dc7-46b3-9966-9aaebb7b6bc3 * Python: avoid duplicate conversation snapshots Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 75d26ffd-7dc7-46b3-9966-9aaebb7b6bc3 * added some notes in the docstring |
||
|
|
bc59c72170 |
Python: Add A2A hosting helpers (#7050)
* Python: Add A2A hosting helpers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607 * Python: Preserve final A2A streaming output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607 * Python: Clarify A2A conversion boundary Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607 * Python: Document A2A sample auth boundary Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
7ca8bb55b6 |
Python: Add Telegram hosting helpers and samples (#7047)
* Python: Add Telegram hosting helpers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607 * Python: Exclude Telegram samples from aggregate typing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607 * Python: Address Telegram helper review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607 * Python: Serialize Telegram webhook sessions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d76a9c32-d170-426d-a64f-b70958b08b12 |
||
|
|
1aca7601b8 |
Python: Add hosting protocol helper surface (#6891)
* Add Python hosting protocol helper surface Introduce AgentFrameworkState and SessionStore for app-owned hosting routes, add Responses run conversion/rendering helpers, and update the local Responses sample to use native FastAPI routing with streaming support. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CI failures, session continuity, and streaming model reporting - Fix constrained TargetT TypeVar in AgentFrameworkState: split __init__ into per-shape overloads (instance/sync factory/async factory/awaitable) since a bound TypeVar combined with one big Callable/Awaitable union parameter was unsolvable across pyright/pyrefly/ty/zuban. - Fix _FakeAgent test fixtures to structurally satisfy SupportsAgentRun (matching attribute types and overloaded run()), which the above surfaced. - Add SessionStore.put() to alias an additional session id to an already-resolved session, and use it in the local_responses sample to fix a real session-continuity bug: previous_response_id rotates every turn, so without aliasing the newly minted response id, turn 3+ of a conversation silently lost all prior history. Verified against a live Foundry model across a 3-turn conversation. - Fix responses_stream_events_from_run to report the real model instead of the "agent" fallback: AgentResponse.from_updates never carries a raw representation forward, so capture model from the individual streamed updates' raw representations instead. Verified live. - Add response_model=None to the sample's FastAPI route (it could not boot at all: FastAPI tried to build a Pydantic response model from the JSONResponse | StreamingResponse return annotation). - Map responses_to_run's ValueError to HTTP 400 instead of a 500. - Add HTTP round-trip integration tests (packages/hosting-responses) that exercise the same FastAPI + AgentFrameworkState + Responses helper wiring as the sample via httpx.ASGITransport, including a regression test for the session-continuity fix. - Add Workflow-target test coverage, SessionStore.put/reset_session tests, and TypeError-path coverage to packages/hosting/tests/hosting/test_state.py. - Extend call_server.py / call_server_af.py to a third conversation turn so they actually exercise the continuity chain (previous scripts stopped at turn 2, which would never have revealed the bug above). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify session-continuity aliasing: fold put() into get() Per feedback: the growth of SessionStore was not the problem -- it's intentional, since OpenAI's previous_response_id is designed to let a caller continue (fork) from any earlier response, not just the latest one, so every response id has to stay independently resolvable. That part stays as-is. What was too complex was the call site: routes had to manually fetch a session and then conditionally alias it with a separate put() call. Folded that into a single get(session_id, alias=...) call instead: - SessionStore.get() gains an optional `alias` keyword that registers an additional id for the same session in the same call (no-op if alias is None or equal to session_id). Removed the separate put() method. - AgentFrameworkState.get_session() passes `alias` through. - local_responses sample and the HTTP round-trip integration tests now do `await state.get_session(lookup_id, alias=response_id)` instead of pulling the store out and orchestrating get()/put() by hand. - Documented that this in-memory SessionStore intentionally never evicts (by design, to support forking), and that a storage-backed replacement (Redis, a database, ...) is responsible for its own TTL/eviction policy. Verified against a live Foundry model across a 3-turn previous_response_id chain after the simplification. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Refine hosting state helpers Split the shared state surface into AgentState and WorkflowState, keep SessionStore and CheckpointStore as plain storage, and make state helpers responsible for get-or-create behavior. Update the Responses sample and HTTP round-trip tests to store the post-run session explicitly under the minted response id, and support WorkflowBuilder/orchestration-style builders via structural build() support. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix hosting state test protocol fakes Widen fake agents' get_session service_session_id parameter to match the SupportsAgentRun protocol under the Python 3.11 test typing checkers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify Responses stream helper naming Rename responses_stream_events_from_run to responses_stream_from_run across exports, tests, docs, and the local Responses sample to align with the generic <protocol>_stream_from_run helper convention. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add state-level storage setters Add AgentState.set_session and WorkflowState.set_checkpoint_storage so app code can pair get-or-create helpers with explicit post-run storage without reaching into the underlying stores. Update Responses docs, tests, and sample to use state.set_session. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify WorkflowState checkpoint handling Remove CheckpointStore from WorkflowState so workflow checkpointing uses the existing CheckpointStorage abstraction directly. Keep WorkflowState focused on resolving workflow targets, including builders, and update hosting docs/tests accordingly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename Responses streaming run helper Rename responses_stream_from_run to responses_from_streaming_run across the hosting-responses exports, tests, docs, and local Responses sample. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Align Python hosting spec with protocol helpers Rewrite SPEC-002 to match the accepted helper-first hosting ADR and the implementation PR: AgentState, WorkflowState, SessionStore, Responses helpers, app-owned security/state responsibilities, and the minimal FastAPI Responses shape. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove old Python hosting channel implementation Remove the unreleased AgentFrameworkHost/channel implementation, the old hosting-telegram package, and old host/channel samples. Keep agent-framework-hosting focused on AgentState, WorkflowState, and SessionStore, and keep hosting-responses focused on helper-first Responses conversion. Update SPEC-002 to match the accepted helper-first ADR and the implementation surface. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Restore helper-first workflow sample Rebuild the local Responses workflow sample on the protocol-helper surface, add production-readiness cautions to the local hosting samples, and align file-backed workflow checkpoint/cursor storage under one sample storage root. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address hosting helper review feedback Handle streaming failures as terminal Responses SSE events, guard concurrent target/session initialization, and scope workflow sample checkpoint storage per continuation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Clarify Responses sample continuation behavior Document unknown conversation_id behavior in the agent sample and make the workflow sample explicitly reject conversation_id while continuing to use responses_session_id for previous_response_id. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Clarify Responses sample option policy Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
7a491f8e76 |
Python: Add hosting channel ADRs and spec (#6578)
* Add Python hosting channel ADRs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add Python hosting implementation spec Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
c70e594e6c |
.NET: [Breaking] RenameAgentRunResponse and AgentRunResponseUpdate classes (#3197)
* rename AgentRunResponse and AgentRunResponseUpdate classes - part1 * rename varialbles, parameters, methods and tests * rollback unnecessary changes |
||
|
|
5284b611c2 |
.NET: API specification for Foundry SDK alignment (#359)
* API specification for Foundry SDK alignment * Add descriptions to the samples * Add descriptions to the samples * Address some review feedback * Remove sample * Remove sample * Update docs/specs/001-foundry-sdk-alignment.md Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> * Update docs/specs/001-foundry-sdk-alignment.md Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> * Update docs/specs/001-foundry-sdk-alignment.md Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> * Update docs/specs/001-foundry-sdk-alignment.md Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> * Address code review feedback --------- Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> |