workflow/improve-python-sample-validation-workflow
90 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
851fd48510 | Remove trailing space | ||
|
|
b513e4ed35 | Merge branch 'main' into local-branch-update-sample-validation-flow | ||
|
|
43309018be |
.NET and Python: Extract Durable Task and Azure Functions integrations (#7465)
* Extract Durable Task and Azure Functions integrations Remove the migrated implementations, samples, tests, documentation, and repository wiring now owned by microsoft/agent-framework-durable-extension. Preserve Python compatibility through the agent_framework.azure shim and agent-framework-core[all], and leave customer-facing redirects to the new repository. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6181dcf9-857b-43ea-9fd2-fcd6b175ffdd * Fix feature registry validation after extraction Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6181dcf9-857b-43ea-9fd2-fcd6b175ffdd * Narrow external feature package paths Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6181dcf9-857b-43ea-9fd2-fcd6b175ffdd --------- Copilot-Session: 6181dcf9-857b-43ea-9fd2-fcd6b175ffdd |
||
|
|
ab786674a8 | Correct README | ||
|
|
b5cc5b5d71 | Merge branch 'main' into local-branch-update-sample-validation-flow | ||
|
|
25ec4c3b5c |
Python: Support archive-type MCP skills (source, toolbox, sample) (#7121)
* Python: Support archive-type MCP skills in MCPSkillsSource Add `archive`-type skill support to `MCPSkillsSource` so an MCP server can advertise packaged skills (ZIP / TAR / gzip-compressed TAR) that are downloaded, safely unpacked to a local directory, and served like file-based skills, while keeping the guarantee that MCP-delivered scripts are never executed. - Dispatch `skill://index.json` entries by `type`: `skill-md` (existing, fetched on demand) and `archive` (new). Unknown types are skipped. - `_ArchiveEntryLoader` downloads, extracts, and prunes archive skills and delegates discovery to an internal `FileSkillsSource` created with no script extensions and no runner, so bundled scripts surface as read-only resources only. - Hardened stdlib extraction: path-traversal (zip-slip) guard, non-regular TAR member skipping, and file-count / uncompressed-size / download-size limits. - Configure via `archive_*` constructor kwargs (no options object, per Python conventions); use `CachingSkillsSource` for refresh rather than a source level refresh interval. - Fix `FileSkillsSource` to treat `None` extensions as "use defaults" and an empty tuple as "discover none" (an empty tuple previously fell back to defaults). Port of .NET PR #6631. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e358a4e-538f-46be-8c58-128b6182352d * Propagate non-not-found archive download errors in MCPSkillsSource Only swallow "resource not found" MCP errors when downloading an archive resource; re-raise every other error (auth failure, INTERNAL_ERROR, connection drop, timeout) so a transient transport failure is not silently turned into a missing skill. This matches the existing failure model used by `_try_read_index` and `MCPSkill.get_resource`, and avoids a failed `CachingSkillsSource` refresh overwriting a previously cached list with a partial result. Add tests asserting archive-download INTERNAL_ERROR and ConnectionError propagate out of `get_skills`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e358a4e-538f-46be-8c58-128b6182352d * Python: Expose archive skill options on FoundryToolbox and demo in sample - FoundryToolbox.as_skills_provider() now forwards the MCPSkillsSource archive options (archive_skills_directory, archive_resource_extensions, archive_resource_search_depth, archive_max_file_count, archive_max_size_bytes, archive_max_uncompressed_size_bytes). Only explicitly-set options are forwarded so unset ones keep the MCPSkillsSource defaults. This lets a hosted toolbox agent redirect archive extraction to a writable directory (the default is under the cwd, which may be read-only in a container). - Add unit tests covering default (no options forwarded) and override forwarding. - Update the 12_foundry_toolbox_mcp_skills sample to demonstrate all three progressive-disclosure stages with an archive skill: escalation-policy now ships a references/refund-matrix.md resource and is uploaded as a ZIP archive; main.py disables load_skill and read_skill_resource approval and points archive extraction at a temp directory. README, toolbox.yaml, and ignore files updated accordingly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4f14f83d-1868-45c1-be1a-12f49a58ac36 * Python: Fix ty type error in toolbox archive-option test Cast provider._source to _FoundryToolboxSkillsSource before accessing the private _archive_options, so the ty checker (which runs over tests) resolves the concrete type instead of the SkillsSource base. Replaces the mypy-style type: ignore that ty did not honor. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4f14f83d-1868-45c1-be1a-12f49a58ac36 * Rework archive-type skill support in MCPSkillsSource to unpack archives entirely in memory instead of extracting them to a local directory, and apply reviewer feedback. * Python: Raise on archive member path-traversal (zip-slip) Treat a `..` path-traversal member in an archive skill as a hostile archive and reject the whole skill, matching how the file-count and uncompressed-size limits reject a malformed archive (previously the member was silently skipped while the rest of the skill still loaded). - `_normalize_archive_member_name` now raises `ValueError` on a `..` escape; benign degenerate entries (empty, `.`, `/`) still return None (skipped) and absolute paths are still neutralized to relative. The raise propagates to `_ArchiveEntryLoader._build_skill`, which already skips the skill on error. - Update tests: traversal cases now assert a raise, and add an end-to-end test that a zip-slip archive drops the whole skill. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e358a4e-538f-46be-8c58-128b6182352d * Python: Revert archive skill demo in toolbox MCP skills sample Restore the 12_foundry_toolbox_mcp_skills sample to its pre-PR, skill-md-only form (matching the .NET Agent_Step26_FoundryToolboxMcpSkills sample, which uses skill-md and no ZIP archive): - Revert main.py, toolbox.yaml, README.md, .azdignore, .dockerignore, and escalation-policy/SKILL.md to the single-file SKILL.md version. - Remove the archive demo files added by this PR (.gitignore and escalation-policy/references/refund-matrix.md). - Soften two README notes so they no longer claim archive skills are unsupported/silently dropped (this PR adds archive support); instead frame single-file SKILL.md as a focus choice and point to the archive_* options. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e358a4e-538f-46be-8c58-128b6182352d * Python: Clarify archive framing in mcp_based_skill sample README The mcp_based_skill sample is a generic MCP consumer that discovers whatever the server advertises; it does not itself demonstrate archive skills. Reword the archive note so it reads as an MCPSkillsSource capability rather than a sample feature, and fix the stale "unpacked to a local directory" claim to "unpacked in memory" (matching the in-memory extraction implementation). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e358a4e-538f-46be-8c58-128b6182352d --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e358a4e-538f-46be-8c58-128b6182352d Copilot-Session: 4f14f83d-1868-45c1-be1a-12f49a58ac36 |
||
|
|
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 |
||
|
|
80eb2570c7 | Remove indices in FHA sample names (#7405) | ||
|
|
8b895b867c | Address copilot comments | ||
|
|
e0082dcb8b | Merge branch 'main' into local-branch-update-sample-validation-flow | ||
|
|
342131ce79 | Fix using deployed agent sample | ||
|
|
59b979213a |
Python: Fix stale agent.json references in A2A sample (#7281)
Co-authored-by: Amit Dhawan <amit.dhawan@barco.com> |
||
|
|
0796af0c26 |
Python: add progressive A2A hosting adapters (#7258)
* Python: add progressive A2A hosting adapters Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607 * Python: address A2A adapter review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607 --------- Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607 |
||
|
|
bf206c4c81 | Merge branch 'main' into local-branch-update-sample-validation-flow | ||
|
|
848443ac68 |
[BREAKING] Python: Ensure session isolation for FHA invocation impl (#7158)
* Ensure session isolation for FHA invocation impl * Fix type check errors * Add user isolation to sample |
||
|
|
3bbcd9af6b | Add sample status | ||
|
|
d303b892ec | Fix using deployed agent sample | ||
|
|
d08200d00e |
Python: Bump package versions for 1.12.0 release (#7238)
* Bump Python package versions for 1.12.0 release Bump packages represented in the 1.12.0 changelog, promote Foundry Hosting, Azure Content Understanding, Gemini, Mistral, Monty, and Tools to beta, and apply the requested beta cohort date stamp. Root and core move to 1.12.0, released and RC packages use their selected increments, alpha packages including Hosting MCP use the 260721 stamp, and core floors are raised only for proven consumers. Copilot-Session: 2dd9980a-b869-4c16-8642-75b7a6d6ebdf * fix version in readme * Add Responses conversation ID changes to release notes Include the breaking Hosting Responses conversation ID helper changes from #7234 in the Python 1.12.0 changelog. Copilot-Session: 2dd9980a-b869-4c16-8642-75b7a6d6ebdf |
||
|
|
a70fe21298 |
[BREAKING] Python: add Responses conversation ID helper (#7234)
* Python: add Responses conversation ID helper Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2dd9980a-b869-4c16-8642-75b7a6d6ebdf * Python: make Responses session flag optional Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2dd9980a-b869-4c16-8642-75b7a6d6ebdf * Python: correlate Responses session return types Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2dd9980a-b869-4c16-8642-75b7a6d6ebdf * Python: clarify Responses conversation parameter Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2dd9980a-b869-4c16-8642-75b7a6d6ebdf * Python: clarify streaming conversation parameter Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2dd9980a-b869-4c16-8642-75b7a6d6ebdf * Python: include conversation in created event Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2dd9980a-b869-4c16-8642-75b7a6d6ebdf * Python: warn on nonstandard Responses IDs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2dd9980a-b869-4c16-8642-75b7a6d6ebdf |
||
|
|
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 |
||
|
|
c218067646 |
Python: Consolidate dependency updates (#7204)
* Bump uv from 0.11.28 to 0.11.29 in /python Bumps [uv](https://github.com/astral-sh/uv) from 0.11.28 to 0.11.29. - [Release notes](https://github.com/astral-sh/uv/releases) - [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/uv/compare/0.11.28...0.11.29) --- updated-dependencies: - dependency-name: uv dependency-version: 0.11.29 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump zuban from 0.8.2 to 0.9.0 in /python Bumps [zuban](https://github.com/zubanls/zubanls-python) from 0.8.2 to 0.9.0. - [Release notes](https://github.com/zubanls/zubanls-python/releases) - [Commits](https://github.com/zubanls/zubanls-python/compare/v0.8.2...v0.9.0) --- updated-dependencies: - dependency-name: zuban dependency-version: 0.9.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * PR #7146: Bump ty from 0.0.55 to 0.0.60 in /python * Bump ruff from 0.15.20 to 0.15.22 in /python Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.20 to 0.15.22. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/0.15.20...0.15.22) --- updated-dependencies: - dependency-name: ruff dependency-version: 0.15.21 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump mypy from 2.2.0 to 2.3.0 in /python Bumps [mypy](https://github.com/python/mypy) from 2.2.0 to 2.3.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v2.2.0...v2.3.0) --- updated-dependencies: - dependency-name: mypy dependency-version: 2.3.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Bump prek from 0.4.8 to 0.4.10 in /python Bumps [prek](https://github.com/j178/prek) from 0.4.8 to 0.4.10. - [Release notes](https://github.com/j178/prek/releases) - [Changelog](https://github.com/j178/prek/blob/master/CHANGELOG.md) - [Commits](https://github.com/j178/prek/compare/v0.4.8...v0.4.10) --- updated-dependencies: - dependency-name: prek dependency-version: 0.4.10 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump azure-ai-projects from 2.2.0 to 2.3.0 in /python Bumps azure-ai-projects from 2.2.0 to 2.3.0. --- updated-dependencies: - dependency-name: azure-ai-projects dependency-version: 2.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Bump types-python-dateutil in /python Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.9.0.20260518 to 2.9.0.20260716. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-python-dateutil dependency-version: 2.9.0.20260716 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump mypy from 2.2.0 to 2.3.0 in /python Bumps [mypy](https://github.com/python/mypy) from 2.2.0 to 2.3.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v2.2.0...v2.3.0) --- updated-dependencies: - dependency-name: mypy dependency-version: 2.3.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Bump botocore from 1.43.45 to 1.43.49 in /python Bumps [botocore](https://github.com/boto/botocore) from 1.43.45 to 1.43.49. - [Commits](https://github.com/boto/botocore/compare/1.43.45...1.43.49) --- updated-dependencies: - dependency-name: botocore dependency-version: 1.43.49 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * PRs #7144/#7147: Align lab uv and ruff pins * Regenerate lockfile for Python Dependabot PRs #7144-#7153 * Python: Support azure-ai-projects 2.3 session operations (#7150) * Python: Apply Ruff 0.15.22 suppression updates (#7147) * Python: Update tests for ty 0.0.60 (#7146) * Python: Update Foundry samples for azure-ai-projects 2.3 (#7150) * Python: Address dependency rollup review comments --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
3e102b36de | Merge branch 'main' into local-branch-update-sample-validation-flow | ||
|
|
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 |
||
|
|
1036fa7438 |
Python: docs: add self-hosting sample snippets (#7104)
* docs: add self-hosting sample snippets Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 636b7fb2-381a-4d62-b5cf-d029efa3ad20 * docs: use stable hosting sample ranges Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 636b7fb2-381a-4d62-b5cf-d029efa3ad20 * docs: address hosting sample review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 636b7fb2-381a-4d62-b5cf-d029efa3ad20 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
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> |
||
|
|
5ab8877ba5 |
Python: HITL respond-URL addressing from inside workflows (#7001)
* feat(durabletask): surface HITL respond-URL addressing to workflow executors
Let a workflow notify a human reviewer (e.g. email an approval link) from inside the
graph, without the caller threading the instanceId/requestId by hand.
- durabletask: the orchestrator injects host_context {instance_id, workflow_name,
request_path_prefix} into each activity input; CapturingRunnerContext surfaces it as
host_metadata. No new core API.
- azurefunctions: WorkflowHitlContext.from_context(ctx) builds the canonical
respond/status URLs (returns None in-process so callers degrade gracefully).
Re-exported through the agent_framework.azure lazy namespace.
- Nested sub-workflows: the address context (root instance + workflow name +
accumulated {executor}~{ordinal}~ prefix) propagates down call_sub_orchestrator via a
new SUBWORKFLOW_ADDRESS_KEY marker, so an executor at any depth builds a URL that
targets the addressable top-level instance with a qualified request id. The per-child
ordinal matches the read-side enumerate() index used by the status/respond endpoints.
The marker is stripped from untrusted input alongside SUBWORKFLOW_INPUT_KEY
(confused-deputy / info-leak guard).
- Samples 12 and 13 reworked into the retry-safe two-step notify pattern: the emitter
generates an explicit request id and a downstream NotifyExecutor builds the URL and
notifies, so failed upstream retries never produce a dead link.
Tests: unit coverage for the metadata round-trip, address/ordinal agreement (fan-out at
depth and nested prefix accumulation), marker stripping, and URL building; integration
tests assert the helper-built URL equals the server respondUrl and resumes the run, for
both the flat (12) and nested (13) samples.
* refactor(durabletask): read back request_info id instead of generating one in samples
Add WorkflowHitlContext.pending_request_id(ctx), an async helper that returns the
id request_info just generated (read from the runner context's pending request-info
events). This works on any host via the core RunnerContext protocol method, so it
needs no core change.
Samples 12 and 13 now call request_info() and read the id back to forward to the
NotifyExecutor, instead of minting a uuid by hand and passing request_id=. The
read-back happens in the same activity execution that generated the id, so the
pending request event and the notify message still commit together with the same id
(retry-safe; failed upstream retries notify no one).
* docs(azurefunctions): document request_info id read-back and notify safety
Tighten pending_request_id docstring to require calling it immediately after request_info, and explain why that is safe on the durable host (each executor runs in its own activity with its own runner context, so the pending set only holds this executor's requests and the newest is the one just emitted). Document the two-step notify pattern in the 12 and 13 sample READMEs, including the downstream-notifier retry safety and the nested address-prefix propagation.
* fix(python): resolve ty typing error and address PR review comments
- test_subworkflow_orchestration: replace the mypy-only type:ignore[arg-type] with a cast so the ty checker passes too (the other four checkers already honored the ignore).
- samples 12/13 README: guard the notify snippet against None before build_respond_url to match the documented graceful-degradation behavior.
- integration tests 12/13: reword comments that implied request_info now generates an explicit uuid4; it generates the id internally by default.
* fix(python): honor configurable Functions route prefix and address HITL PR review
- Resolve the route prefix from host.json (extensions.http.routePrefix, default api) in a new azurefunctions _routes module, used by both the server endpoints and WorkflowHitlContext, so a custom or empty routePrefix no longer 404s respond/status URLs (was hardcoded /api/ in four places).
- Extract respond/status URL construction into one shared builder called from _app.py and _hitl_context.py, removing the sync-by-test duplication.
- Broaden loopback detection (localhost, 127.0.0.0/8, 0.0.0.0, ::1, [::1]) via a _is_loopback helper so local links use http.
- Pin the host_context key names as shared constants in durabletask so producer and azurefunctions consumer cannot drift.
- Reword a stale base_url comment to reference WEBSITE_HOSTNAME.
- Add unit tests for the route module and loopback handling.
* refactor(azurefunctions): derive server-side HITL URLs from the request URL
The run and status endpoints now derive the base URL and route prefix from the incoming request URL (the value the host actually routed) via split_request_url, so the caller-visible respond/status URLs no longer depend on reading host.json on the server. The in-workflow helper keeps reading host.json since it has no request context. Replaces strip_route_prefix and updates its tests.
* test(durabletask): enforce sub-workflow ordinal and read-index agreement
Extract the read-side subworkflows grouping into a shared _index_subworkflows helper (used by the orchestrator) and add test_readside_index_matches_dispatch_ordinal, which round-trips a fan-out through that helper and asserts subworkflows[executor][ordinal] resolves to the child the dispatch stamped that ordinal onto. Turns the previously comment-only write-ordinal / read-index invariant into a shared, CI-enforced one.
* fix(azurefunctions): suppress bandit B104 on loopback host set
|
||
|
|
56e9a8f74c |
Python: Make foundry toolbox MCP skills sample self-contained (#7099)
* Python: Make foundry toolbox MCP skills sample self-contained Rework sample 12 (foundry_toolbox_mcp_skills) so users can build it from zero with azd, mirroring samples 04 and 09: - Bundle two single-file SKILL.md skills (support-style, escalation-policy) and a skills-only toolbox.yaml (with one connectionless code_interpreter tool, required by `azd ai toolbox create`). - Rewrite the README as an azd-native, from-zero guide (create skills -> create toolbox -> set TOOLBOX_ENDPOINT -> run) and fix the stale MCPSkillsSource API description to match main.py. - Switch config from TOOLBOX_NAME to the versioned TOOLBOX_ENDPOINT (.env.example, agent.yaml, agent.manifest.yaml); add .azdignore. Also enable the sample to run unattended behind ResponsesHostServer: - Forward disable_load_skill_approval / disable_read_skill_resource_approval / disable_run_skill_script_approval from FoundryToolbox.as_skills_provider() to the underlying SkillsProvider, so load_skill needs no approval round-trip (the Responses host runs without an AgentSession, which the default approval flow requires). main.py now uses as_skills_provider(disable_load_skill_approval=True). - Add unit tests covering the default and overridden approval behaviour. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4f14f83d-1868-45c1-be1a-12f49a58ac36 * Python: Address PR review on toolbox MCP skills sample - Remove the unused parameters section from agent.manifest.yaml (TOOLBOX_ENDPOINT is supplied via environment_variables, matching sample 04). - README: state the sample is self-contained directly instead of contrasting with the C# sample. - README: describe skill discovery behaviour without naming the internal MCPSkillsSource class. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4f14f83d-1868-45c1-be1a-12f49a58ac36 --------- 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 |
||
|
|
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> |
||
|
|
c8fb491644 |
Python: docs: add env example files for durabletask samples (#5948)
* docs: add env example files for durabletask samples * docs: clarify env example values and comments * docs: set default Redis URL in streaming sample env example |
||
|
|
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> |
||
|
|
2aae66d063 |
Python: use writable runtime directory for Foundry Skills sample (#6606)
* fix: use writable skills download directory * fix: handle empty skills download directory override --------- Co-authored-by: malsabbagh05 <malsabbagh05@users.noreply.github.com> Co-authored-by: Tao Chen <taochen@microsoft.com> |
||
|
|
2889475bce |
docs: add prerequisite commands for Python hosting samples (#5935)
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com> |
||
|
|
b31c8981a4 |
Python: Add multi-tenant hosting hosting security consideration to a2a sample (#6983)
* Add multi-tenant hosting hosting security consideration to a2a sample * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
2958f19df3 | Fix hosted agent file sample | ||
|
|
81e425b44f |
Python: [BREAKING] Durable Task multi-workflow hosting and sub-workflows (#6696)
* feat(durabletask): add workflow naming helpers (multi-workflow phase 0)
Foundation for hosting multiple workflows (and later sub-workflows) on one
durable task host. Adds a host-agnostic naming module that derives the stable
durable names a hosted workflow registers under.
- New `_workflows/naming.py`:
- `workflow_orchestrator_name(name)` -> `dafx-{name}` (orchestration name,
aligned byte-for-byte with .NET `WorkflowNamingHelper`).
- `workflow_name_from_orchestrator(name)` -> reverse, `None` when not prefixed.
- `validate_workflow_name(name)` -> rejects empty / malformed / auto-generated
`WorkflowBuilder-<uuid>` names (validate-and-reject rather than silently
sanitize, since the name becomes a durable identity and an HTTP route segment).
- `is_auto_generated_workflow_name(name)`, `DURABLE_NAME_PREFIX`.
- Export the helpers from the package public API.
- Mark `WORKFLOW_ORCHESTRATOR_NAME` deprecated in favor of per-workflow names
(kept functional; the single-workflow path still uses it until phase 1).
- 39 unit tests covering round-trips and validation.
Design: docs/design/durabletask-multiworkflow-and-subworkflows.md
* feat(durabletask): host multiple workflows per worker with scoped names (phase 1)
Enables hosting more than one MAF workflow on a single standalone Durable Task
worker, and aligns both hosts on workflow-scoped durable names so two co-hosted
workflows that reuse an executor id cannot collide.
Naming (shared, host-agnostic):
- orchestration: dafx-{workflowName} (matches .NET; the name DT tooling surfaces)
- non-agent activity / agent entity: dafx-{workflowName}-{executorId} (scoped)
- New naming helpers workflow_scoped_executor_id / workflow_executor_activity_name.
Standalone worker (agent-framework-durabletask):
- configure_workflow is now additive: stores workflows keyed by Workflow.name,
rejects duplicate / auto-generated (WorkflowBuilder-<uuid>) / invalid names,
registers one orchestrator per workflow plus its scoped activities/entities.
- The shared orchestrator dispatches scoped names derived from workflow.name.
- New registered_workflow_names property.
Client (DurableWorkflowClient):
- Optional default workflow_name on the client; start/run/stream accept a per-call
workflow_name and target dafx-{name}.
- Opt-in ownership validation on status/HITL methods: when a workflow name is
resolvable, an instance whose orchestration name does not match is treated as
not-found (status -> None, pending -> [], send_hitl_response / await -> raise),
mirroring the Azure Functions route-scoping check.
Azure Functions host (agent-framework-azurefunctions):
- Registration now uses the same scoped names so the shared orchestrator's
dispatch matches (single workflow per app for now; flat workflow/* routes kept).
- Workflow name is validated up front; workflow agents register under the scoped
entity id; _is_workflow_orchestration scopes to dafx-{workflow.name}.
Samples + tests:
- Durable Task and Azure Functions workflow samples now name their workflow.
- Unit tests cover multi-workflow registration, name validation, client targeting,
and ownership; integration tests target the named workflows.
WORKFLOW_ORCHESTRATOR_NAME remains exported (deprecated). This is a hard switch:
in-flight single-workflow instances created before upgrade (under the old
workflow_orchestrator name) will not resume.
Design: docs/design/durabletask-multiworkflow-and-subworkflows.md
* feat(azurefunctions): host multiple workflows per app with per-workflow routes (phase 2)
Completes multi-workflow hosting on the Azure Functions host, building on the
shared scoped-naming foundation from the worker phase.
AgentFunctionApp:
- New `workflows=` parameter accepting a list (keyed by each `Workflow.name`) or a
name->Workflow mapping; the existing `workflow=` is a single-workflow alias.
Both may be combined. Duplicate names and mapping-key/name mismatches are rejected.
- Each workflow registers its own `dafx-{name}` orchestration, workflow-scoped
activities/entities, and per-workflow HTTP routes:
`workflow/{name}/run`, `workflow/{name}/status/{instanceId}`,
`workflow/{name}/respond/{instanceId}/{requestId}`. Routes are always
per-workflow (even for a single workflow) so callers don't change URLs as an app
grows from one workflow to many.
- Route ownership check is per-workflow (`_is_owned_orchestration(status, name)`):
a leaked instance id for another orchestration -- or another workflow -- is
treated as not-found, extending the route-scoping defense.
- `get_agent(context, name, workflow_name=...)` resolves a workflow agent under its
scoped id; bare `agents=` registration keeps the standalone surface. New
`workflows` introspection property; `.workflow` now returns the sole workflow
(or None when several are hosted).
- Removed the now-unused flat-URL helper `_build_status_url` (handlers inline
per-workflow URLs).
Samples + tests:
- Azure Functions workflow samples (09-12) name their workflow; integration tests
target the per-workflow routes.
- Unit tests cover multi-workflow registration, duplicate/mapping/auto-name
rejection, and per-workflow ownership.
Note: sample README / demo.http route docs are updated in the docs phase.
Design: docs/design/durabletask-multiworkflow-and-subworkflows.md
* feat(durabletask): sub-workflows via durable child orchestrations (phase 3)
Run WorkflowExecutor nodes as durable child orchestrations on both hosts.
- Protocol: add call_sub_orchestrator to WorkflowOrchestrationContext, implemented by the durabletask and Azure Functions adapters.
- Registration: planner classifies WorkflowExecutor as subworkflow_executors; collect_hosted_workflows walks nested workflows (parent first, deduped by name). Both hosts recursively register every nested workflow's orchestration/agents/activities once; only top-level workflows get HTTP routes. Names validated up front before any registration side effects.
- Orchestrator: dispatch WorkflowExecutor nodes via call_sub_orchestrator(dafx-{innerName}) with deterministic child instance ids ({instanceId}::{executorId}::{counter}), a trusted-input marker carrying nesting depth (bounded at 25), and outputs routed as messages (default) or parent outputs (allow_direct_output).
- Tests: registration/collect, orchestrator prepare/process/unwrap, recursive registration on both hosts. Sample: 11_subworkflow.
* feat(durabletask): sub-workflow HITL via qualified request ids (phase 4)
Surface a nested sub-workflow's human-in-the-loop request behind the top-level instance (B2 single addressing surface).
- Orchestrator records dispatched sub-workflow child instance ids in its custom status (subworkflows map) before suspending in task_all, so the read side can reach a child's pending request while the parent is paused.
- Read side (durabletask client get_pending_hitl_requests; AF status route) recurses into nested child statuses, qualifying each nested request id as {executorId}::{requestId} (accumulated for deeper nesting).
- Write side (durabletask client send_hitl_response; AF respond route) splits a qualified id on '::', resolves the owning child orchestration via the parent's subworkflows map, and raises the event on the leaf child with the bare request id. Unknown/inactive sub-workflow -> error/404.
- Shared SUBWORKFLOW_REQUEST_SEPARATOR ('::') in naming so both hosts and the client agree. respondUrl/respond always targets the top-level instance.
- Tests: TestSubworkflowHitl (durabletask client, 7), TestAgentFunctionAppSubworkflowHitl (AF, 7). Sample: 12_subworkflow_hitl (HITL pause inside an embedded sub-workflow).
* docs(durabletask): ADR + sample route docs for multi-workflow and sub-workflows (phase 5)
- Add ADR-0030 capturing the multi-workflow and sub-workflow hosting decisions (naming, scoped inner names, per-workflow routes, child-orchestration sub-workflows, hard-switch migration, B2 sub-workflow HITL, scoped agent addressing) with considered alternatives; mark the design doc as implemented and link the ADR.
- Update Azure Functions workflow samples (09-12) README/demo.http to the per-workflow route shape (workflow/{name}/run|status|respond) introduced in phase 2.
- Extend the durabletask sample catalog with the workflow hosting patterns (08-12), including the new 11_subworkflow and 12_subworkflow_hitl samples.
* fix(durabletask): harden sub-workflow hosting + add sub-workflow integration tests
Post-review hardening of the multi-workflow / sub-workflow durable hosting:
- Trust boundary: strip the reserved sub-workflow envelope key from untrusted
client input at both host boundaries (DurableWorkflowClient.start_workflow and
the AF start route) so a forged envelope cannot reach the trusted pickle path.
- Nested HITL addressing: qualify nested pending requests by (executorId, ordinal)
using a '~' separator (was '::', which collided with core's auto::N functional
request ids); the parent status subworkflows map is now a per-executor list so
multiple children dispatched in one superstep stay independently addressable.
- Reject two different workflow instances that share a name (the same instance
reused by sibling nodes is still deduped); validate executor ids (separator-free,
length-bounded) when hosting durably.
- Remove the arbitrary sub-workflow nesting depth cap: a WorkflowExecutor wraps a
concrete Workflow so the nesting tree is finite at build time, and the durable
instance-id length limit is the natural ceiling (matches .NET, which has none).
Tests/samples:
- New durabletask integration tests for sub-workflow composition (11) and nested
sub-workflow HITL (12); new no-agent AF sub-workflow HITL sample (13) + test.
- Exempt no-agent samples from the model-credential gate in both integration
conftests so the nested-HITL plumbing is covered deterministically.
- Update durabletask sample 12 docs to the new qualified-id format.
Validated: 484 unit tests; durabletask integration 08/09/11/12 and AF 12/13 pass
against the live emulators; pyright 0 errors; ruff clean.
* fix(durabletask): address PR review feedback on naming, typing, and docs
- Unquote df.DurableOrchestrationClient annotations so pyupgrade passes.
- Narrow the split_subworkflow_request_id result before unpacking in a naming test so the strict type checkers pass.
- Correct the durabletask sample catalog to the {executor}~{ordinal}~{requestId} qualified id format.
- Reword the Azure Functions sub-workflow sample intro so it does not imply a difference from a same-numbered sample.
- Drop internal shorthand (B2, phase labels) from code comments.
* fix(durabletask): reject case-insensitive workflow name collisions
The route ownership guard compares the durable orchestration name with casefold(), but registration kept raw names as distinct keys. Hosting 'Orders' and 'orders' therefore succeeded while either workflow's status/respond route could operate on the other's instances. Reject case-insensitive name collisions at registration (within a composition via collect_hosted_workflows, and across registration calls via the case-folded _registered_orchestrations map and the top-level guard in both hosts) so the case-folded ownership boundary stays real. Single names of any case remain valid; only collisions are rejected.
* docs(durabletask): remove multiworkflow/subworkflow ADR and design docs
Drop the ADR and design exploration documents and the dangling docstring reference to them.
* refactor(durabletask): simplify workflow client status parsing and drop deprecated orchestrator-name symbols
Extract a shared _parse_custom_status helper in DurableWorkflowClient to remove duplicated custom-status JSON parsing across three call sites.
Drop the now-unused single-workflow compatibility shims WORKFLOW_ORCHESTRATOR_NAME and WorkflowRegistrationPlan.orchestrator_name, replaced by per-workflow workflow_orchestrator_name(name).
* fix(core): drop WORKFLOW_ORCHESTRATOR_NAME from agent_framework.azure re-exports
The constant was removed from agent-framework-durabletask, but the core azure lazy-loading namespace still re-exported it, breaking pyright in packages/core. Remove it from both the runtime _IMPORTS map and the .pyi stub.
* fix(durabletask): atomic multi-workflow registration and bubble sub-workflow events
Make configure_workflow / AgentFunctionApp registration atomic: check every cross-call name collision before mutating any state, so a colliding nested sub-workflow no longer leaves a host partially configured (with the top-level name stuck in the registry). Applied to both the standalone worker and the Functions app.
Bubble sub-workflow intermediate events: a workflow run as a child orchestration now returns a SUBWORKFLOW_RESULT_KEY envelope carrying its outputs plus event timeline, and the parent re-tags the child's intermediate events with the WorkflowExecutor node id and republishes them, matching the in-process WorkflowExecutor contract. Top-level runs still return a bare outputs list.
Adds cross-registration atomicity tests on both hosts and unit tests for the result envelope and event bubbling. Resolves review threads on _worker.py, orchestrator.py, and test coverage.
* fix(azurefunctions): widen workflow orchestrator wrapper return type
The shared run_workflow_orchestrator now returns list | dict (the sub-workflow result envelope), so the azurefunctions _workflow.py wrapper that delegates to it must widen its Generator return annotation to match. Caught by the package-level pyright in CI (Package Checks), which type-checks the whole package, not just the files changed in the previous commit.
|
||
|
|
fc10ef31bd |
Python: Add FHA declarative workflow sample (#6897)
* Add FHA declarative workflow sample * Address comments * Address comments |
||
|
|
0260ea0e61 |
Python: implement ADR-0029 service_session_id lifecycle mapping (#6724)
* python: implement ADR-0029 service_session_id lifecycle mapping - Extend AgentSession service_session_id to support structured values - Add agent-owned conversation id extraction for chat forwarding and telemetry - Migrate A2A durable continuation state to A2AServiceSessionId - Keep A2AAgentSession as compatibility shim and mark it deprecated - Update core/a2a tests and package guidance Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix service_session_id type fallout across packages Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix remaining test typing signatures for service_session_id Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix hosting test stubs for widened get_session type Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix remaining test stubs for get_session union type Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify A2A session state handling Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix import * Fix hosting-telegram test get_session typing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
08a09e7ebb |
Python: Update FHA samples after v2 changes (#6841)
* Update FHA samples after v2 changes * Add missing pakcage pin * Address comments |
||
|
|
7f3a2aec38 |
[BREAKING] Python: Foundry Hosted Agent V2 protocol upgrade (#6811)
* Upgrade to FHA protocol v2 + toolbox integration
* Scope checkpoints and approval storage by user id
* Add toolbox skills integration
* Fix formatting
* Add httpx lower and upper bound
* Update foundry-hosting package version
* Remove custom http client
* Revert "Remove custom http client"
This reverts commit
|
||
|
|
6dfcbc5c62 |
Python: support stable + preview Azure AI Search (Foundry IQ) API versions (#6603)
Update agent-framework-azure-ai-search to work across the stable/GA azure-search-documents SDK (12.0.0, api-version 2026-04-01) and the preview SDK (12.1.0b1, api-version 2026-05-01-preview) for both semantic and agentic modes. - Bump the dependency to azure-search-documents>=12.0.0,<13 and the package to 1.0.0b260618. - Add an api_version parameter (threaded into SearchClient, SearchIndexClient, and KnowledgeBaseRetrievalClient) plus STABLE_API_VERSION/PREVIEW_API_VERSION constants, re-exported from agent_framework.azure. - Auto-detect preview-only agentic features (output mode, low/medium reasoning effort) via _preview_features_active(), which requires both the preview SDK and a preview api-version; defaults (extractive + minimal) work on both channels and preview-only options raise an actionable error otherwise. - Make knowledge-base imports SDK-version resilient and fix the 12.x surface (k -> k_nearest_neighbors, defensive additional_properties). - Update tests (pass on both SDKs), docs, samples, CHANGELOG, and uv.lock. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
a1c37b69e0 |
[Generated by SRE Agent] Clarify identifier security guidance (#6510)
Co-authored-by: Azure SRE Agent <noreply@microsoft.com> Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com> |
||
|
|
b8b43798b9 |
Python: Update FHA with toolbox sample with more auth methods (#6713)
* Update FHA with toolbox sample with more auth methods * Clean up * Clean up other samples |
||
|
|
d75f2286f4 |
Python: Add Telegram channel for agent-framework-hosting (#6698)
* Python: Add Telegram channel for agent-framework-hosting - Add agent-framework-hosting-telegram package with TelegramChannel supporting polling and webhook transports, streaming edits with Telegram Bot API rate limiting, per-chat serial workers, and multi-modal inbound/outbound (text, photo, document, voice) - Add local_telegram sample demonstrating multi-channel hosting with a TelegramChannel alongside ResponsesChannel, using per-chat FileHistoryProvider and a run_hook for Telegram persona temperature - Fix test layout: move tests to tests/hosting_telegram/ (no __init__.py) - Remove old [tool.mypy] section and mypy poe task; source type-checking is handled by pyright via shared_tasks - Update uv.lock, pyproject.toml workspace sources, and PACKAGE_STATUS.md Fixes #6588 Refs #6265 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Address Telegram channel CI failures and review feedback - Fix webhook secret validation to use constant-time compare_digest - Harden webhook update parsing: require integer chat IDs and guard slash-only commands - Fix streaming edge cases in TelegramChannel: - prevent edit worker deadlocks when text exceeds 4096 chars - prevent deadlock when placeholder send fails (message_id stays None) - enforce edit throttling with minimum interval sleep - honor send_typing_action=False in streaming mode - always forward final multimodal output (e.g. images), while avoiding duplicate text sends - Expand Telegram tests for slash-only command handling, non-int chat IDs, and streaming behavior (long text, final images, typing toggle) - Fix sample/docs feedback: - rename sample package to agent-framework-hosting-sample-local-telegram - switch sample uv.sources from feature branch to main - align docs/tool names with lookup_weather - fix broken links and server run instructions in README/call_server.py - align local_telegram app docstrings with reasoning hook behavior and strip model in responses_hook Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Fix TelegramChannel streaming to iterate contents for multimodal support - Remove stale PR reference from module docstring - Add Google-style docstring to TelegramChannel.__init__ documenting all keyword args - Fix _stream_to_chat to iterate update.contents instead of using getattr(update, 'text', None); text chunks are extracted from Content items with type='text', non-text content in updates is correctly ignored (images etc. are forwarded via the final response) - Update _FakeStreamUpdate test helper to use contents list matching the real AgentResponseUpdate API; add from_text/from_image class methods - Update _FakeResponseStream to accept _FakeStreamUpdate objects directly - Add test verifying multimodal stream updates don't corrupt text accumulator Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Split local_telegram into simple Telegram-only and new multi-channel sample local_telegram is now a focused Telegram-only sample: - Removes ResponsesChannel and all responses_hook code - Removes call_server.py (no HTTP endpoint to call) - Uses a deterministic lookup_weather tool (hash-based, not random) - Single run_hook that strips model and raises reasoning effort - Drops agent-framework-hosting-responses dependency New local_multi_channel sample shows running both channels at once: - ResponsesChannel + TelegramChannel sharing a FileHistoryProvider - Cross-channel session resumption via previous_response_id - call_server.py moved here (the Responses endpoint lives here now) - Demonstrates the multi-channel coordination story Update README table to list both samples with clear descriptions. Also delete personal_assistant/.venv which was not tracked but caused pyright to crawl the entire installed venv (thousands of files), making sample pyright checks hang indefinitely. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Fallback when Telegram final edit fails - only mark final edit as sent after a confirmed 2xx edit response - fall back to sendMessage when final edit returns a non-success status - add regression test covering failed final edit fallback behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Fix optional await_args typing in telegram test - assert await_args is not None before reading kwargs in streaming fallback test - resolves test-typing failures across mypy/pyright/ty/zuban for hosting-telegram Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
f2d02e58b3 |
Python: Add hosting core and Responses channel (#6580)
* Add Python hosting core and Responses channel Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address hosting core review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Adopt source pyright typing setup for hosting packages Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Cover ResponsesChannel custom path routing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Align hosting tests with package layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix hosting workflow fixture imports in aggregate tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Apply useful Responses channel hardening Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix hosting package typing checks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix hosting pyright under Python 3.11 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Avoid static diskcache dependency in hosting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix aggregate typing and Docker test resilience Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify local Responses workflow sample Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Clarify generic hosting is not Foundry hosting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Revert "Clarify generic hosting is not Foundry hosting" This reverts commit 73b584d919053bed43a258d75dc2b76406e9c181. * Clarify isolation key source flexibility Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Clarify isolation header reuse boundary Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Support multimodal Responses channel outputs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Preserve multimodal streaming Responses output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Stream Responses output items from updates Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Improve Responses streaming output handling * Tighten Responses channel default option handling - Restore full option parsing in parse_responses_request: known fields are remapped (max_output_tokens→max_tokens, parallel_tool_calls→ allow_multiple_tool_calls), transport/session keys excluded, None values dropped, everything else forwarded as-is so run_hook can inspect the full set. - Add a default _strip_options_hook on ResponsesChannel that removes all parsed options before reaching the agent. Callers cannot inject generation params (temperature, instructions, tools, …) unless the host explicitly allows it. - A custom run_hook replaces the default entirely and receives the full ChannelRequest.options plus the raw protocol_request. - Update tests to cover remap, default-strip, and custom-hook paths. - Clarify host debug-log docstring to match new option flow. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
7051a4920d |
Python: Add MCP as a hard dep in Foundry Hosting (#6634)
* Add MCP as a hard dep in Foundry Hosting * Pin GitHub SDK * Fix formatting * Fix formatting |
||
|
|
148f57020a |
Python: host MAF workflows on a standalone Durable Task worker (#6418)
* feat(durabletask): host MAF workflows on a standalone Durable Task worker
Add a host-agnostic workflow execution engine to agent-framework-durabletask so a MAF Workflow can run as a durable orchestration outside Azure Functions:
- WorkflowOrchestrationContext protocol + DurableTaskWorkflowContext adapter, the superstep orchestrator, serialization helpers, capturing runner context, and the shared non-agent activity body (including the yield-output classifier so intermediate executors are not surfaced as final outputs).
- DurableAIAgentWorker.configure_workflow auto-registers agent executors as entities, non-agent executors as activities, and the workflow orchestrator.
- plan_workflow_registration centralizes the 'what to register' decision so it can be shared across hosts.
- run_agent_coroutine runs all agent coroutines on one persistent event loop, fixing a cross-loop hang when shared chat clients/credentials bind their asyncio primitives to a dead loop.
- DurableWorkflowClient (start/await workflow + HITL discover/respond); DurableAIAgentClient stays agent-only.
* refactor(azurefunctions): delegate workflow execution to agent-framework-durabletask
AgentFunctionApp now reuses the shared orchestrator, activity body, and registration planner from agent_framework_durabletask instead of maintaining its own copies; _workflow.py becomes a thin host-specific adapter (AzureFunctionsWorkflowContext).
- Run agent entity coroutines on the shared persistent event loop, fixing the cross-loop hang.
- Relocate state-diff unit tests to the durabletask package; update entity loop tests.
* feat(core): expose durabletask workflow symbols via agent_framework.azure
Lazily re-export WORKFLOW_ORCHESTRATOR_NAME and DurableWorkflowClient from the agent_framework.azure namespace so standalone hosts can import them without depending on internal module paths.
* docs(samples): add standalone durabletask workflow and HITL samples
Add two samples under samples/04-hosting/durabletask demonstrating MAF workflows on a standalone Durable Task worker (no Azure Functions):
- 08_workflow: conditional spam-detection workflow started via DurableWorkflowClient.start_workflow / await_workflow_output.
- 09_workflow_hitl: content-moderation workflow that pauses with ctx.request_info and is resumed via DurableWorkflowClient.get_pending_hitl_requests / send_hitl_response.
Also add the durabletask workflow integration test (test_08_dt_workflow).
* fix: address PR review feedback
- Sanitize HITL external-event responses with strip_pickle_markers in the orchestrator (defense-in-depth for callers that bypass DurableWorkflowClient).
- Raise WorkflowConvergenceException when max_iterations is reached with pending messages, matching the core WorkflowRunner instead of silently returning partial output.
- Route falsy 'sent' messages (use 'is not None' instead of truthiness).
- Normalize None shared_state_snapshot/source_executor_ids in execute_workflow_activity.
- Cast Any returns in AzureFunctionsWorkflowContext to satisfy mypy/pyright.
- Fix sample docstrings to reference DurableWorkflowClient.
* fix: resolve pyright Package Checks errors
- Use typed locals instead of cast in AzureFunctionsWorkflowContext (mypy sees Any, pyright sees concrete types -> avoid reportUnnecessaryCast).
- Annotate shared_state_snapshot and cast partially-typed durabletask SDK returns / HITL custom-status parsing to satisfy reportUnknownVariableType/reportUnknownMemberType.
- Drop the dead deserialize/serialize re-export in _workflow.py and mark the intentional private _extract_message_content re-export.
* fix(durabletask): agent-executor identity and typed workflow input
Register each workflow agent entity under the executor id that the orchestrator dispatches to (instead of the agent name), so AgentExecutor(agent, id=...) works when the id differs from agent.name. The azure-functions host mirrors this.
Reconstruct the start executor declared input type from the workflow initial JSON payload in the shared engine (mirroring in-process delivery) instead of string-coercing it per host. Untrusted input is stripped of pickle markers before reconstruction to prevent deserialization RCE.
* fix(samples): type durable workflow start executors for reconstructed input
The HITL and parallel workflow samples no longer hand-parse a JSON string. Their start executors now declare their real input type (ContentSubmission / DocumentInput), which the durable engine reconstructs from the client payload before delivery.
* test(durabletask): unit coverage for registration, client, worker, and input coercion
Add unit tests for plan_workflow_registration, DurableWorkflowClient, the agent-executor identity registration (entity keyed by executor id), and the typed initial-input coercion including pickle-marker neutralization.
* test(durabletask): HITL and parallel durable workflow integration tests
Add an integration test for the standalone durabletask HITL workflow sample via a new workflow_client fixture. Re-enable the Azure Functions parallel workflow test, consolidated into one end-to-end case so the work-stealing xdist scheduler cannot spawn multiple func hosts for this sample.
* refactor(durabletask): group workflow modules into a _workflows subpackage
Move the eight workflow modules into a private _workflows/ subpackage and drop the redundant _workflow_ prefix (orchestrator.py, registration.py, activity.py, client.py, context.py, dt_context.py, runner_context.py, serialization.py). The public API and __all__ are unchanged; only direct internal-module imports were repointed (package __init__, the worker, the azure-functions shared shim, and the affected unit tests).
* fix(durabletask): harden workflow type resolution and HITL response handling
- resolve_type returns only real classes (avoids issubclass TypeError in reconstruct_to_type)
- re-wait on HITL responses rejected by pickle-marker sanitization instead of dropping the request and losing the run
- American spelling in strip_pickle_markers docstring
- unit tests for resolve_type
* fix(durabletask): treat async edge conditions as not-matched on the synchronous host
The durabletask orchestrator evaluates edge conditions synchronously and does not support async edge conditions. Such an edge is now treated as not matched (the edge is not traversed) rather than assuming a result. Adds unit coverage; full async-condition support will be handled separately.
* fix(durabletask): reconstruct typed workflow outputs at the host boundary
await_workflow_output and the Azure Functions status endpoint now decode the checkpoint-encoded outputs the shared activity produces, via a shared deserialize_workflow_output helper. The client returns the original objects; the AF endpoint emits clean domain JSON instead of checkpoint-marker dicts, keeping the two hosts consistent.
* fix(durabletask): address review findings on workflow hosting
- AF: register workflow agents through add_agent(entity_id=...) so they remain tracked in app.agents / get_agent() (restores documented behavior) while keying by the executor id the orchestrator dispatches to; mirrors DurableAIAgentWorker.add_agent.
- async bridge: treat the shared loop as reusable only while its backing thread is alive, so a dead loop thread is replaced instead of hanging future.result() forever.
- client: add get_runtime_status; the standalone HITL sample now stops polling and reports the real terminal state instead of a generic timeout.
- tests: guard send_hitl_response pickle-marker stripping and add get_runtime_status coverage.
* fix(durabletask): wait indefinitely for HITL responses, matching core
The durable workflow host previously raced HITL responses against a 72h timer and failed the orchestration on elapse. MAF core's request_info has no timeout concept (it waits for the response), and the .NET durable host waits too, so the durable Python host now does the same: it stays paused until a response arrives. Removes the hitl_timeout_hours parameter and DEFAULT_HITL_TIMEOUT_HOURS constant from both hosts. A configurable timeout can be added later once core defines the contract (what happens on elapse).
* feat(durabletask): typed workflow event streaming and async client API
Add a brokerless workflow event stream to the durable host. Each non-agent executor runs inside a durable activity that captures its real WorkflowEvents (with data payloads); the orchestrator replays them into the orchestration custom status after each superstep, and the client streams them back as typed WorkflowEvent objects with reconstructed data. Agent executors contribute synthesized invoked/completed lifecycle events.
Add async client methods run_workflow (start with optional wait) and stream_workflow (typed event iterator), plus is_replaying plumbing through the orchestration context protocol and both host adapters so live status is published only on non-replay execution.
* docs(samples): standalone durabletask workflow streaming sample
Add sample 10_workflow_streaming demonstrating the async DurableWorkflowClient API on a standalone Durable Task worker: run_workflow(wait=False) to start without blocking, then stream_workflow to consume typed WorkflowEvent objects as a WriterAgent -> ReviewerAgent -> publish pipeline runs.
* refactor(durabletask): internal-only checkpoint codec and host-scoped workflow event streaming
Two related hardening changes to the durable workflow hosting layer, plus a
rebase-restored improvement.
Internal-only serialization codec (MSRC follow-up):
- Rename serialize_value/deserialize_value -> _serialize_value/_deserialize_value
in the shared durabletask serialization module and update all call sites, so the
pickle-backed checkpoint codec is unambiguously framework-internal. Untrusted
input is still neutralized with strip_pickle_markers at the HTTP boundary.
- Remove the duplicate agent_framework_azurefunctions._serialization module and
import strip_pickle_markers from the shared durabletask module instead. Move its
unique serialization/strip-marker tests into the durabletask test suite.
Scope workflow event streaming to hosts that can carry it:
- Add WorkflowOrchestrationContext.supports_event_streaming. The standalone
DurableTask host returns True (no custom-status size cap, has a stream_workflow
consumer); the Azure Functions host returns False.
- The orchestrator now accumulates and publishes the WorkflowEvent timeline to the
orchestration custom status only when the host supports streaming. On Azure
Functions the custom status returns to its pre-streaming shape
({state[, pending_requests]}), which fixes orchestrator failures with
"The size of the JSON-serialized payload must not exceed 16 KB" and stops leaking
pickle markers into the HTTP status response. The Azure Functions status endpoint
never consumed the event stream.
Workflow start endpoint:
- Accept text/plain raw request bodies (fall back from get_json to the raw body),
restoring an improvement from main that the rebase conflict resolution dropped.
* fix(azurefunctions): scope workflow status/respond endpoints to the workflow orchestrator
The workflow/status/{instanceId} and workflow/respond/{instanceId}/{requestId}
HTTP endpoints resolved durable instances by ID only. The durable client looks up
IDs across every orchestration in the task hub (agent entities, any
user-registered orchestrations, and other apps sharing the hub), so a caller
holding one instance ID could read another orchestration's status -- including
pending HITL request payloads -- or inject external events into it.
Add AgentFunctionApp._is_workflow_orchestration() and gate both endpoints on it:
an instance whose orchestration name is not WORKFLOW_ORCHESTRATOR_NAME now returns
404 instead of leaking state or accepting events. send_hitl_response now fetches
the orchestration status and validates ownership before raising the external
event. Legitimate workflow instances are unaffected.
Mirrors the .NET fix in PR #6608.
* fix(durabletask): resolve CI typing failures
- serialization: rename _serialize_value/_deserialize_value back to
serialize_value/deserialize_value to follow the package convention for
cross-module internal helpers (matches strip_pickle_markers, resolve_type).
The leading underscore tripped pyright reportPrivateUsage on cross-module
imports under the strict source gate; internal-only status is preserved by
not exporting them from the public API.
- Remove type-ignore comments pyright flags as unnecessary
(reportUnnecessaryTypeIgnoreComment) in _worker.py, orchestrator.py,
serialization.py.
- test_08_dt_workflow: add AgentClientFactoryProtocol and annotate the
agent_client_factory fixture as type[AgentClientFactoryProtocol] (matching
test_01-07) so mypy/ty stop reporting "type has no attribute create".
- samples (08_workflow, 09_workflow_hitl): pass structured output via
FoundryChatOptions[Any](response_format=...) instead of a plain dict so the
samples pyright (basic) config accepts default_options.
---------
Co-authored-by: Gavin Aguiar <80794152+gavin-aguiar@users.noreply.github.com>
|
||
|
|
6e95517659 |
Python: Split type checkers by target (pyright source, 5 checkers on tests/samples) (#6443)
* Python: Split type checkers by target (pyright source, 5 checkers on tests/samples) Rework the typing setup along the lines of the 'too many type checkers' approach: - Pyright (strict) is now the sole source-code type checker; mypy is removed from source and its [tool.mypy] block becomes a relaxed profile used only for tests/samples. - Tests are checked by all five checkers (pyright relaxed, mypy, pyrefly, ty, zuban); samples by pyright, pyrefly, and ty. All run in a relaxed/ basic profile so authors aren't forced into over-annotation. - Add pyrightconfig.tests.json and bump sample pyright configs to basic. - Unify test/sample typing onto the same parallel fan-out used by source pyright via run_command_items in task_runner.py. - Make version-conditional imports symmetric: keep or drop the '# type: ignore' on both branches so results match across interpreter versions (local vs CI). - Update SKILL.md, DEV_SETUP.md, and CODING_STANDARD.md for the five gating checkers and pyright on source+tests+samples. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Fix merge regressions from main (typing + runtime) Merging main into the type-checker split branch surfaced regressions that the new five-checker test suite and unit tests caught: Runtime fixes: - anthropic: restore the dropped `cache_read_input_token_count` mapping in _parse_usage_from_anthropic (lost during merge conflict resolution). - gemini: _get_function_calling_mode test helper returned str(enum) ('FunctionCallingConfigMode.AUTO') instead of the enum value ('AUTO'). - openai: _response_id_from_token test helper was an infinite self-recursion; return token['response_id']. - orchestrations: reset output_events per approval iteration so the terminal output assertion counts only the final run. - core: drop a stale duplicate harness test whose message ('non-negative') contradicted the source ('positive'). - purview: import PolicyLocation/PolicyScope/ProtectionScopeActivities/ ExecutionMode used by the processor tests. Type-checker fixes (tests, relaxed profile): - core: pyright/mypy/pyrefly/ty/zuban green-ups across the harness, MCP, observability and types tests. - anthropic/openai: route provider-namespaced UsageDetails keys through a dict cast (extra_items TypedDict unsupported by mypy/ty). - purview: typed model constructors and cache-mock casts. - ag-ui: annotate WorkflowContext[Any, Any] so yield_output accepts test payloads, guard Optional forwarded_props, and ty-ignore intentional bad args. Source pyright (sole source checker) flagged unnecessary ignores newly introduced by merged code in core _tools.py and declarative _declarative_base.py. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Isolate per-package mypy cache in test-typing fan-out The parallel test-typing fan-out runs many mypy processes concurrently, all defaulting to a single shared ./.mypy_cache. Concurrent writes corrupt the cache and mypy aborts with INTERNAL ERROR (intermittently, depending on worker timing) -- which is why CI's Test Typing job failed on a shifting set of packages while a single-package run was fine. Give each mypy invocation an isolated cache dir keyed by its target paths so incremental caching still works per package without races. Other checkers (zuban/pyrefly/ty/pyright) maintain their own caches and are unaffected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Make lab pyright-only on source (drop source mypy) Lab was the last package still running mypy on its source code, requiring mypy-only `# type: ignore` comments that pyright (the sole source checker everywhere else) flags as unnecessary. Align lab with the rest of the monorepo: - Remove the lab source mypy poe tasks (mypy-gaia/lightning/tau2) and the now-dead strict [tool.mypy] config block. - Drop the 'Run lab mypy' CI step; lab source is type-checked by pyright only. Lab tests remain covered by the workspace test-typing fan-out (mypy, pyrefly, ty, zuban, pyright over tests using the relaxed root config). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Fix test-typing regressions from latest main merge A fresh merge from main brought in new test code never run under the five-checker test-typing suite. Green up across the affected packages: - core: narrow Optional span.attributes with 'and' guards in span filters and assert+cast the json.loads(...attributes[...]) reads (test_observability); match the existing as_agent ignore on the protocol-typed fixture (test_clients). - openai: align new streaming tests with the established chat_options dict pattern (ChatOptions TypedDict isn't assignable to dict), route Optional .annotations[0] access through a small _first_annotation helper (mirrors the file's assert-not-None convention), and annotate a mapped ResponseStream. - foundry_hosting: annotate error: dict[str, Any] = body.get(...) or {} (zuban needs the annotation). - foundry: narrow ignores for the live AIProjectClient credential arg (pyrefly) and connections.get_default (zuban) SDK type gaps. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * updated pyright version * pyright fix * Python: Fix source typing for pyright 1.1.410 Pyright 1.1.410 tightened several checks. Apply the same source fixes as upstream PR #6275: - anthropic: import AsyncAnthropicBedrock from anthropic.lib.bedrock and AsyncAnthropicVertex from anthropic.lib.vertex (no longer re-exported from the anthropic top-level package -> reportPrivateImportUsage). - core _types.py: cast the transform-hook result to UpdateT (reportAssignmentType). - core _workflows/_events.py: annotate the @contextmanager helper as Generator[None] instead of Iterator[None] (reportDeprecated). - redis: build the combined filter expression with an explicit loop instead of reduce(and_, ...), which pyright could no longer fully type (drops the now unused functools.reduce / operator.and_ imports). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Accept plain-text body in Azure Functions workflow/run endpoint The workflow_orchestrator already accepts plain strings as well as JSON objects via context.get_input(), but the start_workflow_orchestration HTTP handler only accepted JSON and returned 400 for any non-JSON body. This made the functions integration tests that POST text/plain to /api/workflow/run (e.g. test_09_workflow_shared_state) fail consistently with 400 != 202. Fall back to the raw request body (decoded as UTF-8) when the body is not JSON, rejecting only a truly empty body. The JSON path is unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
caa75f7cdd |
Python: Add Foundry Toolbox MCP skills hosted agent sample (#6363)
* Add 12_foundry_toolbox_mcp_skills hosted agent sample Demonstrates using MCPSkillsSource with a Foundry Toolbox MCP endpoint to discover and serve skills via SkillsProvider (progressive disclosure). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix env var reference in README and reuse local var in main.py Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Require AZURE_AI_MODEL_DEPLOYMENT_NAME and use placeholder in .env.example Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Document Toolbox MCP skills vs Foundry Skills in sample README Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Reference 12_foundry_toolbox_mcp_skills in parent README 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> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
9cafd7e58b |
Python: Refactor workflow as agent pending request handling (#6259)
* WIP: Refactor Workflow as agent pending request handling * WIP: debugging empty message bug * Working: Workflow as agent with function approval * Address Copilot comments * Fix mypy * Address comments and fix pipeline * Request info non function approval now becomes function call * Revert uv.lock * Fix mypy * Bump min version of azure-ai-project * Remove RequestInfoFunctionArgs * fix tests * Fix failing tests * Fix sample |