MAF

10. Host Agent

Host OpsAgent so users and other agents can reach it over HTTP โ€” deploying the same agent built through Modules 4โ€“9 into a production-ready serverless endpoint using the Azure Functions (Durable) hosting option.

Module Goals

GoalCovered by
Understand the four hosting optionsHosting Options table
Install the Azure Functions hosting packageStep 1
Start the Azurite local storage emulatorStep 2
Configure local.settings.jsonStep 3
Run the Functions hostStep 4
Invoke the hosted endpoint with curlStep 5

In This Module

Once an agent works in a REPL or chat UI, the next step is to make it available over HTTP so other systems, agents, or clients can call it. Microsoft Agent Framework provides four hosting options:

OptionDescriptionBest For
A2A ProtocolExpose agents via the Agent-to-Agent protocolMulti-agent systems
OpenAI-Compatible EndpointsExpose agents via Chat Completions or Responses APIsOpenAI-compatible clients
Azure Functions (Durable)Run agents as durable Azure FunctionsServerless, long-running tasks
AG-UI ProtocolBuild web-based AI agent applicationsWeb frontends

This module uses Azure Functions (Durable) because it is the most portable serverless option: OpsAgent and its full feature set (Tools, MCP, Multi-Turn) run inside a standard HTTP-triggered function with durable state management that survives restarts and scales to zero when idle.

Source: Microsoft Learn โ€” Host Your Agent

Folder Structure

lab/
โ””โ”€โ”€ app/
    โ””โ”€โ”€ hosting/
        โ”œโ”€โ”€ function_app.py                  # OpsAgent + AgentFunctionApp
        โ”œโ”€โ”€ host.json                        # Azure Functions host config
        โ”œโ”€โ”€ local.settings.json.template     # Settings template (git tracked)
        โ”œโ”€โ”€ local.settings.json              # Actual settings (gitignored)
        โ”œโ”€โ”€ requirements.txt                 # Python deps for Azure deployment
        โ””โ”€โ”€ README.md

Prerequisites

  • Completed Modules 1 โ€“ 9.
  • The lab/.env file contains GITHUB_TOKEN and GITHUB_MODEL.
  • The lab virtual environment is active (.venv).
  • Azure Functions Core Tools 4.x installed (func on PATH).
  • Azurite โ€” local Azure Storage emulator for durable state.

Step 1 โ€” Install the Azure Functions Hosting Package

The agent-framework-azurefunctions package adds AgentFunctionApp and all durable task infrastructure needed to host agents.

cd lab
uv add agent-framework-azurefunctions --prerelease=allow

[!NOTE] This is a pre-release add-on to agent-framework, separate from the core package already in pyproject.toml.

Step 2 โ€” Start Azurite

The durable extension uses Azure Storage for state persistence. Azurite emulates this locally so no real Azure subscription is needed.

# Install once
npm install -g azurite

# Start (leave this terminal open)
azurite --silent --location /tmp/azurite

Azurite listens on http://localhost:10000 (Blob), 10001 (Queue), and 10002 (Table). The local.settings.json uses "AzureWebJobsStorage": "UseDevelopmentStorage=true" to connect to it automatically.

Step 3 โ€” Configure local.settings.json

Inside lab/app/hosting/, copy the template and fill in your credentials:

cd lab/app/hosting
cp local.settings.json.template local.settings.json

Edit local.settings.json and replace <your-github-pat> with your token. This file is gitignored so secrets stay local.

local.settings.json reference:

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "DURABLE_TASK_SCHEDULER_CONNECTION_STRING": "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None",
    "TASKHUB_NAME": "default",
    "GITHUB_TOKEN": "<your-github-pat>",
    "GITHUB_MODEL": "gpt-4o-mini"
  }
}

Step 4 โ€” Start the Functions Host

Open a new terminal (Azurite must still be running):

cd lab/app/hosting
func start

You will see:

Functions:

    health_check: [GET] http://localhost:7071/api/health

    http-OpsAgent: [POST] http://localhost:7071/api/agents/OpsAgent/run

    dafx-OpsAgent: entityTrigger

Step 5 โ€” Invoke the Hosted Endpoint

Single turn

curl -i -X POST http://localhost:7071/api/agents/OpsAgent/run \
  -H "Content-Type: text/plain" \
  -d "Check the health of App Service in East US."

Expected response:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
x-ms-thread-id: <guid>

Azure App Service in East US: Healthy. Last checked: 2026-05-22 10:00 UTC

Multi-turn conversation

Pass the x-ms-thread-id from the first response as ?thread_id= to continue the same conversation:

# First turn
curl -i -X POST http://localhost:7071/api/agents/OpsAgent/run \
  -H "Content-Type: text/plain" \
  -d "My name is Alex. What can you help me with?"

# Second turn โ€” replace <id> with the x-ms-thread-id value
curl -X POST "http://localhost:7071/api/agents/OpsAgent/run?thread_id=<id>" \
  -H "Content-Type: text/plain" \
  -d "What tools do you have available?"

Async mode (HTTP 202 โ€” fire and forget)

curl -i -X POST http://localhost:7071/api/agents/OpsAgent/run \
  -H "Content-Type: text/plain" \
  -H "x-ms-wait-for-response: false" \
  -d "Get the AKS deployment checklist."

Expected Outcomes

After completing this module you will have:

  • โœ… A self-contained hosting example under lab/app/hosting/
  • โœ… A locally running HTTP endpoint at POST /api/agents/OpsAgent/run
  • โœ… Multi-turn conversation state preserved via x-ms-thread-id
  • โœ… All Module 4โ€“6 features active in the hosted endpoint

Key Concepts

ConceptWhere it appears
AgentFunctionAppfunction_app.py โ€” wraps the agent and registers HTTP endpoints
Durable stateConversation threads persist across invocations via the Durable Task Scheduler
x-ms-thread-idReturned on first call; pass as ?thread_id= to continue a conversation
AzuriteLocal Azure Storage emulator โ€” required for durable state in local development
A2A ProtocolAlternative for multi-agent systems โ€” learn more
OpenAI-Compatible EndpointsAlternative for OpenAI-compatible clients โ€” learn more
AG-UI ProtocolAlternative for web frontends โ€” learn more

Reference