Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
name: agent-framework-deploy
description: |
Deploy AI agents and workflows built with Microsoft Agent Framework SDK to Microsoft Foundry. Handles Dockerfile generation, ACR container build, hosted agent version creation, and container startup.
USE FOR: deploy agent to Foundry, publish agent to production, host agent on Azure, deploy workflow to Foundry, go live with agent, production deployment agent, deploy agent framework app, push agent to Azure AI Foundry, containerize agent, deploy multi-agent workflow.
DO NOT USE FOR: creating agents (use agent-framework), deploying models (use models/deploy-model), deploying web apps or functions (use azure-deploy), managing quotas (use quota).
---

### Deployment

#### Prerequisites

- Azure CLI installed and authenticated
- Azure AI Foundry Resource and Project created
- Agent must be wrapped as HTTP server using Agent-as-Server pattern. See [agent-as-server.md](references/agent-as-server.md).


#### Deployment Workflow

**Step 1: Verify locally**

Verify agent runs locally as HTTP server.

**Step 2: Gather Context**

Use az CLI to check the logged-in context first; ask user only for values that cannot be retrieved:
- `SUB_ID` - Azure Subscription ID
- `RG_NAME` - Resource Group name
- `FOUNDRY_RESOURCE` - Azure AI Foundry resource name
- `PROJECT_NAME` - Foundry project name
- `AGENT_NAME` - name for the hosted agent
- `ENTRYPOINT` - main file to run, e.g., `app.py` (if Dockerfile needs to be generated)


**Step 3: Prepare Dockerfile**

If no Dockerfile exists, generate one. Below is a Python example:

```dockerfile
FROM python:3.11-slim

WORKDIR /app

COPY ./ user_agent/

WORKDIR /app/user_agent

RUN if [ -f requirements.txt ]; then \
pip install -r requirements.txt; \
else \
echo "No requirements.txt found"; \
fi

EXPOSE 8088

CMD ["python", "<ENTRYPOINT_FILE>"]
```

Replace `<ENTRYPOINT_FILE>` with user's specified entry point.

> **Important:** If you decide to add `.env` to `.dockerignore`, confirm with the user which environment variables need to be included in the Docker container.

**Step 4: Configure ACR**

**If ACR exists**: Use existing ACR directly, skip role assignment.

**If no ACR exists**: Create new ACR with ABAC repository permissions mode, then assign:
- **Container Registry Repository Reader** to Foundry project managed identity
- **Container Registry Repository Writer** to current user

**Step 5: Build and Push Container Image**

Use ACR remote build (no local Docker required):

1. Generate a random alphanumeric image tag (12 characters)
2. Build and push the image:
```bash
IMAGE_NAME="$ACR_NAME.azurecr.io/$AGENT_NAME:$IMAGE_TAG"
az acr build --registry $ACR_NAME --image $IMAGE_NAME --subscription $SUB_ID --source-acr-auth-id "[caller]" <SOURCE_DIR>
```

**Important**: `--source-acr-auth-id "[caller]"` is required.

**Note**: `az acr build` streams logs from the remote build. If the CLI crashes while displaying logs (e.g., `UnicodeEncodeError` on Windows), the remote build continues running independently. Do
not assume failure. Check actual build status with:
```bash
az acr task show-run -r $ACR_NAME --run-id <run-id> --query status
```

**Step 6: Deploy Agent Version**

Ask the user for resource allocation preferences:
- `CPU` - CPU cores for the agent container (default: `0.5`)
- `MEMORY` - Memory allocation (default: `1Gi`)

Get access token and create agent version:

```bash
az account get-access-token --resource https://ai.azure.com --query accessToken --output tsv
```

```
POST https://$FOUNDRY_RESOURCE.services.ai.azure.com/api/projects/$PROJECT_NAME/agents/$AGENT_NAME/versions?api-version=2025-05-15-preview
```

**Body**:
```json
{
"definition": {
"kind": "hosted",
"container_protocol_versions": [
{ "protocol": "RESPONSES", "version": "v1" }
],
"cpu": "$CPU",
"memory": "$MEMORY",
"image": "$IMAGE_NAME",
"environment_variables": { "LOG_LEVEL": "debug" }
}
}
```

Record `$AGENT_VERSION` from response.

**Step 7: Start Agent Container**

```
POST https://$FOUNDRY_RESOURCE.services.ai.azure.com/api/projects/$PROJECT_NAME/agents/$AGENT_NAME/versions/$AGENT_VERSION/containers/default:start?api-version=2025-05-15-preview
```

**Body**:
```json
{
"min_replicas": 1,
"max_replicas": 1
}
```

**Step 8: Validate Deployment**

Test the agent:

```
POST https://$FOUNDRY_RESOURCE.services.ai.azure.com/api/projects/$PROJECT_NAME/openai/responses?api-version=2025-05-15-preview
```

**Body**:
```json
{
"agent": {
"type": "agent_reference",
"name": "$AGENT_NAME",
"version": "$AGENT_VERSION"
},
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "Hi, what can you do"
}
]
}
],
"stream": false
}
```

**Step 9: Post-Deployment**

- Create reusable deployment script in project root
- Save deployment summary to `.azure/foundry-deployment-summary.md`
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Agent as HTTP Server Best Practices

Converting an Agent-Framework-based Agent/Workflow/App to run as an HTTP server requires code changes to host the agent as a RESTful HTTP server.

(This doc applies to Python SDK only)

## Code Changes

### Run Workflow as Agent

Agent Framework provides a way to run a whole workflow as agent, via appending `.as_agent()` to the `WorkflowBuilder`, like:

```python
agent = (
WorkflowBuilder()
.add_edge(...)
...
.set_start_executor(...)
.build()
.as_agent() # here it is
)
```

Then, `azure.ai.agentserver.agentframework` package provides way to run above agent as an http server and receives user input direct from http request:

```text
# requirements.txt
# pin version to avoid breaking changes or compatibility issues
azure-ai-agentserver-agentframework==1.0.0b10
azure-ai-agentserver-core==1.0.0b10
```

```python
from azure.ai.agentserver.agentframework import from_agent_framework

# async method
await from_agent_framework(agent).run_async()

# or, sync method
from_agent_framework(agent).run()
```

Notes:
- User may or may not have `azure.ai.agentserver.agentframework` installed, if not, install it via or equivalent with other package managers:
`pip install azure-ai-agentserver-core==1.0.0b10 azure-ai-agentserver-agentframework==1.0.0b10`

- When changing the startup command line, make sure the http server mode is the default one (without any additional flag), which is better for further development (like local debugging) and deployment (like containerization and deploy to Microsoft Foundry).

- If loading env variables from `.env` file, like `load_dotenv()`, make sure set `override=True` to let the env variables work in deployed environment, like `load_dotenv(override=True)`

### Request/Response Requirements

To handle http request as user input, the workflow's starter executor should have handler to support `list[ChatMessage]` as input, like:

```python
@handler
async def some_handler(self, messages: list[ChatMessage], ctx: WorkflowContext[...]) -> ...:
```

Also, to let http response returns agent output, need to add `AgentRunUpdateEvent` to context, like:

```python
from agent_framework import AgentRunUpdateEvent, AgentRunResponseUpdate, TextContent, Role
...
response = await self.agent.run(messages)
for message in response.messages:
if message.role == Role.ASSISTANT:
await ctx.add_event(
AgentRunUpdateEvent(
self.id,
data=AgentRunResponseUpdate(
contents=[TextContent(text=f"Agent: {message.contents[-1].text}")],
role=Role.ASSISTANT,
response_id=str(uuid4()),
),
)
)
```

## Notes

- This step focuses on code changes to prepare an HTTP server-based agent, not actually containerizing or deploying, thus no need to generate extra files.
- Pin `agent-framework` to version `1.0.0b260107` to avoid breaking renaming changes like `AgentRunResponseUpdate`/`AgentResponseUpdate`, `create_agent`/`as_agent`, etc.
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`agent-framework-deploy - Trigger Tests Trigger Keywords Snapshot skill description triggers match snapshot 1`] = `
{
"description": "Deploy AI agents and workflows built with Microsoft Agent Framework SDK to Microsoft Foundry. Handles Dockerfile generation, ACR container build, hosted agent version creation, and container startup.
USE FOR: deploy agent to Foundry, publish agent to production, host agent on Azure, deploy workflow to Foundry, go live with agent, production deployment agent, deploy agent framework app, push agent to Azure AI Foundry, containerize agent, deploy multi-agent workflow.
DO NOT USE FOR: creating agents (use agent-framework), deploying models (use models/deploy-model), deploying web apps or functions (use azure-deploy), managing quotas (use quota).
",
"extractedKeywords": [
"agent",
"agent-framework",
"agents",
"apps",
"azure",
"azure-deploy",
"build",
"built",
"cli",
"container",
"containerize",
"creating",
"creation",
"deploy",
"deploy-model",
"deploying",
"deployment",
"dockerfile",
"foundry",
"framework",
"functions",
"generation",
"handles",
"host",
"hosted",
"identity",
"live",
"managing",
"microsoft",
"models",
"multi-agent",
"production",
"publish",
"push",
"quota",
"quotas",
"startup",
"version",
"with",
"workflow",
"workflows",
],
"name": "agent-framework-deploy",
}
`;

exports[`agent-framework-deploy - Trigger Tests Trigger Keywords Snapshot skill keywords match snapshot 1`] = `
[
"agent",
"agent-framework",
"agents",
"apps",
"azure",
"azure-deploy",
"build",
"built",
"cli",
"container",
"containerize",
"creating",
"creation",
"deploy",
"deploy-model",
"deploying",
"deployment",
"dockerfile",
"foundry",
"framework",
"functions",
"generation",
"handles",
"host",
"hosted",
"identity",
"live",
"managing",
"microsoft",
"models",
"multi-agent",
"production",
"publish",
"push",
"quota",
"quotas",
"startup",
"version",
"with",
"workflow",
"workflows",
]
`;
Loading
Loading