快速入門:最佳化代管代理程式

在這個快速入門中,你會部署優化範例代理,執行代理優化器以改進指令,然後部署獲勝候選者。

關於每個步驟背後的概念以及完整的端到端路徑,請參見 優化工作流程。

先決條件

在開始之前,您需要:

  • azd CLI (Azure Developer CLI).

  • Azure CLI for authentication.

  • 適用於 azd 的 microsoft.foundry 擴充功能 (azure.ai.agents 相依性 0.1.40-preview 或更新版本):

    azd ext install microsoft.foundry
    

    如果已經安裝好,請升級:

    azd ext upgrade microsoft.foundry
    
  • Azure CLI for authentication.

  • Python 3.10 或更新版本。

  • 此路徑中使用的 Python 套件:

    pip install "azure-ai-projects>=2.5.0" azure-ai-agentserver-optimization azure-identity python-dotenv
    
  • 一個現有的 Foundry 專案,其中已包含你想用於最佳化的託管代理、已註冊的資料集和評估器。

  • Azure CLI for authentication.

  • .NET 10 SDK 或更新版本。

  • 此路徑中使用的 .NET 套件。

    dotnet add package Azure.AI.Projects --prerelease
    dotnet add package Azure.Identity
    
  • 一個現有的 Foundry 專案,其中已包含你想用於最佳化的託管代理、已註冊的資料集和評估器。

Tip

如果你沒有 Foundry Toolkit,可以從 Visual Studio Code 市集安裝。 Foundry Toolkit 將您的 Foundry 資源、模型目錄、代管代理部署與測試場,以及代理程式最佳化整合到 Visual Studio Code 中。 如果有提示就重新載入 Visual Studio Code,然後登入 Azure。 欲了解擴充功能,請參閱「使用 Microsoft Foundry Toolkit for Visual Studio Code 擴充套件」。

  • 一台安裝 Microsoft Foundry Skill 的程式代理主機。

  • Azure CLI 同 Azure Developer CLI (AZD) 安裝並認證:

    az login
    azd auth login
    
  • 適用於 AZD 的 microsoft.foundry 擴充功能。 在開始工作流程前先安裝:

    azd ext install microsoft.foundry
    

    如果已經安裝好,就升級它:

    azd ext upgrade microsoft.foundry
    
  • 你的 Azure 訂閱必須在代理優化器的允許名單上。 請聯絡您的 Microsoft 代表申請存取權限。

步驟 1:建立專案

從優化範例範本初始化一個新專案:

mkdir my-agent && cd my-agent
azd ai agent init -m https://github.com/microsoft-foundry/foundry-samples/blob/main/samples/python/hosted-agents/bring-your-own/responses/optimization-customer-support/azure.yaml .

此範本會匯入最佳化客戶支援樣本,這是一個採用自備方式和回覆通訊協定,可進行最佳化的 Python 託管 Agent。 它代表消費性電子客服代理,負責訂單查詢、退貨、保固理賠、故障排除、抱怨、建議及升級處理。 刻意簡化的基線教學,使得教學優化與技能發現帶來的改進變得容易比較。

範例呼叫load_config()以載入基線或候選配置,包含.agent_configs/baseline/eval.yaml、完整且快速的評估資料集、容器配置,以及 Foundry 部署清單。 互動式流程會匯入這些檔案及提示,用於你的 Azure 訂閱、區域及模型部署設定。

Tip

如果你已經有現有的代理專案,請參閱 「讓你的代理優化器準備好 加入優化支援」。

如果你已經有 Foundry 專案,請加入 -p <project-resource-id> 以指定現有資源。

若要優化已部署的代理程式,無需執行 azd ai agent init 或建立 azure.yaml 檔案 .azure ,請跳過此專案建立步驟,依 照「優化現有代理程式而不使用 AZD 專案檔案」操作。

步驟 2:配置與部署

驗證並配置 Azure 資源:

az login
azd auth login
azd provision

配置約需兩分鐘,建立 Foundry 帳號、專案、Azure Container Registry 及模型部署。

部署代理:

azd deploy

測試部署作業:

azd ai agent invoke "What is 2+2?"

步驟 3:產生評估套件並進行優化

為您的代理建立評估資料集和評估器:

azd ai agent eval generate

此步驟會建立 eval.yaml、一個測試資料集,以及根據您的代理程式指示建立的評分評估工具。 優化器利用這些檔案來衡量改進。

執行優化器:

azd ai agent optimize --max-candidates 2

CLI 會提示你選擇一個最佳化模型。 若要跳過提示,請直接傳遞:

azd ai agent optimize --max-candidates 2 --optimize-model gpt-5

CLI 會從 azure.yaml 偵測你的代理程式,並自動使用產生的 eval.yaml。 有兩位候選人時,優化通常約 8 分鐘完成。 即時進度顯示:

Optimizing agent "customer-support-py"...
  Config: eval.yaml
  Baseline saved to .agent_configs/baseline/metadata.yaml
  Job ID: opt_162bd0f09....
  Status: pending
  Portal: <OPTIMIZATION-JOB-URL>

使用入口網站 URL 來監視 Foundry 入口網站中的作業。

評估模型會對每個回應進行評分(任何聊天完成模型都適用)。 優化模型(--optimize-model)會產生更優秀的候選者,且必須來自支援的清單(gpt-5 家族或 DeepSeek)。 你也可以在 optimization_model 的 options: 下設定 eval.yaml,以避免每次都要傳遞該旗標。

步驟四:部署贏家

輸出中的星號(*)表示最佳候選。 先在本地套用優化後的設定,然後部署:

azd ai agent optimize apply --candidate <candidate-id>
azd deploy

apply 指令會將最佳化設定下載到 .agent_configs/<candidate_id>/ 中,並更新你的 azure.yaml 以使用新的指示。 此 deploy 指令會使用 CodeDeploy,將已最佳化的代理程式部署上線。

請聯絡您的代理人確認改善:

azd ai agent invoke "What is your return policy?"

你也可以進行評估來確認分數的提升:

azd ai agent eval run

Python SDK 路徑

如果你想用 Python 執行優化器,而不是前面提到的 Azure Developer CLI 工作流程,請採用以下步驟。

這條路徑假設你已經在現有的 Foundry 專案中擁有以下資源:

  • 可最佳化的託管代理程式。
  • 一個註冊的訓練資料集。
  • 註冊評估員。

與前面描述的 Azure Developer CLI 流程不同,Python SDK 路徑不會為你提供專案架構、eval.yaml產生資料集或評估器。 如果你想讓取樣自動產生這些素材,請先使用 azd ai agent eval generate 。

1. 建立 .env 檔案

建立一個工作資料夾,然後加入 .env 以下數值的檔案:

FOUNDRY_PROJECT_ENDPOINT=<your-project-endpoint>
FOUNDRY_AGENT_NAME=<your-hosted-agent-name>
DATASET_NAME=<your-registered-dataset-name>
EVALUATOR_NAME=<your-registered-evaluator-name>
DATASET_VERSION=1
POLL_INTERVAL_SECONDS=10
EVAL_MODEL=<your-eval-model-deployment-name>
OPTIMIZATION_MODEL=<your-optimization-model-deployment-name>

從同一個工作資料夾執行腳本,這樣 load_dotenv() 就能自動載入 .env 檔案。 如果你想從另一個目錄執行,先在你的 shell 環境中設定相同的數值。

請使用 Foundry 專案的 概覽 頁面中的確切專案端點。 Python 腳本會立即發送第一個請求。 若 FOUNDRY_PROJECT_ENDPOINT 僅為佔位符或指向錯誤專案,則執行失敗。ResourceNotFound: The project does not exist

將 EVAL_MODEL 和 OPTIMIZATION_MODEL 設定為 Foundry 專案中已存在的部署名稱,而不只是模型系列名稱。 例如,如果您的專案部署名為 gpt-4.1-mini 或 DeepSeek-V3.2,請在 .env 中使用該確切的部署名稱。

2. 執行最佳化任務

在與 optimize_hosted_agent.py 相同的資料夾中建立一個名為 .env 的檔案:


"""
DESCRIPTION:
    Create an optimization job for a hosted agent using the latest agent
    optimization API, poll the job to completion, and list its candidates.

USAGE:
    python optimize_hosted_agent_v3.py

    Before running the sample:

    pip install azure-ai-projects azure-ai-agentserver-optimization azure-identity python-dotenv

    Set these environment variables with your own values:
    1) FOUNDRY_PROJECT_ENDPOINT - Required. The Microsoft Foundry project endpoint.
    2) FOUNDRY_AGENT_NAME       - Required. The hosted agent name.
    3) DATASET_NAME             - Required. The registered training dataset name.
    4) EVALUATOR_NAME           - Required. The registered evaluator name.
    5) DATASET_VERSION          - Optional. The dataset version. Defaults to "1".
    6) EVAL_MODEL               - Optional. The evaluation model. Defaults to "gpt-4o".
    7) OPTIMIZATION_MODEL       - Optional. The optimization model. Defaults to "gpt-5".
    8) POLL_INTERVAL_SECONDS    - Optional. Seconds between status polls. Defaults to 10.
    9) OPTIMIZATION_JOB_ID      - Optional. An existing job ID to resume instead of creating a job.
   10) OPTIMIZATION_LOCAL_DIR   - Optional. Path to the local .agent_configs directory.
   11) CREDENTIAL_PROCESS_TIMEOUT_SECONDS
                                - Optional. Credential subprocess timeout. Defaults to 60.
"""

import os
import time
from pathlib import Path

from azure.ai.agentserver.optimization import load_config, load_skills_from_dir
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import (
    AgentOptimizationBaselineAgentConfiguration,
    AgentOptimizationCandidateExpand,
    AgentOptimizationCandidateSearchConfiguration,
    AgentOptimizationConfiguration,
    AgentOptimizationEvaluationConfiguration,
    AgentOptimizationEvaluator,
    AgentOptimizationFoundryAgentTargetConfiguration,
    AgentOptimizationJob,
    AgentOptimizationModelConfiguration,
    AgentOptimizationSkill,
    AgentOptimizationSpace,
    AgentOptimizationTargetCompletionDatasetReferenceDataSource,
    AgentOptimizationTargetCompletionEvaluationSet,
    EvaluationModelConfiguration,
    JobStatus,
    TargetAttribute,
)
from azure.identity import DefaultAzureCredential
from dotenv import load_dotenv

load_dotenv()

endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]
agent_name = os.environ["FOUNDRY_AGENT_NAME"]
dataset_name = os.environ["DATASET_NAME"]
evaluator_name = os.environ["EVALUATOR_NAME"]
dataset_version = os.environ.get("DATASET_VERSION", "1")
eval_model = os.environ.get("EVAL_MODEL", "gpt-4o")
optimization_model = os.environ.get("OPTIMIZATION_MODEL", "gpt-5")
poll_interval_seconds = int(os.environ.get("POLL_INTERVAL_SECONDS", "10"))
existing_job_id = os.environ.get("OPTIMIZATION_JOB_ID")
credential_process_timeout_seconds = int(
    os.environ.get("CREDENTIAL_PROCESS_TIMEOUT_SECONDS", "60")
)

# Reads the hosted agent's baseline config from .agent_configs/baseline/metadata.yaml.
optimization_config = load_config()

target_attributes = [TargetAttribute.INSTRUCTIONS]
baseline_configuration = None
if optimization_config:
    loaded_skills = optimization_config.skills
    if not loaded_skills and optimization_config.skills_dir:
        loaded_skills = load_skills_from_dir(Path(optimization_config.skills_dir))

    skills = [
        AgentOptimizationSkill(
            name=skill.name,
            description=skill.description,
            body=skill.body or None,
        )
        for skill in loaded_skills
    ]

    if skills:
        target_attributes.append(TargetAttribute.SKILLS)
    if optimization_config.tool_definitions:
        target_attributes.append(TargetAttribute.TOOLS)

    baseline_configuration = AgentOptimizationBaselineAgentConfiguration(
        system_prompt=optimization_config.instructions,
        current_model=optimization_config.model,
        skills=skills or None,
        tools=optimization_config.tool_definitions or None,
    )

with (
    DefaultAzureCredential(
        process_timeout=credential_process_timeout_seconds
    ) as credential,
    AIProjectClient(endpoint=endpoint, credential=credential) as project_client,
):
    job_request = AgentOptimizationJob(
        target_configuration=AgentOptimizationFoundryAgentTargetConfiguration(
            name=agent_name
        ),
        optimization_model_configuration=AgentOptimizationModelConfiguration(
            model=optimization_model
        ),
        optimization_configuration=AgentOptimizationConfiguration(
            evaluation_configuration=AgentOptimizationEvaluationConfiguration(
                training_set=AgentOptimizationTargetCompletionEvaluationSet(
                    source=AgentOptimizationTargetCompletionDatasetReferenceDataSource(
                        name=dataset_name,
                        version=dataset_version,
                    )
                ),
                evaluators=[AgentOptimizationEvaluator(name=evaluator_name)],
                evaluation_model=EvaluationModelConfiguration(model=eval_model),
            ),
            candidate_search_configuration=AgentOptimizationCandidateSearchConfiguration(
                max_candidates=2
            ),
            baseline_agent_configuration=baseline_configuration,
            agent_optimization_space=AgentOptimizationSpace(
                target_attributes=target_attributes
            ),
        ),
    )

    if existing_job_id:
        job_id = existing_job_id
    else:
        poller = project_client.agents.begin_create_optimization_job(
            job=job_request,
            polling=False,
        )
        job_id = poller.details.get("job_id")
        if not isinstance(job_id, str):
            raise RuntimeError(
                "The create operation did not return an optimization job ID."
            )

    print(f"Optimization job ID: {job_id}")

    terminal_statuses = {
        JobStatus.SUCCEEDED,
        JobStatus.FAILED,
        JobStatus.CANCELLED,
    }
    job = project_client.agents.get_optimization_job(job_id=job_id)
    print("Optimization job started, waiting for completion...")
    while job.status not in terminal_statuses:
        print(f"\tstatus=`{job.status}`")
        time.sleep(poll_interval_seconds)
        job = project_client.agents.get_optimization_job(job_id=job_id)
    print(f"\tstatus=`{job.status}`")

    for warning in job.warnings or []:
        print(f"[WARNING] {warning}")

    if job.status == JobStatus.FAILED:
        message = job.error.message if job.error else "<no error message>"
        raise RuntimeError(f"Optimization job `{job.id}` failed: {message}")
    if job.status == JobStatus.CANCELLED:
        raise RuntimeError(f"Optimization job `{job.id}` was cancelled.")
    if job.result is None:
        raise RuntimeError(f"Optimization job `{job.id}` completed without a result.")

    result = job.result
    summary = result.candidate_summary
    if summary:
        print(f"Baseline candidate: {summary.baseline_id}")
        print(f"Best candidate: {summary.best_id}")
        print(f"Completed optimized candidates: {summary.completed_candidate_count}")
        if summary.baseline_score is not None:
            print(f"Baseline score: {summary.baseline_score:.4f}")
        if summary.best_score is not None:
            print(f"Best score: {summary.best_score:.4f}")
    if result.termination_reason:
        print(f"Termination reason: {result.termination_reason}")

    for candidate in project_client.agents.list_optimization_candidates(
        job_id=job_id,
        expand=[AgentOptimizationCandidateExpand.MUTATIONS],
    ):
        details = [
            f"{candidate.name}: candidate_id={candidate.candidate_id}",
            f"status={candidate.status}",
        ]
        if candidate.evaluation:
            if candidate.evaluation.score is not None:
                details.append(f"score={candidate.evaluation.score:.4f}")
            if candidate.evaluation.avg_tokens is not None:
                details.append(f"avg_tokens={candidate.evaluation.avg_tokens:.0f}")
        print(", ".join(details))

執行腳本:

python optimize_hosted_agent.py

優化工作 ID 會在提交後立即列印;用它來監控 Foundry 入口的進度。

當工作成功時,腳本會列印出中標候選人及其 candidate_id。

與 azd ai agent optimize不同,Python SDK 流程不會建立本地.agent_configs/baseline/metadata.yaml檔案。 優化工作的中繼資料會保留在回傳 job 的物件及 Foundry 服務回應中,包括基線候選、最佳候選及評分候選清單。

3. 申請當選候選人

如果您也正在使用上述 CLI 流程中用到的本機azd專案,請使用 Python 指令碼傳回的 candidate_id 來套用勝出候選項目:

azd ai agent optimize apply --candidate <candidate-id>
azd deploy

如果你只需要檢查結果,請在推廣前,先用腳本列印的候選人分數和評估識別碼在 Foundry 中審查中獎配置。

C# SDK 路徑

如果你想從 .NET 執行優化器,而不是使用前面描述的 Azure 開發者 CLI 工作流程,請依照以下步驟操作。

這條路徑假設你已經在現有的 Foundry 專案中擁有以下資源:

  • 可最佳化的託管代理程式。
  • 一個註冊的訓練資料集。
  • 註冊的評估器,例如內建的 builtin.task_adherence 評估器。

與前面描述的 Azure Developer CLI 流程不同,.NET SDK 路徑不會為你建立專案架構,也不會產生eval.yaml資料集或評估器。 如果你想讓取樣自動產生這些素材,請先使用 azd ai agent eval generate 。

1. 設定你的環境變數

建立一個主控台應用程式,然後在執行之前,先在您的 Shell 中設定這些值:

FOUNDRY_PROJECT_ENDPOINT=<your-project-endpoint>
FOUNDRY_AGENT_NAME=<your-hosted-agent-name>
DATASET_NAME=<your-registered-dataset-name>
DATASET_VERSION=1
EVALUATOR_NAME=builtin.task_adherence
EVAL_MODEL=<your-eval-model-deployment-name>
OPTIMIZATION_MODEL=<your-optimization-model-deployment-name>

請使用 Foundry 專案的 概覽 頁面中的確切專案端點。

將 EVAL_MODEL 和 OPTIMIZATION_MODEL 設定為 Foundry 專案中已存在的部署名稱,而不只是模型系列名稱。 最佳化模型必須是優化器所支援的推理模型。 如果你選擇不支援的部署,服務會回傳一個錯誤,列出允許的模型。

2. 執行最佳化任務

以下列程式碼取代 Program.cs。

代理優化要求每個請求都包含 AgentsOptimization=V2Preview 功能標頭。 FoundryFeaturesPolicy本範例中的類別會將該標頭加到用戶端發送的每個請求中:

using System.ClientModel.Primitives;
using Azure.AI.Projects;
using Azure.AI.Projects.Agents;
using Azure.Identity;

#pragma warning disable AAIP001

// Adds the feature header that agent optimization requires.
public sealed class FoundryFeaturesPolicy(string features) : PipelinePolicy
{
    public override void Process(PipelineMessage message, IReadOnlyList<PipelinePolicy> pipeline, int index)
    {
        message.Request.Headers.Set("Foundry-Features", features);
        ProcessNext(message, pipeline, index);
    }

    public override ValueTask ProcessAsync(PipelineMessage message, IReadOnlyList<PipelinePolicy> pipeline, int index)
    {
        message.Request.Headers.Set("Foundry-Features", features);
        return ProcessNextAsync(message, pipeline, index);
    }
}

public static class Program
{
    public static void Main()
    {
        var endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT")!;
        var agentName = Environment.GetEnvironmentVariable("FOUNDRY_AGENT_NAME")!;
        var datasetName = Environment.GetEnvironmentVariable("DATASET_NAME")!;
        var datasetVersion = Environment.GetEnvironmentVariable("DATASET_VERSION") ?? "1";
        var evaluatorName = Environment.GetEnvironmentVariable("EVALUATOR_NAME") ?? "builtin.task_adherence";
        var evalModel = Environment.GetEnvironmentVariable("EVAL_MODEL")!;
        var optimizationModel = Environment.GetEnvironmentVariable("OPTIMIZATION_MODEL")!;

        var options = new AIProjectClientOptions();
        options.AddPolicy(new FoundryFeaturesPolicy("AgentsOptimization=V2Preview"), PipelinePosition.PerCall);

        AIProjectClient projectClient = new(new Uri(endpoint), new DefaultAzureCredential(), options);
        AgentOptimizationJobs optimizationJobs = projectClient.AgentAdministrationClient.GetAgentOptimizationJobs();

        OptimizationJob job = new()
        {
            Inputs = new OptimizationJobInputs(
                new OptimizationAgentIdentifier(agentName),
                new OptimizationReferenceDatasetInput(datasetName) { Version = datasetVersion },
                new[] { new OptimizationEvaluatorRef(evaluatorName) })
            {
                Options = new OptimizationOptions
                {
                    MaxCandidates = 2,
                    EvalModel = evalModel,
                    OptimizationModel = optimizationModel,
                    // The optimizer needs at least one optimizable target, such as the
                    // baseline system prompt, the tool definitions, or skills.
                    OptimizationConfig =
                    {
                        ["system_prompt"] = BinaryData.FromObjectAsJson(
                            "You are a helpful assistant that answers user requests accurately and concisely."),
                    },
                },
            },
        };

        OptimizationJob created = optimizationJobs.Create(job);
        Console.WriteLine($"Optimization job started: {created.Id}");

        OptimizationJob current = created;
        while (current.Status != AgentsJobStatus.Succeeded
            && current.Status != AgentsJobStatus.Failed
            && current.Status != AgentsJobStatus.Cancelled)
        {
            Thread.Sleep(TimeSpan.FromSeconds(20));
            current = optimizationJobs.Get(created.Id);
            Console.WriteLine($"\tstatus=`{current.Status}`");
        }

        Console.WriteLine($"Final status: {current.Status}");

        if (current.Result is not null)
        {
            Console.WriteLine($"Baseline candidate: {current.Result.Baseline}");
            Console.WriteLine($"Best candidate: {current.Result.Best}");

            foreach (OptimizationCandidate candidate in current.Result.Candidates)
            {
                Console.WriteLine(
                    $"{candidate.Name}: candidate_id={candidate.CandidateId}, " +
                    $"avg_score={candidate.AvgScore:F4}, " +
                    $"avg_tokens={candidate.AvgTokens:F0}");
            }
        }
    }
}

執行應用程式:

dotnet run

當工作成功時,應用程式會列印出中標候選人及其 candidate_id:

Optimization job started: opt_<job-id>
        status=`in_progress`
        status=`succeeded`
Final status: succeeded
Baseline candidate: cand_opt_<job-id>_0000
Best candidate: cand_opt_<job-id>_0000
baseline: candidate_id=cand_opt_<job-id>_0000, avg_score=1.0000, avg_tokens=0

與 azd ai agent optimize不同,.NET SDK 流程不會建立本地.agent_configs/baseline/metadata.yaml檔案。 優化工作元資料會保留在回傳的工作物件及 Foundry 服務回應中,包括基線候選人、最佳候選人及評分候選人清單。

3. 申請當選候選人

如果你也在 CLI 流程中使用的本地 azd 專案工作,請使用 App 回傳的項目 candidate_id 來套用中標候選:

azd ai agent optimize apply --candidate <candidate-id>
azd deploy

如果你只需要檢查結果,請在 Foundry 中用應用程式列印的候選人分數和評估識別碼,在推廣前先在 Foundry 中審查中獎配置。

在 VS Code 裡執行優化

Foundry Toolkit 包含針對已部署的託管代理的原生代理優化體驗。 從代理遊樂場,你可以啟動優化執行,將候選方案與基線比較,檢視設定變更,並部署最佳候選方案。

步驟 1:選擇已部署的託管代理

  1. 在工作列中選擇 Foundry 工具包。
  2. 在 「我的資源」中,選擇 代理人。
  3. 如果你有已部署的託管代理,選擇它以開啟託管代理遊樂場。
  4. 如果你還沒有部署的主機代理,請完成 Quickstart 中的 VS Code 路徑 :部署你的第一個主機代理。 部署結束後,回到 代理 伺服器並選擇新的託管代理。

步驟 2:開始優化執行

  1. 選擇 「優化 」標籤。

Foundry Toolkit 中一個託管代理的截圖,選中了優化索引標籤,且新增優化按鈕可用。

  1. 選擇 新優化。

  2. 在 選擇工作區中,選擇包含所選主機代理程式碼的工作區:

    • 如果目前工作區包含代理程式碼及其 azure.yaml 檔案,請選擇 目前工作區。
    • 選擇瀏覽 ...... 以開啟包含代理代碼的工作區。

    Foundry Toolkit 利用工作區檔案來準備優化,並將候選物件套用到匹配 azure.ai.agent 服務中。

Foundry Toolkit 中「選擇工作區」提示的截圖,顯示目前工作區與瀏覽選項,用於尋找託管代理程式碼。

  1. Foundry Toolkit 會開啟 GitHub Copilot Chat,並發送一個包含所選代理的類型、名稱及 Foundry 專案端點的代理優化器請求。

  2. 在 Copilot Chat 回答四個優化問題:

    輸入 需提供的內容
    評估指標 輸入可用的指標或評估工具。 如果沒有,請選擇執行 azd ai agent eval generate 或使用優化器內建的預設值。
    Dataset 選擇最佳化資料集。 如果沒有,請選擇執行 azd ai agent eval generate 或使用優化器內建的預設值。
    候選項目上限 輸入最多要產生的候選者數量,例如 2。
    最佳化模型 從 支援的優化模型中選擇現有部署。

GitHub Copilot 會等待這些輸入後才開始優化。 產生的請求指示 Copilot 只使用 Microsoft Foundry Skill 的 Agent Optimizer 工作流程和 Azure Developer CLI 指令。 它沒有使用 Foundry 的 MCP 工具。 Copilot:

  • 檢查所選工作區中的代理程式碼。
  • 如果專案還沒有 AZD 環境,則會根據現有的 azure.yaml 和 .env 值初始化 AZD 環境。
  • 將代理程式串接以進行最佳化,並部署更新後的託管代理程式。
  • 在代理服務資料夾中建立 eval.yaml 。
  • 在你審核並核准建議的檔案變更和指令後,才開始優化。

Copilot 提交作業後,請返回 最佳化 索引標籤。該執行作業會顯示在 最佳化執行 下。 表格顯示其運行ID、狀態、候選人數量、基線分數、最佳分數及建立時間。

步驟三:比較並部署最佳候選人

  1. 當執行成功時,請在 「優化執行」中選擇它。
  2. 比較 基線 分數與 最佳 分數。 檢視每個候選 的分數細節 ,並選擇 「檢視變更 」以檢視其設定變更。
  3. 如果最佳候選者優於基準,請選取 部署最佳候選者 以更新目前的代理程式。 若要部署為新代理或更改部署設定,請選擇 自訂部署 。

備註

如果每位候選人的分數都低於基準線,就不要派遣候選人。 保留目前的代理程式,並在再次執行優化器前修訂資料集或優化設定。

Foundry Toolkit 中完成的優化執行截圖,比較基線與已產生的候選方案,並包含分數、配置變更及部署選項。

用 Microsoft Foundry 技能執行優化

可在任何支援 Microsoft Foundry 技能的編碼代理主機中使用此路徑,例如 Visual Studio Code 中的 GitHub Copilot、Copilot CLI 或 Claude Code。 技能會從azure.yaml解析 Agent 上下文脈絡,載入其 Agent 最佳化工具工作流程,並讓候選應用程式和部署受審查關卡控管。

步驟 1:開啟代理工作區

在你的 coding agent 主機裡打開一個空資料夾。 確認 microsoft-foundry 該技能是否可用。 如果無法使用該技能,請參閱在程式碼代理程式中使用 Microsoft Foundry 技能。

步驟 2:要求技能執行 Agent 最佳化工具

請將此提示提交給您的程式代理:

Use the Microsoft Foundry Skill to run the Agent Optimizer workflow for a
Python hosted agent. If this workspace doesn't contain an agent, initialize the
customer support optimization sample from this template:
https://github.com/microsoft-foundry/foundry-samples/blob/main/samples/python/hosted-agents/bring-your-own/responses/optimization-customer-support/azure.yaml
Resolve the AZD environment and hosted-agent service, verify that the agent is
optimizer-ready, and deploy and invoke the baseline. Generate and show me the
evaluation dataset, evaluators, and eval.yaml before running optimization.
Verify that the project has a supported optimization model deployment, then run
Agent Optimizer with two candidates. Stop after reporting the operation ID,
portal URL, candidate IDs, and scores. Don't apply or deploy a candidate yet.

當編碼代理無法從工作區解析這些值時,可能會要求你選擇訂閱、區域、Foundry 專案、代理服務、評估模型或優化模型。 在批准任何變更或指令前,務必檢視已產生的檔案與成本相關資源。

步驟三:申請並派遣核准候選人

在檢視優化結果後,請提交以下後續提示:

Recommend the best optimization candidate and explain the score improvement.
Summarize the candidate changes before applying anything. After I approve the
candidate, apply it locally, show the source diff, and stop again before
deployment. After I approve deployment, run azd deploy, invoke the agent with
"What is your return policy?", and rerun the evaluation to confirm the
improvement.

這個技能使用 azd ai agent optimize apply --candidate <candidate-id>,讓你可以在本機檢視最佳化後的設定。 它只有在你核准後才部署,然後呼叫並評估更新後的託管代理。

清理資源

如果你的工作流程是透過 AZD 專案建立資源,完成實驗後刪除已配置的資源:

azd down --force --purge

Tip

為什麼 --purge? Foundry 帳號預設使用軟刪除功能。 如果未使用 --purge,資源名稱會持續保留 48 小時,並且使用相同名稱重新佈建就會失敗。

Troubleshooting

Problem 原因 修復
azd ai agent optimize 找不到命令 延長線太舊了 執行 azd ext upgrade microsoft.foundry 以取得 0.1.40-preview 或更新版本。
optimization_model is required 在未設定模型的情況下以非互動模式運行 在指令中加入 --optimize-model gpt-5,或在 optimization_model: gpt-5 的 options: 下設定 eval.yaml。 在互動模式下,CLI 會提示選擇模型。
Python 腳本因缺少 KeyError: 'DATASET_NAME' 或其他變數而失敗 腳本沒有載入你的 .env 檔案,或者變數遺失 從與 .env相同的資料夾執行腳本,或在執行 python optimize_hosted_agent.py前匯出 shell 所需的數值。
Python 腳本因 ResourceNotFound: The project does not exist 而失敗 FOUNDRY_PROJECT_ENDPOINT 並不代表已有 Foundry 專案 從 Foundry 專案的 總覽 頁面複製專案端點,並在 FOUNDRY_PROJECT_ENDPOINT 中更新 .env。
Python 腳本因 Optimization model deployment '<name>' not found 而失敗 OPTIMIZATION_MODEL 不是你 Foundry 專案中已部署模型的名稱 請使用 Build>Deployments中的確切部署名稱,例如您專案中現有的 gpt-5 系列或 DeepSeek 部署。
工作請求因 evaluators is required and cannot be empty 而失敗 請求中缺少標 Foundry-Features 頭 如 C# 路徑中的 FoundryFeaturesPolicy 類別所示,加入 AgentsOptimization=V2Preview 標頭。
該作業失敗,出現 No optimizable element found for the hosted agent 請求中沒有包含可優化的目標 在 optimization_config 中至少提供一個目標項目,例如基準 system_prompt、工具定義或技能。
該作業失敗,出現 AllEvaluatorsFailedError 評估器設定錯誤,導致每一列都未得分 開啟錯誤訊息中的評估執行連結,並確認評估者有對你的代理程式回應進行評分。 從內建的評估器開始,例如 builtin.task_adherence。
託管代理的 優化 區塊不會出現 Foundry Toolkit 比 1.6.4 版本還舊,或者所選代理不是已部署的託管代理 更新 Foundry Toolkit,重新載入 Visual Studio Code,並從 Agents 標籤重新開啟已部署的代理程式。
在你選擇工作區後,GitHub Copilot Chat 不會開啟 GitHub Copilot 尚未安裝、帳號無法啟用,或是 agent 模式被停用 在 Visual Studio Code 中設定 GitHub Copilot,啟用代理模式,然後再次選擇新優化。
Foundry Toolkit 無法將最佳候選方案套用到目前的工作區 工作區中不包含名稱與已部署的託管代理程式相符的 azure.yaml 服務 打開包含所選代理程式碼及匹配 azure.ai.agent 服務的工作區,然後再試一次。
編碼代理找不到託管代理 錯誤的資料夾開啟了,或 azure.yaml 是沒有定義 azure.ai.agent 服務 打開包含 azure.yaml的 AZD 專案資料夾,然後請程式代理再次解析託管代理服務。
編碼 Agent 在套用或部署候選項目前會停止 代理優化器技能要求在變更原始碼與部署前進行審查 先檢視候選人分數和當地差異,然後明確核准申請或部署步驟。
優化分數為 0 或非常低 評估結果有許多發生錯誤的資料列 在結果中打開 評估 連結。 修正回應產生或評估器錯誤,然後再重跑。
azd provision 因配額錯誤而失敗 訂閱容量不足 試試其他地區或申請配額增加。

你學到了什麼

在這篇快速啟動指南中,您將:

  • 使用客戶支援範本部署了優化範例代理。
  • 我用 Azure Developer CLI、Python SDK、.NET SDK、Visual Studio Code 或 Microsoft Foundry 技能來運行代理優化器。
  • 派出獲勝候選人並確認改進。

下一步