diff --git a/python/packages/azure-cosmos-memory/AGENTS.md b/python/packages/azure-cosmos-memory/AGENTS.md
index 19a45e41663..dcaf780afc4 100644
--- a/python/packages/azure-cosmos-memory/AGENTS.md
+++ b/python/packages/azure-cosmos-memory/AGENTS.md
@@ -32,6 +32,9 @@ from agent_framework_azure_cosmos_memory import CosmosMemoryContextProvider
- Requires the `azure-cosmos-agent-memory` toolkit and an AI Foundry endpoint (used for both
embeddings and fact extraction).
+- Documentation and examples that show a literal Foundry project endpoint must use the full project-scoped form
+ `https://your-account.services.ai.azure.com/api/projects/your-project`, including the `/api/projects/your-project`
+ path.
- Set a stable `user_id` in `state["user_id"]` or `session.state["user_id"]` for long-term,
cross-session memory. Without it, memory scopes to the ephemeral session id and the provider
logs a one-time warning.
diff --git a/python/packages/core/AGENTS.md b/python/packages/core/AGENTS.md
index 13361bbeaa9..7678a7a57d9 100644
--- a/python/packages/core/AGENTS.md
+++ b/python/packages/core/AGENTS.md
@@ -352,6 +352,9 @@ The vector store API is experimental under the shared `VECTOR_STORES` feature ID
- **`FoundryChatClient`** - Chat client for Microsoft Foundry project endpoints
- **`FoundryAgentSessionStore`** - Experimental Foundry-hosting session store, lazily re-exported from
`agent-framework-foundry-hosting`; currently backed by `azure.ai.agentserver.core.storage.FoundryStateStore`
+- Documentation and examples that show a literal Foundry project endpoint must use the full project-scoped form
+ `https://your-account.services.ai.azure.com/api/projects/your-project`, including the `/api/projects/your-project`
+ path.
## Key Patterns
diff --git a/python/samples/01-get-started/01_hello_agent.py b/python/samples/01-get-started/01_hello_agent.py
index 8f85af11f52..7ee0d162b07 100644
--- a/python/samples/01-get-started/01_hello_agent.py
+++ b/python/samples/01-get-started/01_hello_agent.py
@@ -1,50 +1,29 @@
# Copyright (c) Microsoft. All rights reserved.
+"""Create and run a minimal Agent Framework agent.
+
+The agent uses a Microsoft Foundry chat client and prints one response.
+For streaming, see `foundry_chat_client_basic.py` in:
+https://github.com/microsoft/agent-framework/tree/main/python/samples/02-agents/providers/foundry
+"""
+
import asyncio
from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
-"""
-Hello Agent — Simplest possible agent
-
-This sample creates a minimal agent using FoundryChatClient via an
-Microsoft Foundry project endpoint, and runs it in both non-streaming and streaming modes.
-
-There are XML tags in all of the get started samples, those are used to display the same code in the docs repo.
-"""
-
async def main() -> None:
- #
- client = FoundryChatClient(
- project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
- model="gpt-4o",
- credential=AzureCliCredential(),
- )
-
agent = Agent(
- client=client,
- name="HelloAgent",
+ client=FoundryChatClient(
+ project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
+ model="gpt-6-luna",
+ credential=AzureCliCredential(),
+ ),
instructions="You are a friendly assistant. Keep your answers brief.",
)
- #
-
- #
- # Non-streaming: get the complete response at once
- result = await agent.run("What is the capital of France?")
- print(f"Agent: {result}")
- #
-
- #
- # Streaming: receive tokens as they are generated
- print("Agent (streaming): ", end="", flush=True)
- async for chunk in agent.run("Tell me a one-sentence fun fact.", stream=True):
- if chunk.text:
- print(chunk.text, end="", flush=True)
- print()
- #
+ print(await agent.run("What is the largest city of France?"))
if __name__ == "__main__":
diff --git a/python/samples/01-get-started/02_add_tools.py b/python/samples/01-get-started/02_add_tools.py
index 37eca46ed59..3a5b8fc33dc 100644
--- a/python/samples/01-get-started/02_add_tools.py
+++ b/python/samples/01-get-started/02_add_tools.py
@@ -1,62 +1,36 @@
# Copyright (c) Microsoft. All rights reserved.
+"""Give an agent a function tool.
+
+The weather function is registered with @tool and passed to the agent.
+Safety guidance: https://learn.microsoft.com/agent-framework/concepts/agents/safety
+"""
+
import asyncio
-from random import randint
-from typing import Annotated
from agent_framework import Agent, tool
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
-from pydantic import Field
-
-"""
-Add Tools — Give your agent a function tool
-
-This sample shows how to define a function tool with the @tool decorator
-and wire it into an agent so the model can call it.
-"""
-#
-# NOTE: approval_mode="never_require" is for sample brevity.
-# Use "always_require" in production for user confirmation before tool execution.
-# For tools processing untrusted external data or performing privileged operations,
-# review the Agent Safety guidance at
-# https://learn.microsoft.com/en-us/agent-framework/concepts/agents/safety
-# and see samples/02-agents/security/email_security_example.py for SecureAgentConfig
-# and quarantined_llm defense patterns.
+# This read-only sample tool can run without approval.
@tool(approval_mode="never_require")
-def get_weather(
- location: Annotated[str, Field(description="The location to get the weather for.")],
-) -> str:
+def get_weather(location: str) -> str:
"""Get the weather for a given location."""
- conditions = ["sunny", "cloudy", "rainy", "stormy"]
- return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
-
-
-#
+ return f"The weather in {location} is sunny."
async def main() -> None:
- client = FoundryChatClient(
- project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
- model="gpt-4o",
- credential=AzureCliCredential(),
- )
-
- #
agent = Agent(
- client=client,
- name="WeatherAgent",
- instructions="You are a helpful weather agent. Use the get_weather tool to answer questions.",
+ client=FoundryChatClient(
+ project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
+ model="gpt-6-luna",
+ credential=AzureCliCredential(),
+ ),
+ instructions="Use the weather tool to answer questions.",
tools=[get_weather],
)
- #
-
- #
- result = await agent.run("What's the weather like in Seattle?")
- print(f"Agent: {result}")
- #
+ print(await agent.run("What's the weather like in Seattle?"))
if __name__ == "__main__":
diff --git a/python/samples/01-get-started/03_multi_turn.py b/python/samples/01-get-started/03_multi_turn.py
index f1ab3123d0a..0efaa6ed3d2 100644
--- a/python/samples/01-get-started/03_multi_turn.py
+++ b/python/samples/01-get-started/03_multi_turn.py
@@ -1,46 +1,30 @@
# Copyright (c) Microsoft. All rights reserved.
+"""Reuse one agent session across multiple turns.
+
+The shared session preserves conversation history between calls.
+"""
+
import asyncio
from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
-"""
-Multi-Turn Conversations — Use AgentSession to maintain context
-
-This sample shows how to keep conversation history across multiple calls
-by reusing the same session object.
-"""
-
async def main() -> None:
- #
- client = FoundryChatClient(
- project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
- model="gpt-4o",
- credential=AzureCliCredential(),
- )
-
agent = Agent(
- client=client,
- name="ConversationAgent",
+ client=FoundryChatClient(
+ project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
+ model="gpt-6-luna",
+ credential=AzureCliCredential(),
+ ),
instructions="You are a friendly assistant. Keep your answers brief.",
)
- #
-
- #
- # Create a session to maintain conversation history
session = agent.create_session()
- # First turn
- result = await agent.run("My name is Alice and I love hiking.", session=session)
- print(f"Agent: {result}\n")
-
- # Second turn — the agent should remember the user's name and hobby
- result = await agent.run("What do you remember about me?", session=session)
- print(f"Agent: {result}")
- #
+ print(await agent.run("My name is Alice and I love hiking.", session=session))
+ print(await agent.run("What do you remember about me?", session=session))
if __name__ == "__main__":
diff --git a/python/samples/01-get-started/04_memory.py b/python/samples/01-get-started/04_memory.py
index 92f38d5e5e5..3da53dd9a57 100644
--- a/python/samples/01-get-started/04_memory.py
+++ b/python/samples/01-get-started/04_memory.py
@@ -1,5 +1,10 @@
# Copyright (c) Microsoft. All rights reserved.
+"""Persist a user's name with a context provider.
+
+The provider stores the name in session state and injects it into later calls.
+"""
+
import asyncio
from typing import Any
@@ -7,23 +12,10 @@
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
-"""
-Agent Memory with Context Providers and Session State
-Context providers inject dynamic context into each agent call. This sample
-shows a provider that stores the user's name in session state and personalizes
-responses — the name persists across turns via the session.
-"""
-
-
-#
class UserMemoryProvider(ContextProvider):
- """A context provider that remembers user info in session state."""
-
- DEFAULT_SOURCE_ID = "user_memory"
-
- def __init__(self):
- super().__init__(self.DEFAULT_SOURCE_ID)
+ def __init__(self) -> None:
+ super().__init__("user_memory")
async def before_run(
self,
@@ -33,18 +25,11 @@ async def before_run(
context: SessionContext,
state: dict[str, Any],
) -> None:
- """Inject personalization instructions based on stored user info."""
user_name = state.get("user_name")
- if user_name:
- context.extend_instructions(
- self.source_id,
- f"The user's name is {user_name}. Always address them by name.",
- )
- else:
- context.extend_instructions(
- self.source_id,
- "You don't know the user's name yet. Ask for it politely.",
- )
+ instructions = (
+ f"The user's name is {user_name}. Address them by name." if user_name else "Ask for the user's name."
+ )
+ context.extend_instructions(self.source_id, instructions)
async def after_run(
self,
@@ -54,51 +39,30 @@ async def after_run(
context: SessionContext,
state: dict[str, Any],
) -> None:
- """Extract and store user info in session state after each call."""
- for msg in context.input_messages:
- text = msg.text if hasattr(msg, "text") else ""
- if isinstance(text, str) and "my name is" in text.lower():
- state["user_name"] = text.lower().split("my name is")[-1].strip().split()[0].capitalize()
-
-
-#
+ for message in context.input_messages:
+ text = message.text
+ if not isinstance(text, str):
+ continue
+ _, marker, name = text.lower().partition("my name is")
+ if marker and name.strip():
+ state["user_name"] = name.split()[0].capitalize()
async def main() -> None:
- #
- client = FoundryChatClient(
- project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
- model="gpt-4o",
- credential=AzureCliCredential(),
- )
-
agent = Agent(
- client=client,
- name="MemoryAgent",
+ client=FoundryChatClient(
+ project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
+ model="gpt-6-luna",
+ credential=AzureCliCredential(),
+ ),
instructions="You are a friendly assistant.",
context_providers=[UserMemoryProvider()],
)
- #
-
- #
session = agent.create_session()
- # The provider doesn't know the user yet — it will ask for a name
- result = await agent.run("Hello! What's the square root of 9?", session=session)
- print(f"Agent: {result}\n")
-
- # Now provide the name — the provider stores it in session state
- result = await agent.run("My name is Alice", session=session)
- print(f"Agent: {result}\n")
-
- # Subsequent calls are personalized — name persists via session state
- result = await agent.run("What is 2 + 2?", session=session)
- print(f"Agent: {result}\n")
-
- # Inspect session state to see what the provider stored
- provider_state = session.state.get("user_memory", {})
- print(f"[Session State] Stored user name: {provider_state.get('user_name')}")
- #
+ print(await agent.run("Hello! What's the square root of 9?", session=session))
+ print(await agent.run("My name is Alice", session=session))
+ print(await agent.run("What is 2 + 2?", session=session))
if __name__ == "__main__":
diff --git a/python/samples/01-get-started/05a_functional_workflow_basics.py b/python/samples/01-get-started/05a_functional_workflow_basics.py
new file mode 100644
index 00000000000..fc46f6be423
--- /dev/null
+++ b/python/samples/01-get-started/05a_functional_workflow_basics.py
@@ -0,0 +1,33 @@
+# Copyright (c) Microsoft. All rights reserved.
+
+"""Compose two async functions into a functional workflow.
+
+The workflow uppercases text, then reverses it using normal Python control flow.
+"""
+
+import asyncio
+
+from agent_framework import workflow
+
+
+async def to_upper_case(text: str) -> str:
+ return text.upper()
+
+
+async def reverse_text(text: str) -> str:
+ return text[::-1]
+
+
+@workflow
+async def text_workflow(text: str) -> str:
+ upper = await to_upper_case(text)
+ return await reverse_text(upper)
+
+
+async def main() -> None:
+ result = await text_workflow.build().run("hello world")
+ print(result.get_outputs()[0])
+
+
+if __name__ == "__main__":
+ asyncio.run(main())
diff --git a/python/samples/01-get-started/05_functional_workflow_with_agents.py b/python/samples/01-get-started/05b_functional_workflow_with_agents.py
similarity index 50%
rename from python/samples/01-get-started/05_functional_workflow_with_agents.py
rename to python/samples/01-get-started/05b_functional_workflow_with_agents.py
index e77c1bc7431..e17a74fd9a0 100644
--- a/python/samples/01-get-started/05_functional_workflow_with_agents.py
+++ b/python/samples/01-get-started/05b_functional_workflow_with_agents.py
@@ -1,10 +1,8 @@
# Copyright (c) Microsoft. All rights reserved.
-"""
-Functional Workflow with Agents — Call agents inside @workflow
+"""Call two agents from a functional workflow.
-This sample shows how to call agents inside a functional workflow.
-Agent calls are just regular async function calls — no special wrappers needed.
+One agent writes a poem, and the other reviews it.
"""
import asyncio
@@ -12,40 +10,31 @@
from agent_framework import Agent, workflow
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
-from dotenv import load_dotenv
-
-# Load environment variables from .env file (e.g., FOUNDRY_PROJECT_ENDPOINT, FOUNDRY_MODEL)
-load_dotenv()
-#
-client = FoundryChatClient(credential=AzureCliCredential())
+client = FoundryChatClient(
+ project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
+ model="gpt-6-luna",
+ credential=AzureCliCredential(),
+)
writer = Agent(
- name="WriterAgent",
- instructions="Write a short poem (4 lines max) about the given topic.",
client=client,
+ instructions="Write a four-line poem about the given topic.",
)
reviewer = Agent(
- name="ReviewerAgent",
- instructions="Review the given poem in one sentence. Is it good?",
client=client,
+ instructions="Review the poem in one sentence.",
)
-#
-#
@workflow
async def poem_workflow(topic: str) -> str:
- """Write a poem, then review it."""
poem = (await writer.run(f"Write a poem about: {topic}")).text
review = (await reviewer.run(f"Review this poem: {poem}")).text
return f"Poem:\n{poem}\n\nReview: {review}"
-#
-
-
async def main() -> None:
workflow_instance = poem_workflow.build()
result = await workflow_instance.run("a cat learning to code")
diff --git a/python/samples/01-get-started/05c_first_graph_workflow.py b/python/samples/01-get-started/05c_first_graph_workflow.py
new file mode 100644
index 00000000000..1d635fa4cbf
--- /dev/null
+++ b/python/samples/01-get-started/05c_first_graph_workflow.py
@@ -0,0 +1,31 @@
+# Copyright (c) Microsoft. All rights reserved.
+
+"""Build a graph workflow from two function executors.
+
+The first executor transforms the input and sends it to the terminal executor.
+"""
+
+import asyncio
+
+from agent_framework import WorkflowBuilder, WorkflowContext, executor
+from typing_extensions import Never
+
+
+@executor(id="upper_case")
+async def upper_case(text: str, ctx: WorkflowContext[str]) -> None:
+ await ctx.send_message(text.upper())
+
+
+@executor(id="reverse_text")
+async def reverse_text(text: str, ctx: WorkflowContext[Never, str]) -> None:
+ await ctx.yield_output(text[::-1])
+
+
+async def main() -> None:
+ workflow = WorkflowBuilder(start_executor=upper_case).add_edge(upper_case, reverse_text).build()
+ result = await workflow.run("hello world")
+ print(result.get_outputs()[0])
+
+
+if __name__ == "__main__":
+ asyncio.run(main())
diff --git a/python/samples/01-get-started/06_agent_harness.py b/python/samples/01-get-started/06_agent_harness.py
new file mode 100644
index 00000000000..eb1ad53d43a
--- /dev/null
+++ b/python/samples/01-get-started/06_agent_harness.py
@@ -0,0 +1,34 @@
+# Copyright (c) Microsoft. All rights reserved.
+
+"""Create a harness agent for multi-step tasks.
+
+A harness adds planning, todos, and compaction to a regular agent.
+More samples: https://github.com/microsoft/agent-framework/tree/main/python/samples/02-agents/harness
+"""
+
+import asyncio
+
+from agent_framework import create_harness_agent
+from agent_framework.foundry import FoundryChatClient
+from azure.identity import AzureCliCredential
+
+
+async def main() -> None:
+ agent = create_harness_agent(
+ client=FoundryChatClient(
+ project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
+ model="gpt-6-luna",
+ credential=AzureCliCredential(),
+ ),
+ agent_instructions="Help users plan and complete multi-step tasks.",
+ disable_file_memory=True,
+ disable_web_search=True,
+ )
+ session = agent.create_session()
+
+ print(await agent.run("Plan a weekend trip to Seattle.", session=session))
+ print(await agent.run("Turn that plan into a checklist.", session=session))
+
+
+if __name__ == "__main__":
+ asyncio.run(main())
diff --git a/python/samples/01-get-started/06_functional_workflow_basics.py b/python/samples/01-get-started/06_functional_workflow_basics.py
deleted file mode 100644
index ec6fd79f538..00000000000
--- a/python/samples/01-get-started/06_functional_workflow_basics.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright (c) Microsoft. All rights reserved.
-
-"""
-Functional Workflow Basics — Orchestrate async functions with @workflow
-
-The functional API lets you write workflows as plain Python async functions.
-No graph concepts, no edges, no executor classes — just call functions
-and use native control flow (if/else, loops, asyncio.gather).
-
-This sample builds a minimal pipeline with two steps:
-1. Convert text to uppercase
-2. Reverse the text
-
-No external services are required.
-"""
-
-import asyncio
-
-from agent_framework import workflow
-
-
-# Plain async functions — no decorators needed
-async def to_upper_case(text: str) -> str:
- """Convert input to uppercase."""
- return text.upper()
-
-
-async def reverse_text(text: str) -> str:
- """Reverse the string."""
- return text[::-1]
-
-
-#
-@workflow
-async def text_workflow(text: str) -> str:
- """Uppercase the text, then reverse it."""
- upper = await to_upper_case(text)
- return await reverse_text(upper)
-
-
-#
-
-
-async def main() -> None:
- #
- workflow_instance = text_workflow.build()
- result = await workflow_instance.run("hello world")
- print(f"Output: {result.get_outputs()}")
- print(f"Final state: {result.get_final_state()}")
- #
-
- """
- Expected output:
- Output: ['DLROW OLLEH']
- Final state: WorkflowRunState.IDLE
- """
-
-
-if __name__ == "__main__":
- asyncio.run(main())
diff --git a/python/samples/01-get-started/07_first_graph_workflow.py b/python/samples/01-get-started/07_first_graph_workflow.py
deleted file mode 100644
index 2a84fabfab2..00000000000
--- a/python/samples/01-get-started/07_first_graph_workflow.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (c) Microsoft. All rights reserved.
-
-import asyncio
-
-from agent_framework import (
- Executor,
- WorkflowBuilder,
- WorkflowContext,
- executor,
- handler,
-)
-from typing_extensions import Never
-
-"""
-First Graph Workflow — Chain executors with edges
-
-The graph API gives you full control over execution topology: edges,
-fan-out/fan-in, switch/case, and superstep-based checkpointing.
-
-This sample builds a minimal graph workflow with two steps:
-1. Convert text to uppercase (class-based executor)
-2. Reverse the text (function-based executor)
-
-No external services are required.
-"""
-
-
-#
-# Step 1: A class-based executor that converts text to uppercase
-class UpperCase(Executor):
- def __init__(self, id: str):
- super().__init__(id=id)
-
- @handler
- async def to_upper_case(self, text: str, ctx: WorkflowContext[str]) -> None:
- """Convert input to uppercase and forward to the next node."""
- await ctx.send_message(text.upper())
-
-
-# Step 2: A function-based executor that reverses the string and yields output
-@executor(id="reverse_text")
-async def reverse_text(text: str, ctx: WorkflowContext[Never, str]) -> None:
- """Reverse the string and yield the final workflow output."""
- await ctx.yield_output(text[::-1])
-
-
-def create_workflow():
- """Build the workflow: UpperCase → reverse_text."""
- upper = UpperCase(id="upper_case")
- return WorkflowBuilder(start_executor=upper).add_edge(upper, reverse_text).build()
-
-
-#
-
-
-async def main() -> None:
- #
- workflow = create_workflow()
-
- events = await workflow.run("hello world")
- print(f"Output: {events.get_outputs()}")
- print(f"Final state: {events.get_final_state()}")
- #
-
- """
- Expected output:
- Output: ['DLROW OLLEH']
- Final state: WorkflowRunState.IDLE
- """
-
-
-if __name__ == "__main__":
- asyncio.run(main())
diff --git a/python/samples/01-get-started/07_hosting.py b/python/samples/01-get-started/07_hosting.py
new file mode 100644
index 00000000000..291416ba46c
--- /dev/null
+++ b/python/samples/01-get-started/07_hosting.py
@@ -0,0 +1,37 @@
+# /// script
+# requires-python = ">=3.10"
+# dependencies = [
+# "agent-framework-foundry",
+# "agent-framework-foundry-hosting",
+# "azure-identity",
+# ]
+# ///
+# Run with: uv run python/samples/01-get-started/07_hosting.py
+
+# Copyright (c) Microsoft. All rights reserved.
+
+"""Host an agent with the Foundry Responses protocol.
+
+The same Responses host can run locally or as a Microsoft Foundry Hosted Agent.
+"""
+
+from agent_framework import Agent
+from agent_framework.foundry import FoundryChatClient, ResponsesHostServer
+from azure.identity import DefaultAzureCredential
+
+
+def main() -> None:
+ agent = Agent(
+ client=FoundryChatClient(
+ project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
+ model="gpt-6-luna",
+ credential=DefaultAzureCredential(),
+ ),
+ instructions="You are a friendly assistant. Keep your answers brief.",
+ default_options={"store": False},
+ )
+ ResponsesHostServer(agent=agent, history_source="agent_server").run()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/python/samples/01-get-started/README.md b/python/samples/01-get-started/README.md
index 74aad7cccaa..709c9ed82ff 100644
--- a/python/samples/01-get-started/README.md
+++ b/python/samples/01-get-started/README.md
@@ -6,29 +6,33 @@ concepts of **Agent Framework** one step at a time.
## Prerequisites
```bash
-pip install agent-framework-foundry
+pip install agent-framework-foundry azure-identity
+az login
```
-Set the required environment variables:
+All samples hardcode example values for `project_endpoint` and `model`. Replace them with your Microsoft
+Foundry project endpoint and model deployment name before running the sample.
-```bash
-export FOUNDRY_PROJECT_ENDPOINT="https://your-project-endpoint"
-export FOUNDRY_MODEL="gpt-4o"
-```
+Alternatively, set `FOUNDRY_PROJECT_ENDPOINT` and `FOUNDRY_MODEL`, then remove the `project_endpoint` and `model`
+arguments from the `FoundryChatClient` constructor. To read those values from a `.env` file, call `load_dotenv()`
+before creating the client; Agent Framework doesn't load `.env` files automatically.
## Samples
| # | File | What you'll learn |
|---|------|-------------------|
-| 1 | [01_hello_agent.py](01_hello_agent.py) | Create your first agent and run it (streaming and non-streaming). |
+| 1 | [01_hello_agent.py](01_hello_agent.py) | Create your first agent and run one request. |
| 2 | [02_add_tools.py](02_add_tools.py) | Define a function tool with `@tool` and attach it to an agent. |
-| 3 | [03_multi_turn.py](03_multi_turn.py) | Keep conversation history across turns with `AgentSession`. |
-| 4 | [04_memory.py](04_memory.py) | Add dynamic context with a custom `ContextProvider`. |
-| 5 | [05_functional_workflow_with_agents.py](05_functional_workflow_with_agents.py) | Call agents inside a functional workflow. |
-| 6 | [06_functional_workflow_basics.py](06_functional_workflow_basics.py) | Write a workflow as a plain async function. |
-| 7 | [07_first_graph_workflow.py](07_first_graph_workflow.py) | Chain executors into a graph workflow with edges. |
+| 3 | [03_multi_turn.py](03_multi_turn.py) | Reuse an agent session to keep conversation history across turns. |
+| 4 | [04_memory.py](04_memory.py) | Store and inject session state with a custom `ContextProvider`. |
+| 5a | [05a_functional_workflow_basics.py](05a_functional_workflow_basics.py) | Write a workflow as a plain async function. |
+| 5b | [05b_functional_workflow_with_agents.py](05b_functional_workflow_with_agents.py) | Call agents inside a functional workflow. |
+| 5c | [05c_first_graph_workflow.py](05c_first_graph_workflow.py) | Connect function executors with a graph edge. |
+| 6 | [06_agent_harness.py](06_agent_harness.py) | Add planning, todo tracking, and compaction with an agent harness. |
+| 7 | [07_hosting.py](07_hosting.py) | Serve an agent with `ResponsesHostServer`. |
-To host agents and workflows with Durable Task or Azure Functions, continue with the [Durable Agent Framework extension samples](https://github.com/microsoft/agent-framework-durable-extension/tree/main/python/samples).
+For more hosting patterns, continue with [`04-hosting/`](../04-hosting/). Durable Task and Azure Functions samples
+are in the [Durable Agent Framework extension](https://github.com/microsoft/agent-framework-durable-extension/tree/main/python/samples).
## Security in Production
@@ -41,10 +45,17 @@ For the official security guidance, see [Agent Safety](https://learn.microsoft.c
3. [`github_mcp_example.py`](../02-agents/security/github_mcp_example.py): Demonstrates `SecureMCPToolProxy` wrapping remote MCP endpoints with local policy enforcement.
4. [FIDES Developer Guide](../02-agents/security/FIDES_DEVELOPER_GUIDE.md): Architecture reference and security middleware documentation.
-Run any sample with:
+Run samples 1 through 6 with:
```bash
python 01_hello_agent.py
```
-These samples use Azure Foundry models with the Responses API. To switch providers, just replace the client, see [all providers](../02-agents/providers/README.md)
+Run the PEP 723 hosting sample from the repository root with:
+
+```bash
+uv run python/samples/01-get-started/07_hosting.py
+```
+
+These samples use Microsoft Foundry models with the Responses API. To switch providers, replace the client. See
+[all providers](../02-agents/providers/README.md).
diff --git a/python/samples/AGENTS.md b/python/samples/AGENTS.md
index 916e550e07b..1a49f42e739 100644
--- a/python/samples/AGENTS.md
+++ b/python/samples/AGENTS.md
@@ -77,6 +77,10 @@ Durable Task and Azure Functions samples are maintained in the [Durable Agent Fr
All canonical samples (01-get-started) use **Microsoft Foundry project-backed chat** via `FoundryChatClient`
with a Microsoft Foundry project endpoint:
+Whenever a sample, README, or comment shows a literal Foundry project endpoint, use the full project-scoped form
+`https://your-account.services.ai.azure.com/api/projects/your-project`. Do not shorten the example to the
+account-level endpoint.
+
```python
import os
from agent_framework import Agent
diff --git a/python/samples/README.md b/python/samples/README.md
index a53b7eed88f..34befd72f66 100644
--- a/python/samples/README.md
+++ b/python/samples/README.md
@@ -6,7 +6,7 @@ This directory contains samples demonstrating the capabilities of Microsoft Agen
| Folder | Description |
|--------|-------------|
-| [`01-get-started/`](./01-get-started/) | Progressive tutorial: hello agent → graph workflows |
+| [`01-get-started/`](./01-get-started/) | Progressive tutorial: hello agent → workflows → harness → hosting |
| [`02-agents/`](./02-agents/) | Deep-dive by concept: tools, middleware, providers, orchestrations, security |
| [`03-workflows/`](./03-workflows/) | Workflow patterns: sequential, concurrent, state, declarative, explicit output designation |
| [`04-hosting/`](./04-hosting/) | Deployment: A2A, self-hosted protocol helpers, and Foundry hosted agents |
@@ -16,13 +16,17 @@ This directory contains samples demonstrating the capabilities of Microsoft Agen
Start with `01-get-started/` and work through the numbered files:
-1. **[01_hello_agent.py](./01-get-started/01_hello_agent.py)** — Create and run your first agent
-2. **[02_add_tools.py](./01-get-started/02_add_tools.py)** — Add function tools with `@tool`
-3. **[03_multi_turn.py](./01-get-started/03_multi_turn.py)** — Multi-turn conversations with `AgentSession`
-4. **[04_memory.py](./01-get-started/04_memory.py)** — Agent memory with `ContextProvider`
-5. **[05_functional_workflow_with_agents.py](./01-get-started/05_functional_workflow_with_agents.py)** — Call agents inside a functional workflow
-6. **[06_functional_workflow_basics.py](./01-get-started/06_functional_workflow_basics.py)** — Write a workflow as a plain async function
-7. **[07_first_graph_workflow.py](./01-get-started/07_first_graph_workflow.py)** — Build a workflow with executors and edges
+| Step | Sample | What it demonstrates |
+| --- | --- | --- |
+| 1 | [01_hello_agent.py](./01-get-started/01_hello_agent.py) | Create and run your first agent |
+| 2 | [02_add_tools.py](./01-get-started/02_add_tools.py) | Add function tools with `@tool` |
+| 3 | [03_multi_turn.py](./01-get-started/03_multi_turn.py) | Multi-turn conversations with `AgentSession` |
+| 4 | [04_memory.py](./01-get-started/04_memory.py) | Agent memory with `ContextProvider` |
+| 5a | [05a_functional_workflow_basics.py](./01-get-started/05a_functional_workflow_basics.py) | Write a workflow as a plain async function |
+| 5b | [05b_functional_workflow_with_agents.py](./01-get-started/05b_functional_workflow_with_agents.py) | Call agents inside a functional workflow |
+| 5c | [05c_first_graph_workflow.py](./01-get-started/05c_first_graph_workflow.py) | Build a workflow with function executors and edges |
+| 6 | [06_agent_harness.py](./01-get-started/06_agent_harness.py) | Add planning, todo tracking, and compaction |
+| 7 | [07_hosting.py](./01-get-started/07_hosting.py) | Serve an agent with `ResponsesHostServer` |
Durable Task and Azure Functions samples have moved to the [Durable Agent Framework extension](https://github.com/microsoft/agent-framework-durable-extension/tree/main/python/samples).