Skip to content

Commit cfcd7c7

Browse files
Sync Agent Framework Python 1.0.0 docs (#960)
* Sync Python 1.0.0 docs Update the Agent Framework docs to reflect the final Python 1.0.0 changes, including the stable package installs, final Message(contents=...) construction change, and the latest breaking-change guidance. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix OpenAI provider tab IDs Resolve the duplicate DocFX tab-id warning in the OpenAI provider page by giving the configuration and creation tab groups distinct IDs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 3fa43e6 commit cfcd7c7

64 files changed

Lines changed: 976 additions & 553 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

agent-framework/agents/agent-pipeline.md

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ zone_pivot_groups: programming-languages
55
author: eavanvalkenburg
66
ms.topic: conceptual
77
ms.author: edvan
8-
ms.date: 03/20/2026
8+
ms.date: 04/02/2026
99
ms.service: agent-framework
1010
---
1111

@@ -40,13 +40,13 @@ The `Agent` class builds a pipeline through class composition with two main comp
4040
**Agent** (outer component):
4141

4242
1. **Agent Middleware + Telemetry** - the `AgentMiddlewareLayer` and `AgentTelemetryLayer` classes handle middleware invocation and OpenTelemetry instrumentation
43-
2. **RawAgent** - Core agent logic that invokes context providers
44-
3. **Context Providers** - Unified `context_providers` list manages history and additional context
43+
2. **RawAgent** - Core agent logic that invokes context providers and collects provider-added middleware
44+
3. **Context Providers** - Unified `context_providers` list manages history, additional context, and per-run chat/function middleware
4545

4646
**ChatClient** (separate and interchangeable component):
4747

4848
1. **FunctionInvocation** - Handles tool calling loop, invoking Function Middleware + Telemetry per tool call
49-
2. **Chat Middleware + Telemetry** - Optional middleware chain and instrumentation layers, running per model call
49+
2. **Chat Middleware + Telemetry** - Optional middleware chain and instrumentation layers, including any chat middleware added by context providers, running per model call
5050
3. **RawChatClient** - Provider-specific implementation (Azure OpenAI, OpenAI, Anthropic, etc.) that communicates with the LLM
5151

5252
When you call `run()`, your request flows through the Agent layers, then into the ChatClient pipeline for LLM communication.
@@ -144,6 +144,8 @@ agent = Agent(
144144
)
145145
```
146146

147+
Context providers can also attach chat or function middleware to a single invocation via `SessionContext.extend_middleware()`. The agent flattens those additions in provider order before entering the ChatClient pipeline.
148+
147149
::: zone-end
148150

149151
For detailed context provider patterns, see [Context Providers](./conversations/context-providers.md).
@@ -228,14 +230,14 @@ When you invoke an agent, the request flows through the pipeline:
228230
**Agent pipeline:**
229231

230232
1. **Agent Middleware + Telemetry** executes middleware (if configured) and records spans
231-
2. **RawAgent** invokes context providers to load history and add context
233+
2. **RawAgent** invokes context providers to load history, add context, and collect provider-added chat/function middleware
232234
3. Request is passed to the ChatClient
233235

234236
**ChatClient pipeline:**
235237

236238
4. **FunctionInvocation** manages the tool calling loop
237-
- For each tool call, **Function Middleware + Telemetry** executes
238-
5. **Chat Middleware + Telemetry** executes per model call (if configured)
239+
- For each tool call, **Function Middleware + Telemetry** executes, including any function middleware added by context providers
240+
5. **Chat Middleware + Telemetry** executes per model call (if configured), including any chat middleware added by context providers
239241
6. **RawChatClient** handles provider-specific LLM communication
240242
7. Response flows back through the same layers
241243
8. **Context providers** are notified of new messages for storage
@@ -276,6 +278,16 @@ var copilotAgent = originalCopilotAgent
276278
::: zone-end
277279

278280
::: zone pivot="programming-language-python"
281+
282+
## Other agent types
283+
284+
Not every Python agent uses the full `Agent` + `ChatClient` pipeline. `GitHubCopilotAgent`, for example, sends requests through the GitHub Copilot CLI instead of a local chat client.
285+
286+
Even so, Python `GitHubCopilotAgent` still supports agent middleware and now runs `context_providers` around each invocation. Provider-added messages and instructions are included in the prompt sent to Copilot, and providers receive the matching `after_run` callback once a response is available.
287+
288+
> [!NOTE]
289+
> Because `GitHubCopilotAgent` does not use a local chat client, chat client middleware still does not apply.
290+
279291
::: zone-end
280292

281293
## Next steps
@@ -287,4 +299,4 @@ var copilotAgent = originalCopilotAgent
287299

288300
- [Middleware](./middleware/index.md) - Add cross-cutting behavior to your agents
289301
- [Context Providers](./conversations/context-providers.md) - Detailed patterns for history and context injection
290-
- [Running Agents](./running-agents.md) - How to invoke agents
302+
- [Running Agents](./running-agents.md) - How to invoke agents

agent-framework/agents/conversations/context-providers.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -282,10 +282,10 @@ internal sealed class AdvancedServiceMemoryProvider : AIContextProvider
282282
```python
283283
from typing import Any
284284

285-
from agent_framework import AgentSession, BaseContextProvider, SessionContext
285+
from agent_framework import AgentSession, ContextProvider, SessionContext
286286

287287

288-
class UserPreferenceProvider(BaseContextProvider):
288+
class UserPreferenceProvider(ContextProvider):
289289
def __init__(self) -> None:
290290
super().__init__("user-preferences")
291291

@@ -314,6 +314,11 @@ class UserPreferenceProvider(BaseContextProvider):
314314
state["favorite_food"] = text.split("favorite food is", 1)[1].strip().rstrip(".")
315315
```
316316

317+
> [!NOTE]
318+
> `ContextProvider` and `HistoryProvider` are the canonical Python base classes. `BaseContextProvider` and `BaseHistoryProvider` still exist as deprecated aliases for compatibility, but new providers should inherit from the new names.
319+
>
320+
> Context providers can also add chat or function middleware for the current invocation by calling `context.extend_middleware(self.source_id, middleware)`. The agent flattens those additions with `context.get_middleware()` and applies them in provider order before invoking the chat client.
321+
317322
:::zone-end
318323

319324
:::zone pivot="programming-language-python"
@@ -326,10 +331,10 @@ History providers are context providers specialized for loading/storing messages
326331
from collections.abc import Sequence
327332
from typing import Any
328333

329-
from agent_framework import BaseHistoryProvider, Message
334+
from agent_framework import HistoryProvider, Message
330335

331336

332-
class DatabaseHistoryProvider(BaseHistoryProvider):
337+
class DatabaseHistoryProvider(HistoryProvider):
333338
def __init__(self, db: Any) -> None:
334339
super().__init__("db-history", load_messages=True)
335340
self._db = db
@@ -365,6 +370,7 @@ class DatabaseHistoryProvider(BaseHistoryProvider):
365370
> [!IMPORTANT]
366371
> In Python, you can configure multiple history providers, but **only one** should use `load_messages=True`.
367372
> Use additional providers for diagnostics/evals with `load_messages=False` and `store_context_messages=True` so they capture context from other providers alongside input/output.
373+
> If you need local history to persist around each model call in a tool loop, see [Storage](./storage.md#per-service-call-local-history-persistence).
368374
>
369375
> Example pattern:
370376
>

agent-framework/agents/conversations/storage.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,32 @@ response = await agent.run("Continue this conversation.", session=session)
120120

121121
:::zone-end
122122

123+
## Per-service-call local history persistence
124+
125+
Tool-calling runs can make multiple model calls before a single `agent.run()` completes. By default, local history providers persist once after the full run. If you want local history to mirror service-managed conversations more closely, set `require_per_service_call_history_persistence=True` so history providers run around each model call instead.
126+
127+
:::zone pivot="programming-language-python"
128+
129+
```python
130+
from agent_framework import Agent, InMemoryHistoryProvider
131+
from agent_framework.openai import OpenAIChatClient
132+
133+
agent = Agent(
134+
client=OpenAIChatClient(),
135+
name="StorageAgent",
136+
instructions="You are a helpful assistant.",
137+
context_providers=[InMemoryHistoryProvider("memory", load_messages=True)],
138+
require_per_service_call_history_persistence=True,
139+
)
140+
```
141+
142+
> [!IMPORTANT]
143+
> Use this mode only for framework-managed local history. If the run is already bound to a service-managed conversation (for example via `session.service_session_id` or `options={"conversation_id": ...}`), Agent Framework raises an error instead of mixing the two persistence models.
144+
>
145+
> This mode is especially useful when middleware can terminate immediately after a tool call: persisting per model call keeps local history aligned with what a service-managed conversation would keep.
146+
147+
:::zone-end
148+
123149
## Third-party/Custom storage pattern
124150

125151
For database/Redis/blob-backed history, implement a custom history provider.

agent-framework/agents/declarative.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ model:
9797
id: =Env.AZURE_OPENAI_MODEL
9898
connection:
9999
kind: remote
100-
endpoint: =Env.AZURE_AI_PROJECT_ENDPOINT
100+
endpoint: =Env.FOUNDRY_PROJECT_ENDPOINT
101101
"""
102102
async with (
103103
AzureCliCredential() as credential,

agent-framework/agents/index.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ titleSuffix: Microsoft Foundry
44
description: Learn different Agent Framework agent types.
55
ms.service: agent-framework
66
ms.topic: tutorial
7-
ms.date: 09/04/2025
7+
ms.date: 04/01/2026
88
ms.reviewer: ssalgado
99
zone_pivot_groups: programming-languages
1010
author: TaoChenOSU
@@ -224,8 +224,8 @@ from azure.identity.aio import DefaultAzureCredential
224224
agent = Agent(
225225
client=FoundryChatClient(
226226
credential=DefaultAzureCredential(),
227-
project_endpoint=os.getenv("AZURE_AI_PROJECT_ENDPOINT"),
228-
model=os.getenv("AZURE_AI_MODEL_DEPLOYMENT_NAME"),
227+
project_endpoint=os.getenv("FOUNDRY_PROJECT_ENDPOINT"),
228+
model=os.getenv("FOUNDRY_MODEL"),
229229
),
230230
instructions="You are a helpful assistant",
231231
)
@@ -240,8 +240,8 @@ from azure.identity.aio import DefaultAzureCredential
240240

241241
agent = FoundryChatClient(
242242
credential=DefaultAzureCredential(),
243-
project_endpoint=os.getenv("AZURE_AI_PROJECT_ENDPOINT"),
244-
model=os.getenv("AZURE_AI_MODEL_DEPLOYMENT_NAME"),
243+
project_endpoint=os.getenv("FOUNDRY_PROJECT_ENDPOINT"),
244+
model=os.getenv("FOUNDRY_MODEL"),
245245
).as_agent(
246246
instructions="You are a helpful assistant"
247247
)
@@ -259,7 +259,6 @@ For detailed examples, see the agent-specific documentation sections below.
259259
|[Foundry Agent](./providers/microsoft-foundry.md)|An agent that uses the Agent Service as its backend.|Yes|
260260
|[Azure OpenAI Chat Completion](./providers/azure-openai.md)|An agent that uses the Azure OpenAI Chat Completion service.|No|
261261
|[Azure OpenAI Responses](./providers/azure-openai.md)|An agent that uses the Azure OpenAI Responses service.|Yes|
262-
|[Azure OpenAI Assistants](./providers/azure-openai.md)|An agent that uses the Azure OpenAI Assistants service.|Yes|
263262
|[OpenAI Chat Completion](./providers/openai.md)|An agent that uses the OpenAI Chat Completion service.|No|
264263
|[OpenAI Responses](./providers/openai.md)|An agent that uses the OpenAI Responses service.|Yes|
265264
|[Anthropic Claude](./providers/anthropic.md)|An agent that uses Anthropic Claude models.|No|
@@ -287,9 +286,11 @@ async for chunk in agent.run("What's the weather like in Portland?", stream=True
287286

288287
For streaming examples, see:
289288

290-
- [Azure AI streaming examples](https://github.com/microsoft/agent-framework/blob/main/python/samples/02-agents/providers/azure_ai/azure_ai_basic.py)
291-
- [Azure OpenAI streaming examples](https://github.com/microsoft/agent-framework/blob/main/python/samples/02-agents/providers/azure_openai/azure_chat_client_basic.py)
292-
- [OpenAI streaming examples](https://github.com/microsoft/agent-framework/blob/main/python/samples/02-agents/providers/openai/openai_chat_client_basic.py)
289+
- [Foundry streaming examples](https://github.com/microsoft/agent-framework/blob/main/python/samples/02-agents/providers/foundry/foundry_chat_client_basic.py)
290+
- [Azure OpenAI Chat Completion streaming examples](https://github.com/microsoft/agent-framework/blob/main/python/samples/02-agents/providers/azure/openai_chat_completion_client_basic.py)
291+
- [Azure OpenAI Responses streaming examples](https://github.com/microsoft/agent-framework/blob/main/python/samples/02-agents/providers/azure/openai_client_basic.py)
292+
- [OpenAI Chat Completion streaming examples](https://github.com/microsoft/agent-framework/blob/main/python/samples/02-agents/providers/openai/chat_completion_client_basic.py)
293+
- [OpenAI Responses streaming examples](https://github.com/microsoft/agent-framework/blob/main/python/samples/02-agents/providers/openai/client_basic.py)
293294

294295
For more invocation patterns, see [Running Agents](./running-agents.md).
295296

@@ -310,8 +311,8 @@ def get_weather(location: Annotated[str, "The location to get the weather for."]
310311
async with DefaultAzureCredential() as credential:
311312
agent = FoundryChatClient(
312313
credential=credential,
313-
project_endpoint=os.getenv("AZURE_AI_PROJECT_ENDPOINT"),
314-
model=os.getenv("AZURE_AI_MODEL_DEPLOYMENT_NAME"),
314+
project_endpoint=os.getenv("FOUNDRY_PROJECT_ENDPOINT"),
315+
model=os.getenv("FOUNDRY_MODEL"),
315316
).as_agent(
316317
instructions="You are a helpful weather assistant.",
317318
tools=get_weather,

agent-framework/agents/middleware/agent-vs-run-scope.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ zone_pivot_groups: programming-languages
55
author: eavanvalkenburg
66
ms.topic: reference
77
ms.author: edvan
8-
ms.date: 02/09/2026
8+
ms.date: 04/01/2026
99
ms.service: agent-framework
1010
---
1111

@@ -150,7 +150,8 @@ from agent_framework import (
150150
FunctionInvocationContext,
151151
tool,
152152
)
153-
from agent_framework.azure import AzureAIAgentClient
153+
from agent_framework import Agent
154+
from agent_framework.foundry import FoundryChatClient
154155
from azure.identity.aio import AzureCliCredential
155156
from pydantic import Field
156157

@@ -325,7 +326,8 @@ async def main() -> None:
325326
# authentication option.
326327
async with (
327328
AzureCliCredential() as credential,
328-
AzureAIAgentClient(credential=credential).as_agent(
329+
Agent(
330+
client=FoundryChatClient(credential=credential),
329331
name="WeatherAgent",
330332
instructions="You are a helpful weather assistant.",
331333
tools=get_weather,
@@ -448,7 +450,8 @@ from agent_framework import (
448450
FunctionInvocationContext,
449451
tool,
450452
)
451-
from agent_framework.azure import AzureAIAgentClient
453+
from agent_framework import Agent
454+
from agent_framework.foundry import FoundryChatClient
452455
from azure.identity.aio import AzureCliCredential
453456
from pydantic import Field
454457

@@ -623,7 +626,8 @@ async def main() -> None:
623626
# authentication option.
624627
async with (
625628
AzureCliCredential() as credential,
626-
AzureAIAgentClient(credential=credential).as_agent(
629+
Agent(
630+
client=FoundryChatClient(credential=credential),
627631
name="WeatherAgent",
628632
instructions="You are a helpful weather assistant.",
629633
tools=get_weather,

0 commit comments

Comments
 (0)