Agent to the existing Python v2 programming model. Your trigger, validation and response logic stay in your code.This article covers what the preview does, how to wire it up, how it works with Durable Functions, and where it falls short.
What an agent binding is
When the function runs, the extension builds an Agent from Markdown instructions and injects it into your handler as a typed parameter. Your code decides when and how to invoke the agent alongside your deterministic application logic.
The preview's limits are firm:
- Preview status. Agent bindings are in preview, and features, package names and configuration can change before general availability.
- One provider. Microsoft Agent Framework is the only agent SDK supported in the current preview. The architecture is provider-neutral on paper, but in practice there is one provider today.
- Python version. Microsoft's walkthrough requires Python 3.13 or later.
Don't confuse it with the serverless agents runtime
Microsoft has another preview in this area. The Azure Functions serverless agents runtime is a markdown-first model. It offers a built-in chat UI, HTTP API and MCP server endpoint with no extra code. There, the runtime owns the agent loop.
Agent bindings work the other way round. Your function is the coordinator, and the agent is a bounded reasoning step it calls. Pick the runtime when you want an agent to be the application. Pick bindings when you have an existing function that needs a bit of judgment.
Project layout
An agent-enabled app is a normal Python v2 function app with a few extra files:
function_app.pyholds triggers, deterministic logic, the client factory and the agent call.order-fulfillment.agent.mdholds raw UTF-8 instructions for one agent.requirements.txtselects the provider and client packages.local.settings.jsonholds storage, Foundry project and model settings. Don't commit it.- Optional
skills/andmcp.jsonprovide file-based Agent Skills and remote MCP servers.
An agent name must resolve to exactly one instruction file. Microsoft's example resolves order-fulfillment to either order-fulfillment.agent.md in the app root or the same file under agents/. If both exist, startup fails. Names can't contain absolute paths, path separators or traversal components.
Setup walkthrough
Prerequisites
You need:
- Python 3.13 or later
- an Azure subscription
- a Microsoft Foundry project with a deployed model
- Azure Functions Core Tools
- Azurite or an Azure Storage account
- the Azure CLI
- a local identity that can access the Foundry project
Packages
Microsoft's example requirements.txt lists azure-functions, azurefunctions-agents-extensions-agent-framework, agent-framework-foundry and azure-identity. The mcp extra adds remote MCP discovery. The durable extra adds Durable Functions support. The extension package connects the binding to Agent Framework, but it doesn't pick your model. The provider package leaves model provider selection to your client factory.
Local settings
local.settings.json carries four values:
AzureWebJobsStorage, set toUseDevelopmentStorage=truefor AzuriteFUNCTIONS_WORKER_RUNTIME, set topythonFOUNDRY_PROJECT_ENDPOINT, in the formhttps://<resource-name>.services.ai.azure.com/api/projects/<project-name>FOUNDRY_MODEL, the name of your model deployment
Instructions file
The .agent.md file is plain instructions. The extension passes the whole file through. It doesn't parse YAML front matter, model settings or tool declarations from it. Model choice lives in the client factory. Python tools stay explicit application configuration.
Client factory and decorator
AgentFunctionApp takes a zero-argument client factory. Microsoft's sample builds a FoundryChatClient from the two environment variables and authenticates with DefaultAzureCredential. You then apply @app.markdown_agent(arg_name="order_agent", agent_name="order-fulfillment") to a function.
arg_namemust match the handler parameter that receives the agent.agent_nameis the instruction file name without the.agent.mdsuffix.
The agent does not run on its own when the function starts. The handler calls await order_agent.run(...) explicitly. That is the design's best feature, because the reasoning step is visible and testable in your code.
What happens on each invocation
For every invocation, the extension:
- loads the instruction file
- calls your factory to create a client
- combines the instructions with configured tools, skills and MCP servers
- builds the Agent and injects it
- closes its resources afterwards
Microsoft says compiled definitions and provider discovery may be cached. Live clients and credentials are not reused across invocations.
Deterministic code first
Microsoft's order-processing example shows the intended pattern. Ordinary Python selects the fields the model needs: order ID, customer ID, currency, shipping destination and method, and items. The agent then assesses fulfillment risk and flags missing context. The function builds the HTTP response.
Data minimization is a real benefit here, because the model sees less. But treat the sample as a pattern, not a security control:
- The sample helper selects fields. It doesn't amount to full validation or authorization.
- The blog's sample instructions tell the model to treat the supplied fields as trusted facts.
- The Durable quickstart takes a more defensive line. It tells the agent to use order fields only as data and not to follow instructions inside them.
That difference is worth copying. Order fields can contain customer-supplied text, and prompt injection through data fields is a known risk class. Use the more defensive wording if any of your input originates outside your organization. Validate the model's output before it drives anything consequential.
Skills and MCP: the sharing caveat
The extension discovers file-based skills in skills/<name>/SKILL.md or Skills/<name>/SKILL.md. It reads remote MCP servers from a root mcp.json.
The preview has a significant limitation. Every agent binding in the function app receives all discovered agent skills and MCP servers. Microsoft's documentation says the preview can't select a subset for an app or for an individual binding. Skills and MCP tools can perform privileged operations. The guidance is to include only capabilities every agent in the app may use, and to split agents into separate function apps when their capability boundaries differ.
Other MCP details from Microsoft's documentation:
- Remote HTTP and streamable-HTTP servers are supported.
- Local-process and stdio servers are not.
mcp.jsoncan reference environment variables for URLs, headers, authentication scopes and client IDs. Microsoft says not to put secrets directly in a source-controlled file.
Python tools are scoped more tightly. You can pass them at the app level or on a single binding. Microsoft's example gives a lookup_inventory tool to just one agent.
Durable Functions
For work that outlives one request, install the durable extra. The Durable quickstart has three parts:
- HTTP starter. It checks the body is JSON and calls
start_new. It returns202 Acceptedwith management URLs, includingstatusQueryGetUri, plusLocationandRetry-Afterheaders. - Preparation activity. An ordinary activity validates and selects fields.
- Orchestrator. A synchronous generator yields
context.call_activity(...)and thencontext.call_agent("order-fulfillment", {...}).
Orchestrators replay, so they can't do model or network work directly. Microsoft says call_agent() schedules a hidden activity instead. That activity resolves the agent definition and performs the file, credential, model, tool and network operations. The orchestrator only builds a deterministic, JSON-serializable request. On replay, the recorded result is reused and the model isn't called again.
"Replay-safe" has a narrow meaning. The orchestrator doesn't repeat the model call on replay. That says nothing about the model giving the same answer twice, and it doesn't make the whole workflow exactly-once. Inputs and outputs must be JSON-serializable.
Running it locally
- Run
az loginsoDefaultAzureCredentialcan use your Azure CLI identity. - Start Azurite with
azurite --silent --location .azurite. - In a second terminal, run
func start. - POST an order to
/orders/orchestrations. The Durable sample putsorder_idin the body, because the starter has no route parameter for it. - Poll
statusQueryGetUriuntilruntimeStatusisCompleted, then readrisk_assessmentfrom the output.
Failure points
Microsoft's troubleshooting list covers the usual local problems:
| Symptom | Suggested check |
|---|---|
| Agent definition can't be found | Run func start from the app root and confirm the .agent.md file is there |
| Foundry authentication fails | Run az login, then verify the tenant, subscription and project access |
| Durable extension won't load | Confirm the durable extra is in requirements.txt and the extension bundle can download |
| Orchestration stays Pending | Confirm Azurite is running and AzureWebJobsStorage points at the right storage |
| Failure in the preparation activity | Confirm the order has order_id, a customer ID, shipping info and at least one item |
| Agent activity fails | Check host logs and instance status for authentication, model or quota errors |
Malformed JSON returns HTTP 400 and never starts an orchestration. Valid JSON with a missing required field does start one, and it then fails in the preparation activity. Callers who only look at the 202 will miss that. You need status polling or alerting.
Don't lean on breakpoints inside the orchestrator to run only once. Replay means they won't.
Which path to choose
- Call the agent directly when the answer belongs in the current HTTP response or trigger invocation.
- Use Durable Functions when you need persisted progress, several steps, waiting on external systems, or work that continues after the original request ends.
Microsoft also lists queue, Event Grid and timer triggers as places to use bindings, for example classifying or enriching event payloads. The published walkthroughs only demonstrate HTTP.
Practical takeaways
- Treat this as a preview. Microsoft's documentation warns that package names and configuration may change.
- Keep the agent's work narrow: classify, summarize or recommend. Leave authorization and writes to code.
- Because bindings share all discovered skills and MCP servers, separate function apps are the way to isolate capabilities.
- Use the more defensive instruction wording from the Durable quickstart when inputs are untrusted.
- Expect a Foundry project, a deployed model and a configured identity before anything runs.
Microsoft says it wants feedback and points to the Agent Extension repository for issues and feature requests.
References
- Bring agentic reasoning to Python function apps with Azure Functions Agent bindings (preview) Azure SDK Blog · 2026-10-06T15:00:10+00:00
- Use a Microsoft Agent Framework agent binding in a Durable orchestration | Microsoft Learn learn.microsoft.com
- Agent bindings for Python in Azure Functions learn.microsoft.com