10. Host Agent
- 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
| Goal | Covered by |
|---|---|
| Understand the four hosting options | Hosting Options table |
| Install the Azure Functions hosting package | Step 1 |
| Start the Azurite local storage emulator | Step 2 |
Configure local.settings.json | Step 3 |
| Run the Functions host | Step 4 |
Invoke the hosted endpoint with curl | Step 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:
| Option | Description | Best For |
|---|---|---|
| A2A Protocol | Expose agents via the Agent-to-Agent protocol | Multi-agent systems |
| OpenAI-Compatible Endpoints | Expose agents via Chat Completions or Responses APIs | OpenAI-compatible clients |
| Azure Functions (Durable) | Run agents as durable Azure Functions | Serverless, long-running tasks |
| AG-UI Protocol | Build web-based AI agent applications | Web 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.
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/.envfile containsGITHUB_TOKENandGITHUB_MODEL. - The
labvirtual environment is active (.venv). - Azure Functions Core Tools 4.x installed (
funconPATH). - 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 inpyproject.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
| Concept | Where it appears |
|---|---|
AgentFunctionApp | function_app.py โ wraps the agent and registers HTTP endpoints |
| Durable state | Conversation threads persist across invocations via the Durable Task Scheduler |
x-ms-thread-id | Returned on first call; pass as ?thread_id= to continue a conversation |
| Azurite | Local Azure Storage emulator โ required for durable state in local development |
| A2A Protocol | Alternative for multi-agent systems โ learn more |
| OpenAI-Compatible Endpoints | Alternative for OpenAI-compatible clients โ learn more |
| AG-UI Protocol | Alternative for web frontends โ learn more |