Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This article shows you how to manage Hosted agents in Foundry Agent Service. After you deploy a Hosted agent, you can view its status, create new versions, configure traffic routing, monitor logs, and delete agents when they're no longer needed.
The platform manages the container lifecycle automatically. Compute is provisioned when a request arrives and deprovisioned after the idle timeout (15 minutes). This automatic compute scaling is separate from the agent's endpoint state. You don't start or stop the compute manually, but you can disable an agent's endpoint to take it offline and enable it again later.
Prerequisites
- Azure CLI version 2.80 or later, authenticated with
az login.
- Python SDK:
azure-ai-projects>=2.1.0andazure-identity.
Azure Developer CLI version 1.23.0 or later.
The Foundry agents extension:
azd ext install azure.ai.agents
Set up variables
The REST API examples in this article use az rest to call the Foundry Agent Service endpoints directly. Set the following variables before running the commands:
ACCOUNT_NAME="<your-foundry-account-name>"
PROJECT_NAME="<your-project-name>"
AGENT_NAME="<your-agent-name>"
BASE_URL="https://${ACCOUNT_NAME}.services.ai.azure.com/api/projects/${PROJECT_NAME}"
API_VERSION="v1"
RESOURCE="https://ai.azure.com"
Important
The --resource parameter is required for all az rest calls to Foundry Agent Service data-plane endpoints. Without it, az rest can't derive the correct Azure AD audience from the URL and authentication fails.
View agents and versions
Use the following commands to list agents and inspect version details.
List all agents in a project
az rest --method GET \
--url "${BASE_URL}/agents?api-version=${API_VERSION}" \
--resource "${RESOURCE}"
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
project = AIProjectClient(
endpoint=PROJECT_ENDPOINT,
credential=DefaultAzureCredential(),
)
for agent in project.agents.list():
print(agent.name)
azd ai agent show
Note
azd ai agent show reads the agent name and version from the azd service entry in your project configuration.
Get agent details
az rest --method GET \
--url "${BASE_URL}/agents/${AGENT_NAME}?api-version=${API_VERSION}" \
--resource "${RESOURCE}"
The response includes the agent's latest version, status, and definition.
agent = project.agents.get(agent_name="my-agent")
print(f"Name: {agent.name}")
print(f"Status: {agent.versions['latest']['status']}")
azd ai agent show
Get a specific version
az rest --method GET \
--url "${BASE_URL}/agents/${AGENT_NAME}/versions/1?api-version=${API_VERSION}" \
--resource "${RESOURCE}"
agent_version = project.agents.get_version(
agent_name="my-agent", agent_version="1"
)
print(f"Version: {agent_version.version}")
print(f"Status: {agent_version['status']}")
Version information is included in the output of azd ai agent show.
List all versions of an agent
az rest --method GET \
--url "${BASE_URL}/agents/${AGENT_NAME}/versions?api-version=${API_VERSION}" \
--resource "${RESOURCE}"
By default, the list excludes draft versions (preview). To include them, add the include_drafts=true query parameter:
az rest --method GET \
--url "${BASE_URL}/agents/${AGENT_NAME}/versions?api-version=${API_VERSION}&include_drafts=true" \
--resource "${RESOURCE}"
for version in project.agents.list_versions(agent_name="my-agent"):
print(f"Version: {version.version}, Status: {version['status']}")
Version information is included in the output of azd ai agent show.
Create a new version
Create a new agent version when you need to update the container image, change resource allocation, or modify environment variables.
az rest --method POST \
--url "${BASE_URL}/agents/${AGENT_NAME}/versions?api-version=${API_VERSION}" \
--resource "${RESOURCE}" \
--body '{
"definition": {
"kind": "hosted",
"image": "myregistry.azurecr.io/my-agent:v2",
"cpu": "1",
"memory": "2Gi",
"container_protocol_versions": [
{"protocol": "responses", "version": "1.0.0"}
]
}
}'
Replace responses with invocations if your agent uses the Invocations protocol, or include both to expose both protocols. For details on protocol selection, see Deploy a Hosted agent.
from azure.ai.projects.models import HostedAgentDefinition, ProtocolVersionRecord
agent = project.agents.create_version(
agent_name="my-agent",
definition=HostedAgentDefinition(
cpu="1",
memory="2Gi",
image="myregistry.azurecr.io/my-agent:v2",
container_protocol_versions=[
ProtocolVersionRecord(protocol="responses", version="1.0.0"),
],
),
)
print(f"Created version: {agent.version}")
Replace responses with invocations if your agent uses the Invocations protocol, or pass both to expose both protocols.
New versions are created automatically when you run azd deploy with updated code or configuration.
Create a draft version (preview)
Note
Draft versions are in preview. Preview features are provided without a service-level agreement and aren't recommended for production workloads. Behavior can change. Draft creation must be enabled for your subscription; until it's enabled, a request with draft set to true creates a normal release version instead.
A draft version is an experimental version that you can create and test without affecting how your agent serves production traffic. Drafts let you iterate on a new image, resource allocation, or configuration before you promote the change to a regular release version.
Draft versions differ from regular release versions in the following ways:
- Separate version identifier: A draft is assigned a
draft-{timestamp}version string (for example,draft-1719600000000) instead of an auto-incremented integer, so it never advances your release version numbering. - Excluded from default listings: Drafts don't appear when you list versions unless you pass
include_drafts=true. - Excluded from implicit routing: A draft is never resolved as the agent's latest version, so it doesn't receive traffic automatically.
- Can't be a traffic-routing target: You can't pin a traffic-routing rule to a draft version. Requests to route traffic to a draft are rejected.
To create a draft version, set draft to true in the request body:
az rest --method POST \
--url "${BASE_URL}/agents/${AGENT_NAME}/versions?api-version=${API_VERSION}" \
--resource "${RESOURCE}" \
--body '{
"draft": true,
"definition": {
"kind": "hosted",
"image": "myregistry.azurecr.io/my-agent:experimental",
"cpu": "1",
"memory": "2Gi",
"container_protocol_versions": [
{"protocol": "responses", "version": "1.0.0"}
]
}
}'
The response version field contains the assigned draft-{timestamp} identifier. Use that identifier to get or delete the draft, or to test it directly. When you're satisfied with the change, promote it by creating a new version with the same image and configuration but with draft omitted (or set to false). The new version receives a regular auto-incremented version number and becomes eligible for traffic routing.
Draft versions are currently available through the REST API only. Switch to the REST tab for an example, and call the same ${BASE_URL}/agents/${AGENT_NAME}/versions endpoint with "draft": true in the request body.
Draft versions are currently available through the REST API only. Switch to the REST tab for an example.
Version status values
After you create or update an agent version, poll the version endpoint until the status reaches active:
| Status | Description |
|---|---|
creating |
Infrastructure is being provisioned (typically 2-5 minutes). |
active |
Agent is ready to serve requests. |
failed |
Provisioning failed. Check the error field in the response for details. |
deleting |
Version is being cleaned up. |
deleted |
Version has been fully removed. |
Poll the version status after creation:
import time
def wait_for_version_active(project, agent_name, agent_version, max_attempts=60):
for attempt in range(max_attempts):
time.sleep(10)
version = project.agents.get_version(
agent_name=agent_name, agent_version=agent_version
)
status = version["status"]
print(f"Version status: {status} (attempt {attempt + 1})")
if status == "active":
return
if status == "failed":
raise RuntimeError(f"Version provisioning failed: {dict(version)}")
raise RuntimeError("Timed out waiting for version to become active")
Disable or enable an agent
Disable an agent to take its endpoint offline without deleting the agent or any of its versions. While disabled, the agent rejects requests, but its configuration and versions remain intact. Enable the agent again whenever you're ready to resume serving requests. Disabling is reversible, which makes it the preferred way to take an agent out of service temporarily.
Disable an agent
az rest --method POST \
--url "${BASE_URL}/agents/${AGENT_NAME}:disable?api-version=${API_VERSION}" \
--resource "${RESOURCE}"
Not supported as a standalone command. Use the REST API.
Not supported as a standalone command. Use the REST API.
Enable an agent
az rest --method POST \
--url "${BASE_URL}/agents/${AGENT_NAME}:enable?api-version=${API_VERSION}" \
--resource "${RESOURCE}"
Not supported as a standalone command. Use the REST API.
Not supported as a standalone command. Use the REST API.
Delete an agent
You can delete a specific version or an entire agent with all its versions.
Delete a specific version
az rest --method DELETE \
--url "${BASE_URL}/agents/${AGENT_NAME}/versions/1?api-version=${API_VERSION}" \
--resource "${RESOURCE}"
project.agents.delete_version(agent_name="my-agent", agent_version="1")
Not currently supported as a standalone command. Use the REST API or SDK.
Delete an agent and all versions
Warning
This action permanently deletes the agent and all its versions. Active sessions are terminated. This operation can't be undone.
az rest --method DELETE \
--url "${BASE_URL}/agents/${AGENT_NAME}?api-version=${API_VERSION}" \
--resource "${RESOURCE}"
project.agents.delete(agent_name="my-agent")
Not currently supported as a standalone command. Use the REST API or SDK.
View logs and monitor
Access container logs for debugging provisioning and runtime issues.
Stream logs from a specific agent session:
AGENT_VERSION="<version>"
SESSION_ID="<session-id>"
az rest --method GET \
--url "${BASE_URL}/agents/${AGENT_NAME}/versions/${AGENT_VERSION}/sessions/${SESSION_ID}:logstream?api-version=${API_VERSION}" \
--resource "${RESOURCE}" \
--headers "Foundry-Features=HostedAgents=V1Preview" "Accept=text/event-stream"
The logstream endpoint returns Server-Sent Events (SSE) with event: log frames. Each frame contains a JSON payload with timestamp, stream (stdout, stderr, or status), and message fields.
Timeouts:
- Maximum connection duration: 30 minutes
- Idle timeout: 2 minutes
Viewing container logs isn't currently supported through the Python SDK. Use the REST API or Azure Developer CLI.
Monitor a running agent with real-time status and log information:
azd ai agent monitor
This command reads the agent name and version from the azd service entry in your project configuration.
Example log output
2026-04-09T08:43:48.72656 Connecting to the container 'agent-container'...
2026-04-09T08:43:48.75451 Successfully connected to container: 'agent-container'
2026-04-09T08:43:59.0671054Z stdout F INFO: 127.0.0.1:42588 - "GET /readiness HTTP/1.1" 200 OK
Configure agent endpoint routing
Agent endpoints control how traffic is distributed across agent versions. Use version selectors to route a percentage of traffic to specific versions, enabling canary deployments or gradual rollouts.
Endpoint routing is configured by patching the agent object. Use PATCH /agents/{agent_name} with Content-Type: application/merge-patch+json:
az rest --method PATCH \
--url "${BASE_URL}/agents/${AGENT_NAME}?api-version=${API_VERSION}" \
--resource "${RESOURCE}" \
--headers "Content-Type=application/merge-patch+json" "Foundry-Features=AgentEndpoints=V1Preview" \
--body '{
"agent_endpoint": {
"version_selector": {
"version_selection_rules": [
{"agent_version": "1", "traffic_percentage": 100, "type": "FixedRatio"}
]
},
"protocols": ["responses"]
}
}'
Set protocols to ["invocations"] or ["responses", "invocations"] to match the protocols your agent exposes.
To split traffic between two versions (for example, 90/10 for a canary deployment):
az rest --method PATCH \
--url "${BASE_URL}/agents/${AGENT_NAME}?api-version=${API_VERSION}" \
--resource "${RESOURCE}" \
--headers "Content-Type=application/merge-patch+json" "Foundry-Features=AgentEndpoints=V1Preview" \
--body '{
"agent_endpoint": {
"version_selector": {
"version_selection_rules": [
{"agent_version": "1", "traffic_percentage": 90, "type": "FixedRatio"},
{"agent_version": "2", "traffic_percentage": 10, "type": "FixedRatio"}
]
},
"protocols": ["responses"]
}
}'
from azure.ai.projects.models import (
AgentEndpoint,
AgentEndpointProtocol,
FixedRatioVersionSelectionRule,
VersionSelector,
)
endpoint_config = AgentEndpoint(
version_selector=VersionSelector(
version_selection_rules=[
FixedRatioVersionSelectionRule(
agent_version="1", traffic_percentage=100
),
]
),
protocols=[AgentEndpointProtocol.RESPONSES],
)
project.beta.agents.patch_agent_details(
agent_name="my-agent",
agent_endpoint=endpoint_config,
)
Endpoint routing is configured automatically during azd deploy. To customize traffic distribution, use the REST API or SDK.
Retrieve the agent identity for role assignments
Each Hosted agent has an instance identity — a Microsoft Entra ID service principal that the agent uses at runtime to authenticate to downstream resources. To grant the agent access to services such as Azure Storage or Azure Cosmos DB, you need the identity's principal ID so you can create RBAC role assignments.
For more information on how agent identities work, see Agent identity concepts.
Extract the agent identity principal ID
Use the --query parameter to extract the instance_identity.principal_id directly from the agent details:
AGENT_IDENTITY=$(az rest --method GET \
--url "${BASE_URL}/agents/${AGENT_NAME}?api-version=${API_VERSION}" \
--resource "${RESOURCE}" \
--query "instance_identity.principal_id" \
--output tsv)
echo "Agent identity principal ID: ${AGENT_IDENTITY}"
agent = project.agents.get(agent_name="my-agent")
agent_identity = agent.instance_identity["principal_id"]
print(f"Agent identity principal ID: {agent_identity}")
Use the REST API or Python SDK to retrieve the agent identity principal ID.
Assign roles to the agent identity
After you have the principal ID, assign RBAC roles to the agent identity at the appropriate resource scope. Use --assignee-object-id with --assignee-principal-type ServicePrincipal to avoid Microsoft Graph lookup issues with agent identity service principals.
The agent identity works with any Azure resource that supports RBAC. The following examples show two common scenarios: granting access to the Foundry project and granting access to a storage account.
Assign a role on the Foundry project (for example, to allow the agent to use project resources):
az role assignment create \
--assignee-object-id "$AGENT_IDENTITY" \
--assignee-principal-type ServicePrincipal \
--role "Azure AI Developer" \
--scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/<account-name>/projects/<project-name>"
Assign a role on a storage account (for example, to allow the agent to read and write blobs):
az role assignment create \
--assignee-object-id "$AGENT_IDENTITY" \
--assignee-principal-type ServicePrincipal \
--role "Storage Blob Data Contributor" \
--scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Storage/storageAccounts/<storage-account>"
Role assignments are an Azure Resource Manager operation. Use the Azure CLI commands shown in the REST tab with the agent_identity value from the previous step, or use the Azure Authorization Management SDK to create role assignments programmatically.
Use the Azure CLI directly to create role assignments. Retrieve the agent identity principal ID by using the REST API or Python SDK, then run az role assignment create as shown in the REST tab.
Verify role assignments
List the roles assigned to the agent identity on the Foundry project:
az role assignment list \
--assignee "$AGENT_IDENTITY" \
--scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/<account-name>/projects/<project-name>" \
--output table
List the roles assigned to the agent identity on a storage account:
az role assignment list \
--assignee "$AGENT_IDENTITY" \
--scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Storage/storageAccounts/<storage-account>" \
--output table
Use the Azure CLI commands shown in the REST tab to verify role assignments.
Use the Azure CLI directly to verify role assignments as shown in the REST tab.