Skip to content

Commit 8e2cc4b

Browse files
authored
Python: Update workflow orchestration samples to use AzureOpenAIResponsesClient (#4285)
* Update workflow orchestration samples to use AzureOpenAIResponsesClient * Fix broken link
1 parent cfaa0c6 commit 8e2cc4b

18 files changed

Lines changed: 192 additions & 70 deletions

docs/decisions/0001-agent-run-response.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ We need to decide what AIContent types, each agent response type will be mapped
498498
| Google ADK | **Approach 1** Both [input and output schemas can be specified for LLM Agents](https://google.github.io/adk-docs/agents/llm-agents/#structuring-data-input_schema-output_schema-output_key) at construction time. This option is specific to this agent type and other agent types do not necessarily support |
499499
| AWS (Strands) | **Approach 2** Supports a special invocation method called [structured_output](https://strandsagents.com/latest/documentation/docs/api-reference/python/agent/agent/#strands.agent.agent.Agent.structured_output) |
500500
| LangGraph | **Approach 1** Supports [configuring an agent](https://langchain-ai.github.io/langgraph/agents/agents/?h=structured#6-configure-structured-output) at agent construction time, and a [structured response](https://langchain-ai.github.io/langgraph/agents/run_agents/#output-format) can be retrieved as a special property on the agent response |
501-
| Agno | **Approach 1** Supports [configuring an agent](https://docs.agno.com/examples/getting-started/structured-output) at agent construction time |
501+
| Agno | **Approach 1** Supports [configuring an agent](https://docs.agno.com/input-output/structured-output/agent) at agent construction time |
502502
| A2A | **Informal Approach 2** Doesn't formally support schema negotiation, but [hints can be provided via metadata](https://a2a-protocol.org/latest/specification/#97-structured-data-exchange-requesting-and-providing-json) at invocation time |
503503
| Protocol Activity | Supports returning [Complex types](https://github.com/microsoft/Agents/blob/main/specs/activity/protocol-activity.md#complex-types) but no support for requesting a type |
504504

python/samples/03-workflows/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,14 @@ Sequential orchestration uses a few small adapter nodes for plumbing:
160160
These may appear in event streams (executor_invoked/executor_completed). They're analogous to
161161
concurrent’s dispatcher and aggregator and can be ignored if you only care about agent activity.
162162

163+
### AzureOpenAIResponsesClient vs AzureAIAgent
164+
165+
Workflow and orchestration samples use `AzureOpenAIResponsesClient` rather than the CRUD-style `AzureAIAgent` client. The key difference:
166+
167+
- **`AzureOpenAIResponsesClient`** — A lightweight client that uses the underlying Agent Service V2 (Responses API) for non-CRUD-style agents. Orchestrations use this client because agents are created locally and do not require server-side lifecycle management (create/update/delete). This is the recommended client for orchestration patterns (Sequential, Concurrent, Handoff, GroupChat, Magentic).
168+
169+
- **`AzureAIAgent`** — A CRUD-style client for server-managed agents. Use this when you need persistent, server-side agent definitions with features like file search, code interpreter sessions, or thread management provided by the Azure AI Agent Service.
170+
163171
### Environment Variables
164172

165173
Workflow samples that use `AzureOpenAIResponsesClient` expect:

python/samples/03-workflows/declarative/agent_to_function_tool/main.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818
"""
1919

2020
import asyncio
21+
import os
2122
from pathlib import Path
2223
from typing import Any
2324

24-
from agent_framework.azure import AzureOpenAIChatClient
25+
from agent_framework.azure import AzureOpenAIResponsesClient
2526
from agent_framework.declarative import WorkflowFactory
2627
from azure.identity import AzureCliCredential
2728
from pydantic import BaseModel, Field
@@ -196,8 +197,12 @@ def format_order_confirmation(order_data: dict[str, Any], order_calculation: dic
196197

197198
async def main():
198199
"""Run the agent to function tool workflow."""
199-
# Create Azure OpenAI client
200-
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
200+
# Create Azure OpenAI Responses client
201+
chat_client = AzureOpenAIResponsesClient(
202+
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
203+
deployment_name=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
204+
credential=AzureCliCredential(),
205+
)
201206

202207
# Create the order analysis agent with structured output
203208
order_analysis_agent = chat_client.as_agent(

python/samples/03-workflows/declarative/function_tools/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This sample demonstrates an agent with function tools responding to user queries
66

77
The workflow showcases:
88
- **Function Tools**: Agent equipped with tools to query menu data
9-
- **Real Azure OpenAI Agent**: Uses `AzureOpenAIChatClient` to create an agent with tools
9+
- **Real Azure OpenAI Agent**: Uses `AzureOpenAIResponsesClient` to create an agent with tools
1010
- **Agent Registration**: Shows how to register agents with the `WorkflowFactory`
1111

1212
## Tools
@@ -72,7 +72,11 @@ Session Complete
7272

7373
```python
7474
# Create the agent with tools
75-
client = AzureOpenAIChatClient(credential=AzureCliCredential())
75+
client = AzureOpenAIResponsesClient(
76+
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
77+
deployment_name=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
78+
credential=AzureCliCredential(),
79+
)
7680
menu_agent = client.as_agent(
7781
name="MenuAgent",
7882
instructions="You are a helpful restaurant menu assistant...",

python/samples/03-workflows/orchestrations/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ from agent_framework.orchestrations import (
9292

9393
These may appear in event streams (executor_invoked/executor_completed). They're analogous to concurrent's dispatcher and aggregator and can be ignored if you only care about agent activity.
9494

95+
## Why AzureOpenAIResponsesClient?
96+
97+
Orchestration samples use `AzureOpenAIResponsesClient` rather than the CRUD-style `AzureAIAgent` client. Orchestrations create agents locally and do not require server-side lifecycle management (create/update/delete). `AzureOpenAIResponsesClient` is a lightweight client that uses the underlying Agent Service V2 (Responses API) for non-CRUD-style agents, which is ideal for orchestration patterns like Sequential, Concurrent, Handoff, GroupChat, and Magentic.
98+
9599
## Environment Variables
96100

97101
Orchestration samples that use `AzureOpenAIResponsesClient` expect:

python/samples/03-workflows/orchestrations/concurrent_agents.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# Copyright (c) Microsoft. All rights reserved.
22

33
import asyncio
4+
import os
45
from typing import Any
56

67
from agent_framework import Message
7-
from agent_framework.azure import AzureOpenAIChatClient
8+
from agent_framework.azure import AzureOpenAIResponsesClient
89
from agent_framework.orchestrations import ConcurrentBuilder
910
from azure.identity import AzureCliCredential
1011
from dotenv import load_dotenv
@@ -26,14 +27,20 @@
2627
- Workflow completion when idle with no pending work
2728
2829
Prerequisites:
29-
- Azure OpenAI access configured for AzureOpenAIChatClient (use az login + env vars)
30+
- AZURE_AI_PROJECT_ENDPOINT must be your Azure AI Foundry Agent Service (V2) project endpoint.
31+
- Azure OpenAI configured for AzureOpenAIResponsesClient with required environment variables.
32+
- Authentication via azure-identity. Use AzureCliCredential and run az login before executing the sample.
3033
- Familiarity with Workflow events (WorkflowEvent)
3134
"""
3235

3336

3437
async def main() -> None:
35-
# 1) Create three domain agents using AzureOpenAIChatClient
36-
client = AzureOpenAIChatClient(credential=AzureCliCredential())
38+
# 1) Create three domain agents using AzureOpenAIResponsesClient
39+
client = AzureOpenAIResponsesClient(
40+
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
41+
deployment_name=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
42+
credential=AzureCliCredential(),
43+
)
3744

3845
researcher = client.as_agent(
3946
instructions=(

python/samples/03-workflows/orchestrations/concurrent_custom_agent_executors.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright (c) Microsoft. All rights reserved.
22

33
import asyncio
4+
import os
45
from typing import Any
56

67
from agent_framework import (
@@ -12,7 +13,7 @@
1213
WorkflowContext,
1314
handler,
1415
)
15-
from agent_framework.azure import AzureOpenAIChatClient
16+
from agent_framework.azure import AzureOpenAIResponsesClient
1617
from agent_framework.orchestrations import ConcurrentBuilder
1718
from azure.identity import AzureCliCredential
1819
from dotenv import load_dotenv
@@ -29,21 +30,23 @@
2930
ConcurrentBuilder API and the default aggregator.
3031
3132
Demonstrates:
32-
- Executors that create their Agent in __init__ (via AzureOpenAIChatClient)
33+
- Executors that create their Agent in __init__ (via AzureOpenAIResponsesClient)
3334
- A @handler that converts AgentExecutorRequest -> AgentExecutorResponse
3435
- ConcurrentBuilder(participants=[...]) to build fan-out/fan-in
3536
- Default aggregator returning list[Message] (one user + one assistant per agent)
3637
- Workflow completion when all participants become idle
3738
3839
Prerequisites:
39-
- Azure OpenAI configured for AzureOpenAIChatClient (az login + required env vars)
40+
- AZURE_AI_PROJECT_ENDPOINT must be your Azure AI Foundry Agent Service (V2) project endpoint.
41+
- Azure OpenAI configured for AzureOpenAIResponsesClient with required environment variables.
42+
- Authentication via azure-identity. Use AzureCliCredential and run az login before executing the sample.
4043
"""
4144

4245

4346
class ResearcherExec(Executor):
4447
agent: Agent
4548

46-
def __init__(self, client: AzureOpenAIChatClient, id: str = "researcher"):
49+
def __init__(self, client: AzureOpenAIResponsesClient, id: str = "researcher"):
4750
self.agent = client.as_agent(
4851
instructions=(
4952
"You're an expert market and product researcher. Given a prompt, provide concise, factual insights,"
@@ -63,7 +66,7 @@ async def run(self, request: AgentExecutorRequest, ctx: WorkflowContext[AgentExe
6366
class MarketerExec(Executor):
6467
agent: Agent
6568

66-
def __init__(self, client: AzureOpenAIChatClient, id: str = "marketer"):
69+
def __init__(self, client: AzureOpenAIResponsesClient, id: str = "marketer"):
6770
self.agent = client.as_agent(
6871
instructions=(
6972
"You're a creative marketing strategist. Craft compelling value propositions and target messaging"
@@ -83,7 +86,7 @@ async def run(self, request: AgentExecutorRequest, ctx: WorkflowContext[AgentExe
8386
class LegalExec(Executor):
8487
agent: Agent
8588

86-
def __init__(self, client: AzureOpenAIChatClient, id: str = "legal"):
89+
def __init__(self, client: AzureOpenAIResponsesClient, id: str = "legal"):
8790
self.agent = client.as_agent(
8891
instructions=(
8992
"You're a cautious legal/compliance reviewer. Highlight constraints, disclaimers, and policy concerns"
@@ -101,7 +104,11 @@ async def run(self, request: AgentExecutorRequest, ctx: WorkflowContext[AgentExe
101104

102105

103106
async def main() -> None:
104-
client = AzureOpenAIChatClient(credential=AzureCliCredential())
107+
client = AzureOpenAIResponsesClient(
108+
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
109+
deployment_name=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
110+
credential=AzureCliCredential(),
111+
)
105112

106113
researcher = ResearcherExec(client)
107114
marketer = MarketerExec(client)

python/samples/03-workflows/orchestrations/concurrent_custom_aggregator.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# Copyright (c) Microsoft. All rights reserved.
22

33
import asyncio
4+
import os
45
from typing import Any
56

67
from agent_framework import Message
7-
from agent_framework.azure import AzureOpenAIChatClient
8+
from agent_framework.azure import AzureOpenAIResponsesClient
89
from agent_framework.orchestrations import ConcurrentBuilder
910
from azure.identity import AzureCliCredential
1011
from dotenv import load_dotenv
@@ -17,7 +18,7 @@
1718
1819
Build a concurrent workflow with ConcurrentBuilder that fans out one prompt to
1920
multiple domain agents and fans in their responses. Override the default
20-
aggregator with a custom async callback that uses AzureOpenAIChatClient.get_response()
21+
aggregator with a custom async callback that uses AzureOpenAIResponsesClient.get_response()
2122
to synthesize a concise, consolidated summary from the experts' outputs.
2223
The workflow completes when all participants become idle.
2324
@@ -28,12 +29,18 @@
2829
- Workflow output yielded with the synthesized summary string
2930
3031
Prerequisites:
31-
- Azure OpenAI configured for AzureOpenAIChatClient (az login + required env vars)
32+
- AZURE_AI_PROJECT_ENDPOINT must be your Azure AI Foundry Agent Service (V2) project endpoint.
33+
- Azure OpenAI configured for AzureOpenAIResponsesClient with required environment variables.
34+
- Authentication via azure-identity. Use AzureCliCredential and run az login before executing the sample.
3235
"""
3336

3437

3538
async def main() -> None:
36-
client = AzureOpenAIChatClient(credential=AzureCliCredential())
39+
client = AzureOpenAIResponsesClient(
40+
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
41+
deployment_name=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
42+
credential=AzureCliCredential(),
43+
)
3744

3845
researcher = client.as_agent(
3946
instructions=(

python/samples/03-workflows/orchestrations/group_chat_agent_manager.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
# Copyright (c) Microsoft. All rights reserved.
22

33
import asyncio
4+
import os
45
from typing import cast
56

67
from agent_framework import (
78
Agent,
89
AgentResponseUpdate,
910
Message,
1011
)
11-
from agent_framework.azure import AzureOpenAIChatClient
12+
from agent_framework.azure import AzureOpenAIResponsesClient
1213
from agent_framework.orchestrations import GroupChatBuilder
1314
from azure.identity import AzureCliCredential
1415
from dotenv import load_dotenv
@@ -25,7 +26,9 @@
2526
- Coordinates a researcher and writer agent to solve tasks collaboratively
2627
2728
Prerequisites:
28-
- OpenAI environment variables configured for OpenAIChatClient
29+
- AZURE_AI_PROJECT_ENDPOINT must be your Azure AI Foundry Agent Service (V2) project endpoint.
30+
- Azure OpenAI configured for AzureOpenAIResponsesClient with required environment variables.
31+
- Authentication via azure-identity. Use AzureCliCredential and run az login before executing the sample.
2932
"""
3033

3134
ORCHESTRATOR_AGENT_INSTRUCTIONS = """
@@ -39,8 +42,12 @@
3942

4043

4144
async def main() -> None:
42-
# Create a chat client using Azure OpenAI and Azure CLI credentials for all agents
43-
client = AzureOpenAIChatClient(credential=AzureCliCredential())
45+
# Create a Responses client using Azure OpenAI and Azure CLI credentials for all agents
46+
client = AzureOpenAIResponsesClient(
47+
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
48+
deployment_name=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
49+
credential=AzureCliCredential(),
50+
)
4451

4552
# Orchestrator agent that manages the conversation
4653
# Note: This agent (and the underlying chat client) must support structured outputs.

python/samples/03-workflows/orchestrations/group_chat_philosophical_debate.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
import asyncio
44
import logging
5+
import os
56
from typing import cast
67

78
from agent_framework import (
89
Agent,
910
AgentResponseUpdate,
1011
Message,
1112
)
12-
from agent_framework.azure import AzureOpenAIChatClient
13+
from agent_framework.azure import AzureOpenAIResponsesClient
1314
from agent_framework.orchestrations import GroupChatBuilder
1415
from azure.identity import AzureCliCredential
1516
from dotenv import load_dotenv
@@ -38,15 +39,21 @@
3839
- Doctor from Scandinavia (public health, equity, societal support)
3940
4041
Prerequisites:
41-
- OpenAI environment variables configured for OpenAIChatClient
42+
- AZURE_AI_PROJECT_ENDPOINT must be your Azure AI Foundry Agent Service (V2) project endpoint.
43+
- Azure OpenAI configured for AzureOpenAIResponsesClient with required environment variables.
44+
- Authentication via azure-identity. Use AzureCliCredential and run az login before executing the sample.
4245
"""
4346

4447
# Load environment variables from .env file
4548
load_dotenv()
4649

4750

48-
def _get_chat_client() -> AzureOpenAIChatClient:
49-
return AzureOpenAIChatClient(credential=AzureCliCredential())
51+
def _get_chat_client() -> AzureOpenAIResponsesClient:
52+
return AzureOpenAIResponsesClient(
53+
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
54+
deployment_name=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
55+
credential=AzureCliCredential(),
56+
)
5057

5158

5259
async def main() -> None:

0 commit comments

Comments
 (0)