Skip to content

Repository files navigation

Foundry Agent Service chat basic reference implementation

This reference implementation illustrates an approach running a chat application and an AI orchestration layer in a single region. It uses Foundry Agent Service to host the agent, with Azure OpenAI foundation models providing the inference. This repository directly supports the Basic end-to-end chat reference architecture on Microsoft Learn.

The reference implementation illustrates a basic example of a chat application. For a reference implementation that implements more enterprise requirements, please see the Microsoft Foundry Agent Service baseline reference implementation. That implementation addresses many of the production readiness changes identified in this code.

Architecture

The implementation covers the following scenarios:

Setting up Microsoft Foundry to host agents

Microsoft Foundry hosts the Foundry Agent Service as a capability. Foundry Agent Service's REST APIs are exposed as an internet facing endpoint.

Diagram that shows a basic chat architecture.

Download a Visio file of this architecture.

Workflow

The following workflow corresponds to the previous diagram:

  1. An application user interacts with a web application that contains chat functionality. They issue an HTTPS request to the App Service default domain on azurewebsites.net. This domain automatically points to the App Service built-in public IP address. The Transport Layer Security connection is established from the client directly to App Service. Azure fully manages the certificate.
  2. The App Service feature called Easy Auth ensures that the user who accesses the website is authenticated via Microsoft Entra ID.
  3. The application code deployed to App Service handles the request and renders a chat UI for the application user. The chat UI code connects to APIs that are also hosted in that same App Service instance. The API code connects to the workload's hosted agent through the Microsoft Agent Framework with the Foundry provider, which calls the agent's OpenAI-compatible Responses endpoint on Foundry Agent Service under the hood.
  4. The hosted agent runs in its platform-managed session sandbox and uses its web search tool to fetch grounding data for the query. The grounding data is added to the prompt that's sent to the Azure OpenAI model in the next step.
  5. Foundry Agent Service connects to an Azure OpenAI model deployed in the same project and sends the prompt that includes the relevant grounding data and chat context.
  6. Application Insights logs information about the original request to App Service and the call agent interactions.

Deploying a hosted agent into Foundry Agent Service

A hosted agent is your own code packaged as a containerized application and deployed to Foundry Agent Service. Unlike prompt-based agents (defined entirely through configuration), hosted agents give you full control over the agent logic, tools, and orchestration while the platform handles scaling, session state, and lifecycle.

The agent in this reference implementation uses the Microsoft Agent Framework with the Foundry provider and exposes an OpenAI-compatible /responses endpoint via the Responses protocol (version 2.0.0). It includes a web search tool for grounding answers with real-time information.

Agents can be created and versioned via the Foundry SDK, the REST API, or Azure Developer CLI. The creation and invocation of agents are data plane operations. Each agent is a source-controlled, versioned asset that you can deploy in a coordinated way with the rest of your workload's code. In this deployment guide, you'll deploy the agent through the REST API to simulate a deployment pipeline which could have created the agent.

Invoking the hosted agent from .NET code hosted in an Azure Web App

A chat UI application is deployed into Azure App Service. The .NET code uses the Microsoft Agent Framework with the Foundry provider to connect to the workload's hosted agent. The endpoint for the agent is exposed over internet through Foundry.

Agent invocation at runtime uses a different API surface than agent lifecycle management. Hosted agents are invoked through their dedicated, agent-specific endpoint ({projectEndpoint}/agents/<agentName>/endpoint/protocols/openai), which the application derives from the project endpoint and the registered agent name. Multi-turn continuity is managed by Foundry Agent Service through hosted agent sessions: this reference implementation provisions a single shared session up front (pinned to a specific agent version), and all subsequent turns run in that same session so conversation state persists across turns. The active agent version is resolved by the endpoint's administrator-controlled version selector.

Deployment guide

Follow these instructions to deploy this example to your Azure subscription, try out what you've deployed, and learn how to clean up those resources.

Prerequisites

  • An Azure subscription

    • The subscription must have all of the resource providers used in this deployment registered.

      • Microsoft.CognitiveServices
      • Microsoft.Insights
      • Microsoft.ManagedIdentity
      • Microsoft.OperationalInsights
      • Microsoft.Storage
    • The subscription must have the following quota available in the region you choose.

      • App Service Plans: P1v3 (AZ), 3 instances
      • OpenAI model: GPT-4.1 model deployment with 50k tokens per minute (TPM) capacity
  • Your deployment user must have the following permissions at the subscription scope.

    • Ability to assign Azure roles on newly created resource groups and resources. (E.g. User Access Administrator or Owner)
    • Ability to purge deleted AI services resources. (E.g. Contributor or Cognitive Services Contributor)
  • The Azure CLI installed

    If you're executing this from WSL, be sure the Azure CLI is installed in WSL and is not using the version installed in Windows. which az should show /usr/bin/az.

  • Docker installed and running

1. 🚀 Deploy the infrastructure

The following steps are required to deploy the infrastructure from the command line.

  1. In your shell, clone this repo and navigate to the root directory of this repository.

    git clone https://github.com/Azure-Samples/microsoft-foundry-basic
    cd microsoft-foundry-basic
  2. Log in and set your target subscription.

    az login
    az account set --subscription xxxxx
  3. Set the deployment location to one with available quota in your subscription.

    This deployment has been tested in the following locations: australiaeast, eastus, eastus2, francecentral, japaneast, southcentralus, swedencentral, switzerlandnorth, or uksouth. You might be successful in other locations as well.

    LOCATION=eastus2
  4. Set the base name value that will be used as part of the Azure resource names for the resources deployed in this solution.

    BASE_NAME=<base resource name, between 6 and 8 lowercase characters, all DNS names will include this text, so it must be unique.>
  5. Create a resource group and deploy the infrastructure.

    There is an optional tracking ID on this deployment. To opt out of its use, add the following parameter to the deployment code below: -p telemetryOptOut true.

    RESOURCE_GROUP=rg-chat-basic-${BASE_NAME}
    az group create -l $LOCATION -n $RESOURCE_GROUP
    
    PRINCIPAL_ID=$(az ad signed-in-user show --query id -o tsv)
    
    # This takes about 10 minutes to run.
    az deployment group create -f ./infra-as-code/bicep/main.bicep \
      -g $RESOURCE_GROUP \
      -p baseName=${BASE_NAME} \
      -p yourPrincipalId=$PRINCIPAL_ID

2. Deploy a hosted agent in Foundry Agent Service

To test this scenario, you'll deploy a hosted agent, your own code running as a containerized application on Microsoft-managed infrastructure. The agent uses the Microsoft Agent Framework with the Foundry provider and exposes an OpenAI-compatible /responses endpoint. It includes hosted web search for grounding answers with real-time information.

The agent source code lives in src/agent/ in this repository. You'll package it as a ZIP, upload it to Foundry Agent Service via the REST API, and poll until the version is active.

2a. Package the agent source code

Build and publish the agent using the devcontainer image (no local .NET install needed), then create a flat ZIP of the published output:

docker run --rm -v "$PWD":/work -w /work \
  mcr.microsoft.com/devcontainers/dotnet:dev-10.0 \
  bash -c "apt-get update && apt-get install -y zip && cd src/agent && dotnet publish -c Release -o ./publish && cd ../.. && rm -rf /tmp/agent-zip && mkdir -p /tmp/agent-zip && cp -r src/agent/publish/* /tmp/agent-zip/ && cd /tmp/agent-zip && zip -r /work/src/agent.zip ."

This produces src/agent.zip containing the published .NET binaries at the ZIP root (no wrapper folder).

2b. Deploy the agent via the REST API

The following commands upload the agent source code to Foundry Agent Service and create a new version. Because the ZIP ships prebuilt dotnet publish output, dependency resolution is set to bundled.

FOUNDRY_NAME="aif${BASE_NAME}"
FOUNDRY_PROJECT_NAME="projchat"
FOUNDRY_BASE_URL="https://${FOUNDRY_NAME}.services.ai.azure.com/api/projects/${FOUNDRY_PROJECT_NAME}"
API_VERSION="2025-11-15-preview"
AGENT_NAME="baseline-chatbot-agent"

# Compute the SHA-256 of the ZIP
ZIP_SHA256=$(sha256sum src/agent.zip | awk '{print $1}')

BING_CONNECTION_ID="$(az cognitiveservices account show -n $FOUNDRY_NAME -g $RESOURCE_GROUP --query 'id' -o tsv)/projects/${FOUNDRY_PROJECT_NAME}/connections/bingaiagent"
sed "s|{{BING_CONNECTION_ID}}|${BING_CONNECTION_ID}|" agents/chat-with-bing.json > /tmp/agent-definition.json

# Upload the agent (multipart: metadata JSON + code ZIP, SHA-256 as header)
curl -sS -X POST \
  "${FOUNDRY_BASE_URL}/agents/${AGENT_NAME}/versions?api-version=${API_VERSION}" \
  -H "Authorization: Bearer $(az account get-access-token --resource https://ai.azure.com --query accessToken -o tsv)" \
  -H "x-ms-code-zip-sha256: ${ZIP_SHA256}" \
  -F "metadata=@/tmp/agent-definition.json;type=application/json" \
  -F "code=@src/agent.zip;type=application/zip"

2c. Poll until the agent version is active

while true; do
  STATUS=$(az rest --method GET \
    --url "${FOUNDRY_BASE_URL}/agents/${AGENT_NAME}/versions?api-version=${API_VERSION}" \
    --resource "https://ai.azure.com" \
    --query "data[0].status" -o tsv)
  echo "Status: ${STATUS}"
  if [ "$STATUS" = "active" ]; then
    break
  fi
  if [ "$STATUS" = "failed" ]; then
    echo "Deployment failed. Check the Foundry portal for logs."
    exit 1
  fi
  sleep 10
done
echo "Agent is active!"

3. Test the agent from the Foundry portal in the playground

Here you'll test your hosted agent by invoking it directly from the Foundry portal agent playground chat experience.

  1. Navigate to the Foundry project named projchat and open the Foundry portal by clicking the Go to Foundry portal button (or go directly to https://ai.azure.com).

  2. In the top-right corner, click Build to open the Agents blade.

  3. Select the agent named 'baseline-chatbot-agent'. It should show status Active.

  4. Enter a question to the agent that would require grounding data through recent internet content, such as a notable recent event or the weather today in your location.

  5. A grounded response to your question should appear on the UI.

4. Deploy the chat front-end web app

Workloads build chat functionality into an application. Those interfaces usually call the agent's endpoint in Foundry Agent Service. This implementation comes with such an interface. You'll deploy it to Azure App Service using the Azure CLI.

  1. Deploy the ChatUI web app

    First, package the ChatUI app using the devcontainer image (no local .NET install needed):

    docker run --rm -v "$PWD":/work -w /work \
      mcr.microsoft.com/devcontainers/dotnet:dev-10.0 \
      bash -c "apt-get update && apt-get install -y zip && cd src/chatui && dotnet publish -c Release -o ./publish && cd ../.. && rm -rf /tmp/chatui-zip && mkdir -p /tmp/chatui-zip && cp -r src/chatui/publish/* /tmp/chatui-zip/ && cd /tmp/chatui-zip && zip -r /work/src/chatui.zip ."

    Then deploy the package to Azure App Service:

    APPSERVICE_NAME=app-$BASE_NAME
    az webapp deploy -g $RESOURCE_GROUP -n $APPSERVICE_NAME --type zip --src-path src/chatui.zip

Sometimes the prior command will fail with a GatewayTimeout. If you receive that error, you're safe to simply execute the command again.

5. Try it out! Test the deployed application that calls into the Foundry Agent Service

After the deployment is complete, you can try the deployed application by navigating to the Web App's URL in a web browser.

You can also execute the following from your workstation. Unfortunately, this command does not reliably work from Azure Cloud Shell.

az webapp browse -g $RESOURCE_GROUP -n $APPSERVICE_NAME

Once you're there, ask your solution a question. Your question should involve something that would only be known with real-time web search context, such as recent weather or events.

🧹 Clean up resources

Most Azure resources deployed in the prior steps will incur ongoing charges unless removed. Additionally, a few of the resources deployed go into a soft delete status which will restrict the ability to redeploy another resource with the same name and might not release quota. It's best to purge any soft deleted resources once you are done exploring. Use the following commands to delete the deployed resources and resource group and to purge each of the resources with soft delete.

Note: This will completely delete any data you may have included in this example and it will be unrecoverable.

# These deletes and purges take about 30 minutes to run.
az group delete -n $RESOURCE_GROUP -y

# Purge the soft delete resources
az cognitiveservices account purge -g $RESOURCE_GROUP -l $LOCATION -n aif${BASE_NAME}

Contributions

Please see our Contributor guide.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

With ❤️ from Azure Patterns & Practices, Azure Architecture Center.

Used by

Contributors

Languages