You will learn how a Microsoft Agent Framework project can move from locally authored Python agents, tools, workflows, middleware, and observability into YAML configuration, hosted execution, and interactive local debugging.
Objective
Concept/Theory
The earlier chapters built the pieces of an agent system: instructions and identity, chat clients and messages, tools, workflows, human review, streaming, checkpoints, middleware, and traces. This final chapter is about the boundary around those pieces: how they are configured, where they run, and how you inspect them while developing.
A code-defined agent is easiest when behavior is dynamic or tightly coupled to Python. A declarative agent moves stable agent definition into YAML: name, description, instructions, model options, and related configuration. The host still supplies real runtime objects such as a chat client, tools, credentials, and policy, but the agent spec becomes easier to review, share, version, and load in different environments. Microsoft Learn describes this as a configuration-first way to create agents from YAML or external configuration stores.Microsoft Learn
Hosting is the next boundary. Locally, your Python process directly calls an agent or workflow. In production-oriented shapes, an adapter exposes that same framework object through a runtime: Azure Functions for serverless HTTP and durable patterns, Foundry-hosted agents for managed Foundry definitions, or Agent-to-Agent (A2A) for remote agent interoperability. This playbook stays at overview depth for hosting: you should recognize the entry points and when to investigate them, not treat this chapter as a deployment manual.
DevUI is the development boundary. It gives you a local web UI and OpenAI-compatible endpoint for trying agents and workflows while you build. That makes it a companion to Chapter 9 observability: traces and middleware show what happened, while DevUI gives you an interactive place to exercise the system. It is a sample developer host, not the production host for your application.Microsoft Learn
In MAF
This chapter targets the inspected Python packages agent-framework==1.9.0, agent-framework-declarative==1.0.0rc2, agent-framework-devui==1.0.0b260528, agent-framework-foundry==1.8.2, and agent-framework-a2a==1.0.0b260604.
Declarative agent loading
The verified loader is AgentFactory from agent_framework_declarative. Use create_agent_from_yaml(...) when you already have a YAML string, or create_agent_from_yaml_path(...) when the spec lives on disk.
AgentFactory for a prompt agent.kind: Prompt
name: LocalDeclarativeAgent
displayName: Local Declarative Agent
description: No-network PromptAgent definition loaded by AgentFactory.
instructions: |
You are a local demo agent. Keep responses short.
model:
options:
temperature: 0.0
agent-framework projects.from agent_framework_declarative import AgentFactory
factory = AgentFactory(client=chat_client)
agent_from_text = factory.create_agent_from_yaml(yaml_text)
agent_from_file = factory.create_agent_from_yaml_path("local_prompt_agent.yaml")
If you do not pass client=..., the factory expects provider configuration in the YAML and factory mappings, with Foundry as the default provider. Keep safe_mode=True for untrusted YAML.
DevUI launch
The real DevUI entry point is agent_framework_devui.serve. It starts a server, so use it from an application entry point rather than during imports or tests.
from agent_framework_devui import serve
# Marked server step: starts uvicorn and binds to 127.0.0.1:8080 by default.
serve(entities=[agent], port=8080, host="127.0.0.1", auto_open=False)
Hosting and A2A entry points
| Boundary | Verified entry point | Use it for |
|---|---|---|
| Azure Functions hosting | agent_framework.azure.AgentFunctionApp |
Registering agents or a workflow with Azure Functions HTTP endpoints, health checks, durable patterns, and optional MCP triggers.Microsoft Learn |
| Foundry model and hosted-agent integration | FoundryChatClient, FoundryAgent |
Connecting framework code to Azure AI Foundry project deployments and existing Foundry PromptAgent or HostedAgent definitions. Live use requires a Foundry project endpoint, credentials, and network access.Microsoft Learn |
| Foundry-hosted deployment shape | FoundryAgent |
Using managed, versioned agent definitions in Foundry when central lifecycle and platform hosting matter.Microsoft Learn |
| Agent-to-Agent interoperability | agent_framework_a2a.A2AAgent, A2AExecutor |
Calling remote A2A-compliant agents or bridging a local SupportsAgentRun object into A2A server infrastructure. Live client use requires an A2A endpoint and any required auth/network setup.Microsoft Learn |
| Local development UI | agent_framework_devui.serve, DevServer |
Manual testing, directory discovery, local OpenAI-compatible smoke tests, and trace-oriented debugging. It starts a local server and is not a production hosting adapter. |
When to use / pitfalls
| Choice | Use when | Avoid when |
|---|---|---|
| Declarative YAML | Instructions, model options, and agent metadata should be reviewed, versioned, or shared separately from Python host code. | The agent is assembled dynamically from trusted Python objects and the YAML layer would hide more than it clarifies. |
| Code-defined agents | Tool wiring, client construction, policies, and runtime composition are application-specific or depend on Python logic. | Non-Python contributors need to safely edit stable prompts and configuration without changing host code. |
| Local run or DevUI | You are building, debugging, or smoke-testing behavior before committing to a host. | You need production auth, scale, lifecycle management, or a hardened public endpoint. |
| Azure Functions, Foundry, or A2A hosting | The agent must be invoked by other systems, run in a managed environment, participate in remote collaboration, or use Foundry-managed definitions. | A single-process workflow or in-process multi-agent pattern from Chapters 6 and 7 is simpler and sufficient. |
Common pitfalls
- Treating YAML as execution. Declarative specs describe an agent, but a real run still needs a chat client or provider configuration, credentials for live models, and any tools or middleware supplied by the host.
- Putting secrets in YAML. Keep credentials in environment configuration, managed identity, or your deployment platform. YAML belongs in source control more often than secrets do.
- Disabling safety for convenience. Leave
AgentFactory(..., safe_mode=True)in place unless you fully control the source and consequences of the YAML. - Using DevUI as production hosting.
serve(...)is excellent for local exploration and debugging, but production needs explicit auth, policy, scaling, monitoring, and deployment controls. - Starting servers in import paths. Keep DevUI and hosting startup behind an application entry point so tests can import modules without binding ports or launching uvicorn.
- Jumping to remote agents too early. If all collaborators run in the same process, use direct agents, tools, workflows, handoff, or group chat before adding A2A network boundaries.
Worked example
The primary example is the verified file at backend/examples/ch10/declarative_loader.py. It loads backend/examples/ch10/local_prompt_agent.yaml, injects a no-network local chat client, runs the resulting agent, and prints the response. The UTF-8 stdout setup is only defensive robustness for Windows consoles because one imported dependency may print a Unicode character during import.
agent-framework==1.9.0; no keys or network required."""Load a declarative YAML agent without credentials or network."""
import asyncio
import sys
from pathlib import Path
# Importing agent_framework_declarative pulls in powerfx, which prints a Unicode
# checkmark at import time. Force UTF-8 stdout so this works on Windows consoles
# (cp1252) too, where it would otherwise raise UnicodeEncodeError.
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
from agent_framework import ChatResponse, Content, Message
from agent_framework_declarative import AgentFactory
class LocalChatClient:
async def get_response(self, messages, *, stream=False, options=None, middleware=None, **kwargs):
return ChatResponse(
messages=Message(role="assistant", contents=[Content.from_text("loaded declarative agent locally")]),
model="local-no-network",
)
async def main() -> None:
yaml_path = Path(__file__).with_name("local_prompt_agent.yaml")
factory = AgentFactory(client=LocalChatClient())
agent = factory.create_agent_from_yaml_path(yaml_path)
response = await agent.run("confirm load")
print(f"loaded: {agent.name}")
print(f"description: {agent.description}")
print(f"response: {response.text}")
if __name__ == "__main__":
asyncio.run(main())
The companion structure probe at backend/examples/ch10/devui_hosting_structure.py verifies import and construction boundaries without starting external services. It constructs DevServer and AgentFunctionApp, imports Foundry and A2A entry points, and explicitly skips live Foundry or A2A construction unless the environment contains the required endpoint values.
from agent_framework.azure import AgentFunctionApp
from agent_framework.foundry import FoundryAgent, FoundryChatClient
from agent_framework_a2a import A2AAgent, A2AExecutor
from agent_framework_devui import DevServer, serve
server = DevServer(port=8765, auth_enabled=False)
function_app = AgentFunctionApp(agents=[])
print(f"devui entry point: {serve.__module__}.serve")
print(f"dev server constructed: {type(server).__name__} (not started)")
print(f"azure functions app constructed: {type(function_app).__name__}")
print(f"foundry imports: {FoundryAgent.__name__}, {FoundryChatClient.__name__}")
print(f"a2a imports: {A2AAgent.__name__}, {A2AExecutor.__name__}")
Marked live steps: Foundry hosting needs FOUNDRY_PROJECT_ENDPOINT, credentials, and network access. A2A client construction needs an A2A endpoint such as A2A_AGENT_URL. DevUI launch with serve(...) starts a local server, so it is described here rather than run as part of the static example.
Recap & next
- Declarative agents let stable instructions and metadata move into YAML while the Python host still supplies clients, tools, credentials, middleware, and policy.
AgentFactory.create_agent_from_yaml(...)andAgentFactory.create_agent_from_yaml_path(...)are the verified Python loader calls for this chapter.agent_framework_devui.serve(...)is a local development server entry point, not a production hosting strategy.AgentFunctionApp,FoundryAgent,FoundryChatClient,A2AAgent, andA2AExecutorare the overview-level hosting and interoperability entry points to explore when you move beyond local execution.
This closes the playbook arc: Chapters 1 and 2 gave you the theory and pattern map; Chapters 3 through 5 built agents, messages, and tools; Chapters 6 through 8 added orchestration, collaboration, streaming, checkpointing, and human review; Chapter 9 added middleware and observability; and this chapter wrapped those pieces in configuration, hosting, and development UI boundaries.
Where to go next: use the Microsoft Learn Agent Framework documentation for current provider, hosting, DevUI, and A2A details, then compare your design with the official Microsoft Agent Framework GitHub samples before building a production deployment.Microsoft Learn GitHub samples