Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build and deploy AI applications on Azure AI Foundry using Microsoft's model catalog and AI services
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
foundry-agent/deploy/deploy.md
1# Foundry Agent Deploy23Create and manage agent deployments in Azure AI Foundry. For hosted agents, this includes the full workflow from containerizing the project to verifying the deployed agent.45## Quick Reference67| Property | Value |8|----------|-------|9| Agent types | Prompt (LLM-based), Hosted |10| MCP server | `azure` |11| Key Foundry MCP tools | `agent_definition_schema_get`, `agent_update`, `agent_get` |12| CLI tools | `docker`, `az acr` (hosted agents only) |13| Container protocols | `a2a`, `responses`, `invocations`, `mcp` |14| Supported languages | .NET, Node.js, Python, Go, Java |1516## When to Use This Skill1718USE FOR: deploy agent to foundry, push agent to foundry, ship my agent, build and deploy container agent, deploy hosted agent, create hosted agent, deploy prompt agent, ACR build, container image for agent, docker build for foundry, redeploy agent, update agent deployment, clone agent, delete agent, azd deploy hosted agent, azd ai agent, azd up for agent, deploy agent with azd.1920> ⚠️ **DO NOT manually run** `azd up`, `azd deploy`, `az acr build`, `docker build`, or `agent_update` **without reading this skill first.** This skill orchestrates the full deployment pipeline: project scan → env var collection → Dockerfile generation → image build → agent creation → verification. Running CLI commands or calling MCP tools individually skips critical steps (env var confirmation, schema validation, RBAC setup, invocation verification).2122## MCP Tools2324| Tool | Description | Parameters |25|------|-------------|------------|26| `agent_definition_schema_get` | Get JSON schema for agent definitions | `projectEndpoint` (required), `schemaType` (`prompt`, `hosted`, `tools`, `all`) |27| `agent_update` | Create, update, or clone an agent | `projectEndpoint`, `agentName` (required); `agentDefinition` (JSON), `isCloneRequest`, `cloneTargetAgentName`, `modelName` |28| `agent_get` | List all agents or get a specific agent | `projectEndpoint` (required), `agentName` (optional) |29| `agent_delete` | Delete an agent and clean up hosted-agent runtime resources | `projectEndpoint`, `agentName` (required) |3031## Workflow: Hosted Agent Deployment323334### Step 1: Detect and Scan Project3536Get the project path from the selected agent root in the project context (see Common: Project Context Resolution). Detect the project type by checking for these files. Do **not** scan sibling agent folders.3738| Project Type | Detection Files |39|--------------|-----------------|40| .NET | `*.csproj`, `*.fsproj` |41| Node.js | `package.json` |42| Python | `requirements.txt`, `pyproject.toml`, `setup.py` |43| Go | `go.mod` |44| Java (Maven) | `pom.xml` |45| Java (Gradle) | `build.gradle` |4647Delegate an environment variable scan to a sub-agent. Provide the selected agent root path and project type. Search source files inside that folder only for these patterns:4849| Project Type | Patterns to Search |50|--------------|--------------------|51| .NET (`*.cs`) | `Environment.GetEnvironmentVariable("...")`, `configuration["..."]`, `configuration.GetValue<T>("...")` |52| Node.js (`*.js`, `*.ts`, `*.mjs`) | `process.env.VAR_NAME`, `process.env["..."]` |53| Python (`*.py`) | `os.environ["..."]`, `os.environ.get("...")`, `os.getenv("...")` |54| Go (`*.go`) | `os.Getenv("...")`, `os.LookupEnv("...")` |55| Java (`*.java`) | `System.getenv("...")`, `@Value("${...}")` |5657Classification: if followed by a throw/error → required; if followed by a fallback value → optional with default; otherwise → assume required, ask user.5859### Step 2: Collect and Confirm Environment Variables6061> ⚠️ **Warning:** Environment variables are included in the agent payload and are difficult to change after deployment.6263Use azd environment values from the project context to pre-fill discovered variables. Merge with any user-provided values. Present all variables to the user for confirmation with variable name, value, and source (`azd`, `project default`, or `user`). Mask sensitive values.6465Loop until the user confirms or cancels:66- `yes` → Proceed67- `VAR_NAME=new_value` → Update the value, show updated table, ask again68- `cancel` → Abort deployment6970### Step 3: Generate Dockerfile and Build Image7172Delegate Dockerfile creation to a sub-agent. Guidelines:73- Use official base image for the detected language and runtime version74- Use multi-stage builds for compiled languages75- Use Alpine or slim variants for smaller images76- Always target `linux/amd64` platform77- Expose the correct port (usually 8088)7879> 💡 **Tip:** Reference [Hosted Agents Foundry Samples](https://github.com/microsoft-foundry/foundry-samples/tree/main/samples/python/hosted-agents) for containerized agent examples.8081Also generate `docker-compose.yml` and `.env` files for local development.8283**IMPORTANT**: You MUST always generate image tag as current timestamp (e.g., `myagent:202401011230`) to ensure uniqueness and avoid conflicts with existing images in ACR. DO NOT use static tags like `latest` or `v1`.8485Collect ACR details from project context.8687- If an ACR already exists, use it, then verify that the Foundry project managed identity has pull permissions (for example, `Container Registry Repository Reader` or equivalent) on the target repository/registry. If the role assignment is missing, add it.88- If no ACR exists, create a new one with ABAC repository permissions mode, and assign `Container Registry Repository Reader` to the Foundry project managed identity. Foundry hosted agents use ABAC mode that requires repository-scoped roles, not the registry-level `AcrPull` role.8990Let the user choose the build method:9192**Cloud Build (ACR Tasks) (Recommended)** — no local Docker required:93```bash94az acr build --registry <acr-name> --image <repository>:<tag> --platform linux/amd64 --source-acr-auth-id "[caller]" --file Dockerfile .95```9697> ⚠️ **Mandatory:** The `--source-acr-auth-id "[caller]"` parameter is required. Do NOT omit it — without this flag the build will fail due to missing authentication context.9899**Local Docker Build:**100```bash101docker build --platform linux/amd64 -t <image>:<tag> -f Dockerfile .102az acr login --name <acr-name>103docker tag <image>:<tag> <acr-name>.azurecr.io/<repository>:<tag>104docker push <acr-name>.azurecr.io/<repository>:<tag>105```106107> 💡 **Tip:** Prefer Cloud Build if Docker is not available locally. On Windows with WSL, prefix Docker commands with `wsl -e` if `docker info` fails but `wsl -e docker info` succeeds.108109### Step 4: Collect Agent Configuration110111Use the project endpoint and ACR name from the project context. Ask the user only for values not already resolved:112- **Agent name** — Unique name for the agent113- **Model deployment** — Model deployment name (e.g., `gpt-4o`)114115### Step 5: Get Agent Definition Schema116117Use `agent_definition_schema_get` with `schemaType: hosted` to retrieve the current schema and validate required fields.118119### Step 6: Create the Agent120121Use `agent_update` with the agent definition:122123> ⚠️ **Protocol version source of truth:** Do NOT copy the protocol version from `agent_definition_schema_get` examples. Use the protocol version declared by the agent source itself (for example, `agent.yaml` or `agent.manifest.yaml`).124125```json126{127"command": "agent_update",128"intent": "Update a hosted agent with a new docker image",129"parameters": {130"projectEndpoint": "<project-endpoint>",131"agentName": "<agent-name>",132"agentDefinition": {133"kind": "hosted",134"image": "<acr-name>.azurecr.io/<repository>:<tag>",135"cpu": "<cpu-cores>",136"memory": "<memory>",137"container_protocol_versions": [138{ "protocol": "<protocol>", "version": "<version>" }139],140"environment_variables": { "<var>": "<value>" }141}142}143}144```145146Capture the per-agent identity from the agent creation response, then retrieve the project-level agent identity from the project resource after creation. You will need both identities to assign the minimum RBAC required for invocation before running invoke tests.147148### Step 7: Test the Agent149150For a newly deployed hosted agent, before invocation testing, first check whether the per-agent identity and project-level agent identity already have the minimum RBAC required for invocation.151152Required role assignment:153- `Azure AI User`154155Required scope: the Cognitive Services account, not the project.156157Check existing assignments before creating any new assignment. If the required role assignment is missing for either identity, assign it before invocation testing.158159If the current user account does not have permission to create a missing role assignment, stop the deployment workflow here. Explain to the user that hosted-agent invocation requires `Azure AI User` on the per-agent identity and project-level agent identity at the Cognitive Services account scope, and the deployment cannot be treated as complete until someone with RBAC assignment permission grants the missing role.160161After this RBAC check is complete, read and follow the [invoke skill](../invoke/invoke.md) to send a test message and verify the agent responds correctly. DO NOT SKIP reading the invoke skill — it contains important information about required hosted-agent session handling.162163If invocation testing still fails after this RBAC check, immediately read and follow the [troubleshoot skill](../troubleshoot/troubleshoot.md). Do not treat the deployment as fully successful until invocation succeeds.164165> ⚠️ **DO NOT stop here.** Continue to Step 8 (Auto-Create Evaluators & Dataset). This step is mandatory after every successful deployment.166167### Step 8: Auto-Create Evaluators & Dataset168169Follow [After Deployment — Auto-Create Evaluators & Dataset](#after-deployment--auto-create-evaluators--dataset) below.170171## Workflow: Prompt Agent Deployment172173### Step 1: Collect Agent Configuration174175Use the project endpoint from the project context (see Common: Project Context Resolution). Ask the user only for values not already resolved:176- **Agent name** — Unique name for the agent177- **Model deployment** — Model deployment name (e.g., `gpt-4o`)178- **Instructions** — System prompt (optional)179- **Temperature** — Response randomness 0-2 (optional, default varies by model)180- **Tools** — Tool configurations (optional)181182### Step 2: Get Agent Definition Schema183184Use `agent_definition_schema_get` with `schemaType: prompt` to retrieve the current schema.185186### Step 3: Create the Agent187188Use `agent_update` with the agent definition:189190```json191{192"kind": "prompt",193"model": "<model-deployment>",194"instructions": "<system-prompt>",195"temperature": 0.7196}197```198199### Step 4: Test the Agent200201Read and follow the [invoke skill](../invoke/invoke.md) to send a test message and verify the agent responds correctly.202203> ⚠️ **DO NOT stop here.** Continue to Step 5 (Auto-Create Evaluators & Dataset). This step is mandatory after every successful deployment.204205### Step 5: Auto-Create Evaluators & Dataset206207Follow [After Deployment — Auto-Create Evaluators & Dataset](#after-deployment--auto-create-evaluators--dataset) below.208209## Display Agent Information210Once deployment is done for either hosted or prompt agent, display the agent's details in a nicely formatted table.211212Below the table you MUST also display a Playground link for direct access to the agent in Azure AI Foundry:213214[Open in Playground](https://ai.azure.com/nextgen/r/{encodedSubId},{resourceGroup},,{accountName},{projectName}/build/agents/{agentName}/build?version={agentVersion})215216To calculate the encodedSubId, you need to take subscription id and convert it into its 16-byte GUID, then encode it as URL-safe base64 without padding (= characters trimmed). You can use the following Python code to do this conversion:217218```219python -c "import base64,uuid;print(base64.urlsafe_b64encode(uuid.UUID('<SUBSCRIPTION_ID>').bytes).rstrip(b'=').decode())"220```221222## Document Deployment Context223224After a successful deployment, persist the deployment context to the selected metadata file under `<agent-root>/.foundry/` so future conversations (evaluation, trace analysis, monitoring) can reuse it automatically. Local/dev flows should default to `agent-metadata.yaml`; prod or CI-targeted flows can point at `agent-metadata.prod.yaml` or another explicit sidecar file. See [Agent Metadata Contract](../../references/agent-metadata-contract.md) for the canonical schema.225226| Metadata Field | Purpose | Example |227|----------------|---------|---------|228| `environments.<env>.projectEndpoint` | Foundry project endpoint | `https://<account>.services.ai.azure.com/api/projects/<project>` |229| `environments.<env>.agentName` | Deployed agent name | `my-support-agent` |230| `environments.<env>.azureContainerRegistry` | ACR resource (hosted agents) | `myregistry.azurecr.io` |231| `environments.<env>.evaluationSuites[]` | Evaluation bundles for datasets, evaluators, tags, and thresholds | `smoke-core`, `trace-regression-suite` |232| `environments.<env>.evaluationSuites[].datasetUri` | Remote Foundry dataset URI for shared eval workflows | `azureml://datastores/.../paths/...` |233234If the selected metadata file is a preferred single-environment file, update only that one environment block and leave sibling metadata files untouched. If the selected metadata file is a legacy multi-environment file, merge the selected environment instead of overwriting other environments or cached evaluation suites without confirmation. If the selected environment still uses older `testSuites[]` or legacy `testCases[]`, rewrite that environment to `evaluationSuites[]` when you persist deployment metadata.235236## After Deployment — Auto-Create Evaluators & Dataset237238> ⚠️ **This step is automatic.** After a successful deployment, immediately prepare the selected `.foundry` environment for evaluation without waiting for the user to request it. This matches the eval-driven optimization loop.239240### 1. Read Agent Instructions241242Use **`agent_get`** (or local `agent.yaml`) to understand the agent's purpose and capabilities.243244### 2. Reuse or Refresh Local Cache245246Inspect the selected agent root before generating anything new:247248- Reuse `.foundry/evaluators/` and `.foundry/datasets/` when they already contain the right assets for the selected environment.249- Ask before refreshing cached files or replacing thresholds.250- If cache is missing or stale, regenerate the dataset/evaluators and update metadata for the active environment only.251252### 2.5 Discover Existing Evaluators253254Use **`evaluator_catalog_get`** with the selected environment's project endpoint to list all evaluators already registered in the project. Display them to the user grouped by type (`custom` vs `built-in`) with name, category, and version. During Phase 1, catalog any promising custom evaluators for later reuse, but keep the first run on the built-in baseline. Only propose creating a new evaluator in Phase 2 when no existing evaluator covers the required dimension.255256### 3. Select Default Evaluators257258Follow the [observe skill's Two-Phase Evaluator Strategy](../observe/observe.md). Phase 1 is built-in only, so do not create a new custom evaluator during the initial setup pass.259260Start with <=5 built-in evaluators for the initial eval run so the first pass stays fast:261262| Category | Evaluators |263|----------|-----------|264| **Quality (built-in)** | relevance, task_adherence, intent_resolution |265| **Safety (built-in)** | indirect_attack |266| **Tool use (built-in, conditional)** | tool_call_accuracy (use when the agent calls tools; some catalogs label it as `builtin.tool_call_accuracy`) |267268After analyzing initial results, suggest additional evaluators (custom or built-in) targeted at specific failure patterns instead of front-loading a larger default set.269270If Phase 2 is needed, call `evaluator_catalog_get` again to reuse an existing custom evaluator first. Only create a new custom evaluator when the catalog still lacks the required signal, and prefer prompt templates that consume `expected_behavior` for per-query behavioral scoring. When creating custom evaluator `promptText`, preserve the rubric but remove or rewrite user-provided output-format instructions that conflict with the runtime-enforced `result`/`reason` JSON contract (for example, `score`/`reasoning` schemas or duplicate `OUTPUT FORMAT` blocks).271272### 4. Identify LLM-Judge Deployment273274Use **`model_deployment_get`** to list the selected project's actual model deployments, then choose one that supports chat completions for quality evaluators. Do **not** assume `gpt-4o` exists in the project. If no deployment supports chat completions, stop the auto-setup flow and tell the user quality evaluators cannot run until a compatible judge deployment is available.275276### 5. Generate Seed Dataset277278> ⚠️ **MANDATORY: Read the full generation workflow before proceeding.**279280Read and follow [Generate Seed Evaluation Dataset](../eval-datasets/references/generate-seed-dataset.md). That reference contains:281- The required JSONL row schema (`query` + `expected_behavior` are both mandatory)282- Coverage distribution targets and generation rules283- Generation requirements that keep rows valid by construction (valid JSON, required fields, coverage targets, and minimum row count)284- Foundry registration steps (blob upload + `evaluation_dataset_create`)285- Metadata updates for the selected metadata file and `manifest.json`286287Do NOT skip the `expected_behavior` field. The generation reference handles the complete flow from query generation through Foundry registration.288289The local filename must start with the selected environment's Foundry agent name (`agentName` in the selected metadata file) before adding stage, environment, or version suffixes.290291Use [Generate Seed Evaluation Dataset](../eval-datasets/references/generate-seed-dataset.md) as the single source of truth for seed dataset registration. It covers `project_connection_list` with `AzureStorageAccount`, key-based versus AAD upload, `evaluation_dataset_create` with `connectionName`, and saving the returned `datasetUri`.292293### 6. Persist Artifacts and Evaluation Suites294295Save evaluator definitions, local datasets, and evaluation outputs under `.foundry/`, then register or update evaluation suites in the selected metadata file for the selected environment:296297```text298.foundry/299agent-metadata.yaml300agent-metadata.prod.yaml301evaluators/302<name>.yaml303datasets/304<agent-name>-eval-seed-v1.jsonl305results/306```307308Each evaluation suite should bundle one dataset with the evaluator list, thresholds, and a `tags` map (for example, `tier: smoke`, `purpose: baseline`, `stage: seed`). Persist the local `datasetFile` and remote `datasetUri` together, and seed exactly one smoke suite after deployment. If the selected environment still uses older `testSuites[]` or legacy `testCases[]`, replace that list with `evaluationSuites[]` in the rewritten metadata and map legacy `priority` to `tags.tier` only when `tags.tier` is missing.309310### 7. Prompt User311312*"Your agent is deployed and running in the selected environment. The `.foundry` cache now contains evaluators, a local seed dataset, the Foundry dataset registration metadata, and evaluation-suite metadata. Would you like to run an evaluation to identify optimization opportunities?"*313314- **Yes** → follow the [observe skill](../observe/observe.md) starting at **Step 2 (Evaluate)** — cache and metadata are already prepared.315- **No** → stop. The user can return later.316- **Production trace analysis** → follow the [trace skill](../trace/trace.md) to search conversations, diagnose failures, and analyze latency using App Insights.317318## Agent Definition Schemas319320### Prompt Agent321322| Property | Type | Required | Description |323|----------|------|----------|-------------|324| `kind` | string | ✅ | Must be `"prompt"` |325| `model` | string | ✅ | Model deployment name (e.g., `gpt-4o`) |326| `instructions` | string | | System message for the model |327| `temperature` | number | | Response randomness (0-2) |328| `top_p` | number | | Nucleus sampling (0-1) |329| `tools` | array | | Tools the model may call |330| `tool_choice` | string/object | | Tool selection strategy |331| `rai_config` | object | | Responsible AI configuration |332333### Hosted Agent334335| Property | Type | Required | Description |336|----------|------|----------|-------------|337| `kind` | string | ✅ | Must be `"hosted"` |338| `image` | string | ✅ | Container image URL |339| `cpu` | string | ✅ | CPU allocation (e.g., `"0.5"`, `"1"`, `"2"`) |340| `memory` | string | ✅ | Memory allocation (e.g., `"1Gi"`, `"2Gi"`) |341| `container_protocol_versions` | array | ✅ | Protocol and version pairs |342| `environment_variables` | object | | Key-value pairs for container env vars |343| `tools` | array | | Tool configurations |344| `rai_config` | object | | Responsible AI configuration |345346### Container Protocols347348| Protocol | Description |349|----------|-------------|350| `a2a` | Agent-to-Agent protocol |351| `responses` | OpenAI Responses API |352| `invocations` | Invocation payload protocol for arbitrary request bodies and custom SSE behavior |353| `mcp` | Model Context Protocol |354355## Agent Management Operations356357### Clone an Agent358359Use `agent_update` with `isCloneRequest: true` and `cloneTargetAgentName` to create a copy. For prompt agents, optionally override the model with `modelName`.360361### Delete an Agent362363Use `agent_delete` — automatically cleans up hosted-agent runtime resources.364365### List Agents366367Use `agent_get` without `agentName` to list all agents, or with `agentName` to get a specific agent's details.368369## Error Handling370371| Error | Cause | Resolution |372|-------|-------|------------|373| Project type not detected | No known project files found | Ask user to specify project type manually |374| Docker not running | Docker Desktop not started or not installed | Start Docker Desktop, or use Cloud Build (ACR Tasks) instead |375| ACR login failed | Not authenticated to Azure | Run `az login` first, then `az acr login --name <acr-name>` |376| Build/push failed | Dockerfile errors or insufficient ACR permissions | Check Dockerfile syntax, verify Contributor or AcrPush role on registry |377| ACR build log crash | `UnicodeEncodeError` when `az acr build` streams remote logs | The remote build continues independently — do not assume failure. Get the `<run-id>` from the earlier `az acr build` output and check status with `az acr task show-run -r <acr-name> --run-id <run-id> --query status`. |378| Agent creation failed | Invalid definition or missing required fields | Use `agent_definition_schema_get` to verify schema, check all required fields |379| Hosted agent not running after creation | Provisioning failed or the image is not usable | Verify ACR image path, check cpu/memory values, confirm ACR permissions, then inspect hosted-agent logs with the troubleshoot skill |380| Role assignment failed | The required invocation RBAC was not granted | Stop the deployment workflow and explain that hosted-agent invocation requires `Azure AI User` on the per-agent identity and project-level agent identity at the Cognitive Services account scope |381| Invocation test failed after deployment | Missing or incorrect invocation RBAC for the per-agent identity or project-level agent identity | Check whether `Azure AI User` is assigned to the per-agent identity and project-level agent identity at the Cognitive Services account scope; assign missing role assignments, then retry invocation |382| Permission denied | Insufficient Foundry project permissions | Verify Azure AI Owner or Contributor role on the project |383| Schema fetch failed | Invalid project endpoint | Verify project endpoint URL format: `https://<resource>.services.ai.azure.com/api/projects/<project>` |384385## Non-Interactive / YOLO Mode386387When running in non-interactive mode (e.g., `nonInteractive: true` or YOLO mode), the skill skips user confirmation prompts and uses sensible defaults:388389- **Environment variables** — Uses values resolved from `azd env get-values` and project defaults without prompting for confirmation390- **Agent name** — Must be provided in the initial user message or derived sensibly from the project context; if missing, the skill fails with an error instead of prompting391- **Hosted agent verification** — Automatically continues into RBAC and invocation verification without additional prompts once deployment succeeds392393> ⚠️ **Warning:** In non-interactive mode, ensure all required values (project endpoint, agent name, ACR image) are provided upfront in the user message or available via `azd env get-values`. Missing values will cause the deployment to fail rather than prompt.394395## Additional Resources396397- [Foundry Hosted Agents](https://learn.microsoft.com/azure/ai-foundry/agents/concepts/hosted-agents?view=foundry)398- [Foundry Agent Runtime Components](https://learn.microsoft.com/azure/ai-foundry/agents/concepts/runtime-components?view=foundry)399- [Foundry Samples](https://github.com/microsoft-foundry/foundry-samples/)400