Distribuire e gestire il flusso di lavoro di Agent Framework migrato per Foundry (versione classica)

Avviso

Lo sviluppo delle funzionalità di Prompt Flow è terminato il 20 aprile 2026. La funzionalità verrà ritirata completamente il 20 aprile 2027. Alla data di ritiro, Prompt Flow passa alla modalità di sola lettura. I flussi esistenti continueranno a funzionare fino a tale data.

Azione consigliata: Eseguire la migrazione dei carichi di lavoro di Prompt Flow a Microsoft Agent Framework prima del 20 aprile 2027.

Questo articolo illustra le operazioni e i passaggi di transizione della migrazione da Prompt Flow a Microsoft Agent Framework: configurazione della tracciatura, distribuzione in App contenitore di Azure, aggiunta di una soglia di qualità CI/CD e trasferimento del traffico di produzione. Per i passaggi di controllo, ricompilazione e convalida, vedere Audit, ricompilare e convalidare il workflow di Prompt Flow in Microsoft Agent Framework. Per la panoramica della migrazione e il mapping dei concetti, vedere Migrate from Prompt Flow to Microsoft Agent Framework.For the migration overview and concept mapping, see Migrate from Prompt Flow to Microsoft Agent Framework.

Prerequisiti

  • Sono stati completati i passaggi di controllo, ricompilazione e convalida con un punteggio di parità medio ≥ 3,5 in parity_results.csv. Per informazioni dettagliate, vedere Verificare, ricompilare e convalidare il Workflow di Prompt Flow.

  • Istanza di Application Insights.

  • Un ambiente di Registro Azure Container e Container Apps.

  • Repository GitHub con segreti configurati per CI/CD.

  • Installare pacchetti aggiuntivi:

    pip install fastapi uvicorn azure-monitor-opentelemetry
    

Eseguire la migrazione delle operazioni

Questo passaggio sostituisce l'infrastruttura operativa gestita automaticamente da Prompt Flow.

Sottofase Sostituisce Dettagli
4a — Tracciamento Visualizzatore di esecuzione integrato di Prompt Flow OpenTelemetry + Application Insights
4b - Distribuzione Endpoint online gestito di Prompt Flow FastAPI + App contenitore di Azure
4c — CI/CD La valutazione manuale viene eseguita nell'interfaccia utente di Prompt Flow GitHub Actions soglia di qualità

Configurare il tracciamento

Foundry include l'integrazione nativa per il tracciamento con Agent Framework. Gli agenti compilati con Agent Framework generano automaticamente tracce quando la traccia è abilitata per il progetto Foundry. Per istruzioni dettagliate sulla configurazione, vedere Configurare la traccia per i framework dell'agente di intelligenza artificiale.

Per le distribuzioni autonome all'esterno di Foundry (ad esempio, App contenitore di Azure), usare configure_azure_monitor():

  1. Aggiungere il stringa di connessione di Application Insights al file .env:

    APPLICATIONINSIGHTS_CONNECTION_STRING=<your-connection-string>
    
  2. Chiamare configure_azure_monitor() prima di qualsiasi workflow.run() chiamata:

    import os
    
    from dotenv import load_dotenv
    from azure.monitor.opentelemetry import configure_azure_monitor
    
    load_dotenv()
    
    configure_azure_monitor(
        connection_string=os.environ[
            "APPLICATIONINSIGHTS_CONNECTION_STRING"
        ]
    )
    
    # All workflow.run() calls after this point emit traces.
    
  3. Visualizzare le tracce nel portale di Azure: passare alla risorsa di Application Insights e selezionare Transaction Search.

Importante

Chiamare configure_azure_monitor() all'avvio dell'applicazione, non all'interno di un gestore o dopo workflow.run(). Le tracce generate prima della chiamata vengono perse.

Eseguire la distribuzione in App contenitore di Azure

Eseguire il wrapping del flusso di lavoro di Agent Framework in un servizio FastAPI e distribuirlo come contenitore.

Creare il wrapper FastAPI

Creare un app.py file che espone un /ask endpoint:

"""Wraps an Agent Framework workflow in a FastAPI service."""

import os
from contextlib import asynccontextmanager

from dotenv import load_dotenv
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from azure.monitor.opentelemetry import configure_azure_monitor

load_dotenv()

# Import your rebuilt workflow
from your_workflow_module import workflow

# Configure tracing if connection string is present.
appinsights_conn = os.getenv("APPLICATIONINSIGHTS_CONNECTION_STRING")
if appinsights_conn:
    configure_azure_monitor(connection_string=appinsights_conn)


class QuestionRequest(BaseModel):
    question: str


class AnswerResponse(BaseModel):
    answer: str


@asynccontextmanager
async def lifespan(app: FastAPI):
    yield


app = FastAPI(title="Agent Framework Workflow Service", lifespan=lifespan)


@app.get("/health")
async def health():
    return {"status": "ok"}


@app.post("/ask", response_model=AnswerResponse)
async def ask(payload: QuestionRequest):
    if not payload.question.strip():
        raise HTTPException(
            status_code=400, detail="Question must not be empty."
        )

    result = await workflow.run(payload.question.strip())
    outputs = result.get_outputs()

    if not outputs:
        raise HTTPException(
            status_code=500,
            detail="Workflow produced no output.",
        )

    return AnswerResponse(answer=outputs[0])

Eseguire il test in locale con:

uvicorn app:app --reload

Creare il file dei requisiti

Creare un requirements.txt file con le dipendenze del progetto:

agent-framework>=1.0.0
agent-framework-foundry
fastapi
uvicorn
python-dotenv
azure-identity
azure-monitor-opentelemetry

Creare il Dockerfile

FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
EXPOSE 8000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]

Eseguire la distribuzione con interfaccia della riga di comando di Azure

Se non si dispone di un Registro Azure Container e di un ambiente Container Apps, createli.

az acr create --name <your-acr> --resource-group <your-rg> --sku Basic
az containerapp env create \
  --name <your-env> \
  --resource-group <your-rg> \
  --location <your-location>
  1. Compilare ed eseguire il push dell'immagine del contenitore:

    az acr build \
      --registry <your-acr> \
      --image maf-app:latest \
      .
    
  2. Creare l'applicazione contenitore:

    az containerapp create \
      --name maf-app \
      --resource-group <your-rg> \
      --environment <your-env> \
      --image <your-acr>.azurecr.io/maf-app:latest \
      --target-port 8000 \
      --ingress external \
      --registry-server <your-acr>.azurecr.io \
      --env-vars \
        FOUNDRY_PROJECT_ENDPOINT="https://<resource>.services.ai.azure.com" \
        FOUNDRY_MODEL="<deployment>"
    
  3. Verificare la distribuzione:

    APP_URL=$(az containerapp show \
      --name maf-app \
      --resource-group <your-rg> \
      --query "properties.configuration.ingress.fqdn" -o tsv)
    
    curl "https://${APP_URL}/health"
    

Suggerimento

Per le distribuzioni di produzione, usare un'identità gestita. DefaultAzureCredential è già configurato negli esempi di FoundryChatClient, quindi l'identità gestita funziona automaticamente negli ambienti ospitati Azure. Rimuovere tutte le variabili di ambiente della chiave API.

Aggiungere un controllo di qualità CI/CD

Creare un workflow di GitHub Actions che esegue la verifica della parità a ogni push e fallisce la pipeline se la somiglianza media scende al di sotto della soglia.

name: Evaluate on Deploy
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  evaluate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
          cache: pip

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Run parity evaluation
        run: python parity_check.py
        env:
          AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
          AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }}
          AZURE_OPENAI_CHAT_DEPLOYMENT_NAME: ${{ secrets.AZURE_OPENAI_CHAT_DEPLOYMENT_NAME }}
          FOUNDRY_PROJECT_ENDPOINT: ${{ secrets.FOUNDRY_PROJECT_ENDPOINT }}
          FOUNDRY_MODEL: ${{ secrets.FOUNDRY_MODEL }}

      - name: Enforce quality gate
        run: |
          python -c "
          import pandas as pd, sys
          df = pd.read_csv('parity_results.csv')
          score = df['similarity'].mean()
          print(f'Mean similarity: {score:.2f} / 5.0')
          sys.exit(0 if score >= 3.5 else 1)
          "

Passaggio

Passare il traffico di produzione all'Agent Framework e dismettere le risorse Prompt Flow.

Elenco di controllo pre-migrazione

Prima di procedere, verificare tutti gli elementi seguenti:

  • [ ] Punteggio medio di parità è 3,5 o superiore nel gruppo di test completo.
  • [ ] Agent Framework Container App (o distribuzione del servizio agente) è integro.
  • [ ] La traccia viene confermata in Application Insights o nel Portale Foundry.
  • [ ] Controllo qualità CI/CD viene passato al ramo principale.
  • [ ] La configurazione del gateway API o del client viene aggiornata in modo che punti all'endpoint di Agent Framework.

Eseguire il cutover

  1. Archivia il file YAML del flusso di prompt esistente.

    cp -r <your-flow-directory> ./archived-flow/
    
  2. Eliminare l'endpoint online gestito di Prompt Flow.

    az ml online-endpoint delete \
      --name <your-pf-endpoint> \
      --resource-group <your-rg> \
      --workspace-name <your-ws> \
      --yes
    
  3. Eliminare la connessione di Prompt Flow.

    az ml connection delete \
      --name <your-pf-connection> \
      --resource-group <your-rg> \
      --workspace-name <your-ws>
    

Avviso

Eseguire i comandi cutover solo dopo aver verificato che il traffico venga indirizzato all'endpoint di Agent Framework. Usare --dry-run i flag negli script per visualizzare in anteprima i comandi prima di eseguirli.

Dopo il passaggio

  • Monitorare Application Insights (o la visualizzazione di traccia del portale Foundry) per individuare i picchi di errore nelle prime 24 ore.
  • Mantenere il file YAML del flusso archiviato per almeno 30 giorni prima dell'eliminazione.

Risoluzione dei problemi

Nessuna traccia visualizzata in Application Insights

Assicurarsi di chiamare configure_azure_monitor() prima di qualsiasi workflow.run() chiamata. Verificare anche la stringa di connessione: portale di Azure > la risorsa di Application Insights >Overview>Connection String.

Per le distribuzioni ospitate in Foundry, verificare che il tracciamento sia abilitato per il tuo progetto nel portale Foundry.

uvicorn inizia ma /ask restituisce 500

La causa più comune è che app.py il file del flusso di lavoro errato è stato caricato o il file di destinazione non definisce un oggetto a livello workflow di modulo. Controllare la traccia di Application Insights per l'eccezione completa.

az containerapp create ha esito negativo con un errore di pull dell'immagine

Verifica:

  1. --registry-server corrisponde esattamente al server di accesso ACR (<name>.azurecr.io).
  2. L'identità gestita dell'applicazione container (o credenziali amministrative) ha il AcrPull ruolo sul registro.
  3. Il tag immagine inserito da az acr build corrisponde al tag in --image.

CredentialUnavailableError O ClientAuthenticationError

DefaultAzureCredential prova più origini di credenziali nell'ordine indicato. Se tutte le origini hanno esito negativo, il messaggio di errore elenca ogni credenziale tentata.

  1. Verificare che la sessione di interfaccia della riga di comando di Azure sia corrente: az account show.
  2. Verificare che l'account abbia accesso al progetto Foundry: az account set --subscription <your-subscription-id>.
  3. Per l'identità gestita in App Contenitore, assicurati che l'identità possieda il ruolo Utente di Servizi Cognitivi nella risorsa Foundry.

Il flusso di lavoro si blocca e non viene mai completato

La causa più comune è una definizione di arco circolare. Imposta un max_iterations limite per interrompere i cicli infiniti e controlla le tue chiamate add_edge() per rilevare cicli.

start_exec = YourStartExecutor(id="start")
workflow = WorkflowBuilder(
    max_iterations=10, start_executor=start_exec
).build()