Skip to content

Merge feature/azure-ai-projects/vnext into Main. Do not complete this PR! - #47803

Open
dargilco wants to merge 31 commits into
mainfrom
feature/azure-ai-projects/vnext
Open

Merge feature/azure-ai-projects/vnext into Main. Do not complete this PR!#47803
dargilco wants to merge 31 commits into
mainfrom
feature/azure-ai-projects/vnext

Conversation

@dargilco

@dargilco dargilco commented Jul 1, 2026

Copy link
Copy Markdown
Member

No description provided.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the azure-ai-projects package version to 2.4.0 and adds a new 2.4.0 section to the changelog to begin tracking changes for that version.

Changes:

  • Added a new ## 2.4.0 (Unreleased) changelog section with subsections.
  • Bumped the library version constant from 2.3.0 to 2.4.0.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
sdk/ai/azure-ai-projects/CHANGELOG.md Adds a new 2.4.0 (Unreleased) entry scaffold (currently with placeholder bullets).
sdk/ai/azure-ai-projects/azure/ai/projects/_version.py Updates the package version constant to 2.4.0.

Comment thread sdk/ai/azure-ai-projects/CHANGELOG.md Outdated
Comment thread sdk/ai/azure-ai-projects/CHANGELOG.md Outdated
Copilot AI review requested due to automatic review settings July 16, 2026 21:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 25 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

sdk/ai/azure-ai-projects/tsp-location.yaml:22

  • These paths do not exist at the pinned fca510e0... commit. That tree still exposes openai-conversations, openai-evaluations, and openai-responses directly under src, so tsp-client update cannot resolve these additional directories. Keep the paths aligned with the pinned commit (or pin a commit that contains the nested layout).

Comment thread sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py Outdated
Comment thread sdk/ai/azure-ai-projects/CHANGELOG.md Outdated
Copilot AI review requested due to automatic review settings July 20, 2026 21:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 25 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

sdk/ai/azure-ai-projects/CHANGELOG.md:11

  • The 2.4.0 release notes still hide the actual breaking API changes behind a placeholder. This API surface removes ReminderPreviewTool and introduces/narrows several public request types, so consumers need concrete migration information before this stable release ships. Replace this placeholder with the breaking changes, and remove any empty placeholder sections rather than publishing them.
* Placeholder

Comment thread sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py Outdated
Comment thread sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py Outdated
@howieleung
howieleung force-pushed the feature/azure-ai-projects/vnext branch from 17fc856 to d68f0da Compare July 24, 2026 21:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 54 out of 54 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (5)

sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py:10511

  • With polling=False, Azure Core's NoPolling.resource() invokes this callback with the initial 201 response. That response is an EvaluatorGenerationJob, not a terminal payload containing result, so this path deserializes {} into an invalid EvaluatorVersion. Make the callback handle the initial response explicitly (or reject polling=False) and cover this mode with a test.
            deserialized = _deserialize(_models.EvaluatorVersion, response.json().get("result", {}))

sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py:17020

  • With polling=False, NoPolling passes the initial queued DataGenerationJob response to this callback. Since that body has no terminal result, the poller's result() becomes an invalid empty DataGenerationJobResult. Handle the initial response explicitly or disallow this polling mode, and add coverage for it.
            deserialized = _deserialize(_models.DataGenerationJobResult, response.json().get("result", {}))

sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py:17385

  • The new samples use this operation with polling=False, but NoPolling.result() invokes this callback on the initial queued OptimizationJob. Because the initial body lacks result, callers receive an invalid empty OptimizationJobResult. Handle the initial response explicitly or reject polling=False, with a regression test.
            deserialized = _deserialize(_models.OptimizationJobResult, response.json().get("result", {}))

sdk/ai/azure-ai-projects/samples/hosted_agents/rbac_util.py:88

  • Checking only the deterministic assignment name does not detect an equivalent role assignment created with another UUID. Azure then rejects create with RoleAssignmentExists, so this “ensure” helper fails on accounts that are already configured. Query/verify the existing principal-role-scope tuple, or tolerate the conflict after confirming it matches.
    sdk/ai/azure-ai-projects/samples/hosted_agents/rbac_util.py:132
  • This discards the (created, assignment_name) result, so callers cannot remove an assignment created for the temporary agent-version identity. Both toolbox samples delete that version during teardown, leaving an orphaned account-scope role assignment. Return cleanup information and delete only assignments created by the sample in its finally path.

Copilot AI review requested due to automatic review settings July 24, 2026 21:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 54 out of 54 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (9)

sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py:10511

  • polling=False selects NoPolling, whose result() runs this callback against the initial 201 response. That response is an EvaluatorGenerationJob, so its result is absent/null while queued; this returns an empty/None value instead of the advertised EvaluatorVersion. Handle the initial response shape explicitly (and mirror the fix asynchronously), or do not expose polling=False for this LRO.
            deserialized = _deserialize(_models.EvaluatorVersion, response.json().get("result", {}))

sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py:17020

  • With polling=False, NoPolling.result() invokes this callback on the initial DataGenerationJob, whose result is not available yet. Extracting result therefore returns an empty/None DataGenerationJobResult, contrary to the poller's return type. Handle the initial response shape explicitly (and mirror the fix asynchronously), or disallow polling=False for this operation.
            deserialized = _deserialize(_models.DataGenerationJobResult, response.json().get("result", {}))

sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py:17385

  • The new polling samples confirm that the initial 201 body is an OptimizationJob. When polling=False, NoPolling.result() passes that initial response here, so extracting result before the job finishes yields an empty/None OptimizationJobResult. Fix the no-polling contract consistently instead of requiring callers to recover the job through an undocumented raw_response_hook.
            deserialized = _deserialize(_models.OptimizationJobResult, response.json().get("result", {}))

sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py:7086

  • AsyncNoPolling.result() also deserializes the initial queued EvaluatorGenerationJob, not a terminal response. Its result is absent/null, so polling=False returns an empty/None value rather than EvaluatorVersion. Apply the same initial-response contract fix as in the synchronous operation.
            deserialized = _deserialize(_models.EvaluatorVersion, response.json().get("result", {}))

sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py:13968

  • The initial async response is an OptimizationJob (the new async polling sample parses it as such). Under polling=False, AsyncNoPolling.result() sends that response here, so extracting result returns empty/None before completion. Fix the no-polling contract rather than forcing callers to use raw_response_hook to obtain the job ID.
            deserialized = _deserialize(_models.OptimizationJobResult, response.json().get("result", {}))

sdk/ai/azure-ai-projects/samples/hosted_agents/rbac_util.py:37

  • This substring match can select the wrong project when names share a prefix (for example, project foo also matches /projects/foobar), causing RBAC to be assigned at the wrong account scope. Match the normalized resource ID suffix exactly.
    sdk/ai/azure-ai-projects/.github/skills/azure-ai-projects-emit-from-typespec/SKILL.md:37
  • The prerequisite documentation explicitly supports Windows PowerShell 5.1, whose executable is powershell.exe, not pwsh. This check therefore rejects a documented supported setup before the workflow starts. Use the Windows PowerShell command here, or implement a check that accepts either executable.
pwsh --version

sdk/ai/azure-ai-projects/samples/hosted_agents/sample_routines_with_teams_message_trigger.py:73

  • The package supports Python 3.9 (pyproject.toml:31), but evaluating this function definition on 3.9 raises TypeError because PEP 604 unions (str | None) require Python 3.10. Use Optional[str] (and import Optional) so the new sample can run on the documented minimum version.
    sdk/ai/azure-ai-projects/samples/hosted_agents/rbac_util.py:88
  • This only checks the deterministic assignment name generated by this helper. If the principal already has the same role and scope under an administrator-created UUID, get() returns 404 and this create() returns RoleAssignmentExists, so an already-correct RBAC setup fails. Detect an equivalent existing assignment (or handle the duplicate-assignment response as success) before creating.

@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor
[Pilot] PR Pipeline Failure Analysis

A CI pipeline failed on this pull request. Here is an automated analysis of what went wrong and how to get the build green.

What failed

One test case failed consistently across three test configurations (sdist, mindependency, and whl) on the windows2022_312 job for the azure-ai-projects package:

  • TestSamples.test_datasets_samples[sample_dataset_generation_job_simpleqna_with_prompt_source]

The failure appears in all three test run configurations, suggesting this is a test/sample code issue rather than a packaging or infrastructure problem.

Recommended next steps

  • Investigate the sample sample_dataset_generation_job_simpleqna_with_prompt_source — likely in sdk/ai/azure-ai-projects/samples/ — for any issues with the SimpleQnAWithPromptSource dataset generation job scenario.
  • Check whether this sample relies on a service feature or API that has changed in this PR (given the PR adds 2826 lines and removes 1429 lines, an API contract change is plausible).
  • Run the failing test locally on Windows with Python 3.12 to reproduce and debug:
    pytest sdk/ai/azure-ai-projects/tests/samples/test_samples.py -k "test_datasets_samples[sample_dataset_generation_job_simpleqna_with_prompt_source]"
    
  • If the sample code needs updating to match the new API, update it and push a new commit.
  • See the CI troubleshooting guide: https://aka.ms/ci-fix
  • Push new commits to address the failures; this comment updates automatically on the next failing run.
Raw pipeline analysis (azsdk ci analyze)
Analyzing pipeline https://github.com/Azure/azure-sdk-for-python/pull/47803...
--------------------------------------------------------------------------------
Failed Tests
--------------------------------------------------------------------------------
{
  "/tmp/6615416/LLM Artifacts - windows2022_312 - 2/ai-azure-ai-projects-test-junit-sdist.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples.TestSamples.test_datasets_samples[sample_dataset_generation_job_simpleqna_with_prompt_source]"
  ],
  "/tmp/6615416/LLM Artifacts - windows2022_312 - 2/ai-azure-ai-projects-test-junit-mindependency.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples.TestSamples.test_datasets_samples[sample_dataset_generation_job_simpleqna_with_prompt_source]"
  ],
  "/tmp/6615416/LLM Artifacts - windows2022_312 - 2/ai-azure-ai-projects-test-junit-whl.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples.TestSamples.test_datasets_samples[sample_dataset_generation_job_simpleqna_with_prompt_source]"
  ]
}

Copilot detected the failing pipeline and generated the analysis above. To have it attempt a fix automatically, reply with @copilot please fix the failing pipeline on this PR.

Generated by Pipeline Analysis - Next Steps · 18.5 AIC · ⌖ 6.16 AIC · ⊞ 6.6K ·

Copilot AI review requested due to automatic review settings July 24, 2026 22:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 54 out of 54 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (6)

sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py:10511

  • With polling=False, NoPolling invokes this callback on the initial 201 response, whose body is an EvaluatorGenerationJob and has no result yet. This therefore deserializes {} as an EvaluatorVersion and discards the job ID, leaving callers unable to use get_generation_job or cancel_generation_job while the job runs. Expose the initial job metadata through a supported poller/result API (and mirror the fix asynchronously) instead of treating the initial response as a terminal result.
            deserialized = _deserialize(_models.EvaluatorVersion, response.json().get("result", {}))

sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py:7086

  • With polling=False, AsyncNoPolling resolves this callback against the initial job response, which does not contain result. The poller consequently returns an empty EvaluatorVersion and loses the job ID needed by the public get/cancel APIs. The async LRO needs the same supported initial-job access as the sync API.
            deserialized = _deserialize(_models.EvaluatorVersion, response.json().get("result", {}))

sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py:17020

  • This callback strips the enclosing DataGenerationJob, including its ID, and returns only DataGenerationJobResult, which has no provenance/job-ID property. Callers can no longer invoke the still-public get, cancel, or delete job methods for the job they just created; the updated samples consequently stop deleting job records. Preserve a public job ID (for example on the result, as evaluator generation does) or otherwise expose the initial/final job metadata.
            deserialized = _deserialize(_models.DataGenerationJobResult, response.json().get("result", {}))

sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py:13604

  • The async data-generation LRO also discards the enclosing job and returns a result type with no job ID. This makes the public async get/cancel/delete methods unusable for the newly created job without relying on raw-response internals. Preserve and expose the job identifier in the generated contract.
            deserialized = _deserialize(_models.DataGenerationJobResult, response.json().get("result", {}))

sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py:17385

  • With polling=False, NoPolling calls this deserializer on the initial OptimizationJob response, where result is absent, so poller.result() becomes an empty OptimizationJobResult and the job ID is lost. The new manual-polling and cancellation samples have to use raw_response_hook solely to recover that ID. Provide a supported initial-job result/accessor so cancellation and manual polling do not depend on pipeline internals.
            deserialized = _deserialize(_models.OptimizationJobResult, response.json().get("result", {}))

sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py:13968

  • The async polling=False path has the same issue: AsyncNoPolling feeds the initial job response to this callback, but no result exists yet, producing an empty result and dropping the job ID. This is why the async manual-polling sample captures and parses a raw pipeline response. Expose initial job metadata through the public LRO API instead.
            deserialized = _deserialize(_models.OptimizationJobResult, response.json().get("result", {}))

Comment thread sdk/ai/azure-ai-projects/azure/ai/projects/models/_models.py
Copilot AI review requested due to automatic review settings July 25, 2026 00:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

Copilot AI review requested due to automatic review settings July 28, 2026 05:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 28, 2026 05:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

sdk/ai/azure-ai-projects/docs/tool-classes-removed-properties.md:43

  • The count is incorrect: only the nine preview classes with non-empty entries had properties removed. The stable classes retained those properties as deprecated, as documented in CHANGELOG.md:89-90. Update the count and summary pattern so they do not repeat the incorrect GA-removal claim.
- **Classes with removed properties:** 19
- **Common pattern:** `name`, `description`, and `tool_configs` were moved exclusively to `ToolboxTool` subclasses

Comment on lines +3 to +21
The following Tool-derived classes had properties **removed** in v2.3.0 compared to v2.2.0. These properties (`name`, `description`, `tool_configs`) now only exist on the corresponding `ToolboxTool` subclasses.

## General Availability Tools

| Class Name | Removed Properties |
|------------|-------------------|
| `AzureAISearchTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` |
| `AzureFunctionTool` | `tool_configs: Optional[dict[str, ToolConfig]]` |
| `BingGroundingTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` |
| `CaptureStructuredOutputsTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` |
| `CodeInterpreterTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` |
| `FileSearchTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` |
| `FunctionShellToolParam` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` |
| `FunctionTool` | *(no changes)* |
| `ImageGenTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` |
| `LocalShellToolParam` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` |
| `MCPTool` | `tool_configs: Optional[dict[str, ToolConfig]]` |
| `OpenApiTool` | `tool_configs: Optional[dict[str, ToolConfig]]` |
| `WebSearchTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` |
| `MCPTool` | `tool_configs: Optional[dict[str, ToolConfig]]` |
| `OpenApiTool` | `tool_configs: Optional[dict[str, ToolConfig]]` |
| `WebSearchTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` |
v
* Refactor agent name retrieval to use a fallback mechanism

- Updated multiple sample scripts to change the way the agent name is retrieved from environment variables.
- Replaced the default value assignment using `os.environ.get("FOUNDRY_AGENT_NAME", "MyAgent")` with a more concise approach using `os.environ.get("FOUNDRY_AGENT_NAME") or "MyAgent"`.
- This change ensures that if the environment variable is not set, the fallback value "MyAgent" is still used, while improving code readability.
- The affected files include various agent tools and hosted agent samples across the project.

* rever dataset generation job polling and update assistant prompt
Copilot AI review requested due to automatic review settings July 28, 2026 22:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 53 out of 53 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (5)

sdk/ai/azure-ai-projects/docs/tool-classes-removed-properties.md:22

  • Remove this stray v; it renders as an unexplained paragraph between the two tables.
v

sdk/ai/azure-ai-projects/docs/tool-classes-removed-properties.md:3

  • This is incorrect for the GA tools: the published 2.3.0 models retain these properties and mark them deprecated (for example, AzureAISearchTool still accepts name, description, and tool_configs), matching CHANGELOG.md:89-90. Only the preview-tool properties were removed in 2.3.0. Rewrite the GA section and summary so users are not told that valid 2.3.0 constructor arguments disappeared.
The following Tool-derived classes had properties **removed** in v2.3.0 compared to v2.2.0. These properties (`name`, `description`, `tool_configs`) now only exist on the corresponding `ToolboxTool` subclasses.

sdk/ai/azure-ai-projects/samples/hosted_agents/hosted_agents_util.py:4

  • os is never referenced in this utility, so this added import will fail the package's unused-import Pylint check. Remove it.
    sdk/ai/azure-ai-projects/samples/hosted_agents/github_routine_util.py:15
  • This new module never uses time, urlparse, ResourceNotFoundError, or AIProjectClient, so the sample validation will report unused imports. Keep only the imports used by the two helpers.
    sdk/ai/azure-ai-projects/samples/hosted_agents/sample_routines_with_github_issue_trigger.py:151
  • GITHUB_USERNAME is documented as either a user or an organization, but this always sends that owner as the issue assignee. An organization cannot be assigned an issue, so automatic triggering fails for organization-owned repositories. Use a separate optional user assignee (and omit assignees when absent) rather than reusing the repository owner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants