mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: [BREAKING] Simplify API: ChatAgent -> Agent, ChatMessage -> Message (#3747)
* [BREAKING] Rename ChatAgent -> Agent, ChatMessage -> Message, ChatClientProtocol -> SupportsChatGetResponse Simplify the public API by removing redundant 'Chat' prefix from core types: - ChatAgent -> Agent - RawChatAgent -> RawAgent - ChatMessage -> Message - ChatClientProtocol -> SupportsChatGetResponse Also renamed internal WorkflowMessage (was Message in _runner_context) to avoid collision. No backward compatibility aliases - this is a clean breaking change. * [BREAKING] Rename Agent chat_client parameter to client * Fix rebase issues: WorkflowMessage references and broken markdown links * Fix formatting and lint issues from code quality checks * Fix import ordering in workflow sample files * fixed rebase * Fix test failures: use WorkflowMessage and A2AMessage after ChatMessage→Message rename - Replace Message(data=..., source_id=...) with WorkflowMessage(...) in workflow tests - Fix isinstance check in A2A agent to use A2AMessage instead of Message - Fix import in test_workflow_observability.py (Message→WorkflowMessage) * Fix lint, fmt, and sample errors after ChatMessage→Message rename - Auto-fix 70+ ruff lint issues across samples (ChatMessage→Message refs) - Fix HostedVectorStoreContent→Content.from_hosted_vector_store in file search sample - Fix _normalize_messages→normalize_messages in custom agent sample - Fix context.terminate→raise MiddlewareTermination in middleware samples - Fix with_update_hook→with_transform_hook in override middleware sample - Add TOptions_co import back to custom_chat_client sample - Add noqa for FastAPI File() default in chatkit sample - Fix B023 loop variable capture in weather agent sample * fix: update Agent constructor calls from chat_client to client in declaration-only tool tests * fix: add register_cleanup to devui lazy-loading proxy and type stub * fixed tests and updated new pieces * fix agui typevar * fix merge errors * fix merge conflicts * fiux merge * Remove unused links --------- Co-authored-by: Evan Mattson <evan.mattson@microsoft.com>
This commit is contained in:
co-authored by
Evan Mattson
parent
a4c9e43afb
commit
0521f5bed8
@@ -23,7 +23,7 @@ This sample demonstrates the three main methods of AzureAIProjectAgentProvider:
|
||||
It also shows how to use a single provider instance to spawn multiple agents
|
||||
with different configurations, which is efficient for multi-agent scenarios.
|
||||
|
||||
Each method returns a ChatAgent that can be used for conversations.
|
||||
Each method returns a Agent that can be used for conversations.
|
||||
"""
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ async def create_agent_example() -> None:
|
||||
"""Example of using provider.create_agent() to create a new agent.
|
||||
|
||||
This method creates a new agent version on the Azure AI service and returns
|
||||
a ChatAgent. Use this when you want to create a fresh agent with
|
||||
a Agent. Use this when you want to create a fresh agent with
|
||||
specific configuration.
|
||||
"""
|
||||
print("=== provider.create_agent() Example ===")
|
||||
@@ -199,7 +199,7 @@ async def multiple_agents_example() -> None:
|
||||
async def as_agent_example() -> None:
|
||||
"""Example of using provider.as_agent() to wrap an SDK object without HTTP calls.
|
||||
|
||||
This method wraps an existing AgentVersionDetails into a ChatAgent without
|
||||
This method wraps an existing AgentVersionDetails into a Agent without
|
||||
making additional HTTP calls. Use this when you already have the full
|
||||
AgentVersionDetails from a previous SDK operation.
|
||||
"""
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework import Agent
|
||||
from agent_framework.azure import AzureAIClient
|
||||
from azure.ai.projects.aio import AIProjectClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
@@ -23,8 +23,8 @@ async def main() -> None:
|
||||
# Endpoint here should be application endpoint with format:
|
||||
# /api/projects/<project-name>/applications/<application-name>/protocols
|
||||
AIProjectClient(endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], credential=credential) as project_client,
|
||||
ChatAgent(
|
||||
chat_client=AzureAIClient(
|
||||
Agent(
|
||||
client=AzureAIClient(
|
||||
project_client=project_client,
|
||||
),
|
||||
) as agent,
|
||||
|
||||
+5
-5
@@ -5,9 +5,9 @@ import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
from agent_framework import (
|
||||
Agent,
|
||||
AgentResponseUpdate,
|
||||
Annotation,
|
||||
ChatAgent,
|
||||
Content,
|
||||
HostedCodeInterpreterTool,
|
||||
)
|
||||
@@ -33,7 +33,7 @@ QUERY = (
|
||||
)
|
||||
|
||||
|
||||
async def download_container_files(file_contents: list[Annotation | Content], agent: ChatAgent) -> list[Path]:
|
||||
async def download_container_files(file_contents: list[Annotation | Content], agent: Agent) -> list[Path]:
|
||||
"""Download container files using the OpenAI containers API.
|
||||
|
||||
Code interpreter generates files in containers, which require both file_id
|
||||
@@ -45,7 +45,7 @@ async def download_container_files(file_contents: list[Annotation | Content], ag
|
||||
Args:
|
||||
file_contents: List of Annotation or Content objects
|
||||
containing file_id and container_id.
|
||||
agent: The ChatAgent instance with access to the AzureAIClient.
|
||||
agent: The Agent instance with access to the AzureAIClient.
|
||||
|
||||
Returns:
|
||||
List of Path objects for successfully downloaded files.
|
||||
@@ -61,7 +61,7 @@ async def download_container_files(file_contents: list[Annotation | Content], ag
|
||||
print(f"\nDownloading {len(file_contents)} container file(s) to {output_dir.absolute()}...")
|
||||
|
||||
# Access the OpenAI client from AzureAIClient
|
||||
openai_client = agent.chat_client.client # type: ignore[attr-defined]
|
||||
openai_client = agent.client.client # type: ignore[attr-defined]
|
||||
|
||||
downloaded_files: list[Path] = []
|
||||
|
||||
@@ -139,7 +139,7 @@ async def non_streaming_example() -> None:
|
||||
|
||||
# Check for annotations in the response
|
||||
annotations_found: list[Annotation] = []
|
||||
# AgentResponse has messages property, which contains ChatMessage objects
|
||||
# AgentResponse has messages property, which contains Message objects
|
||||
for message in result.messages:
|
||||
for content in message.contents:
|
||||
if content.type == "text" and content.annotations:
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ async def non_streaming_example() -> None:
|
||||
|
||||
# Check for annotations in the response
|
||||
annotations_found: list[str] = []
|
||||
# AgentResponse has messages property, which contains ChatMessage objects
|
||||
# AgentResponse has messages property, which contains Message objects
|
||||
for message in result.messages:
|
||||
for content in message.contents:
|
||||
if content.type == "text" and content.annotations:
|
||||
|
||||
@@ -36,7 +36,7 @@ async def using_provider_get_agent() -> None:
|
||||
)
|
||||
|
||||
try:
|
||||
# Get newly created agent as ChatAgent by using provider.get_agent()
|
||||
# Get newly created agent as Agent by using provider.get_agent()
|
||||
provider = AzureAIProjectAgentProvider(project_client=project_client)
|
||||
agent = await provider.get_agent(name=azure_ai_agent.name)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import AgentResponse, AgentThread, ChatMessage, HostedMCPTool, SupportsAgentRun
|
||||
from agent_framework import AgentResponse, AgentThread, HostedMCPTool, Message, SupportsAgentRun
|
||||
from agent_framework.azure import AzureAIProjectAgentProvider
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
@@ -25,10 +25,10 @@ async def handle_approvals_without_thread(query: str, agent: "SupportsAgentRun")
|
||||
f"User Input Request for function from {agent.name}: {user_input_needed.function_call.name}"
|
||||
f" with arguments: {user_input_needed.function_call.arguments}"
|
||||
)
|
||||
new_inputs.append(ChatMessage("assistant", [user_input_needed]))
|
||||
new_inputs.append(Message("assistant", [user_input_needed]))
|
||||
user_approval = input("Approve function call? (y/n): ")
|
||||
new_inputs.append(
|
||||
ChatMessage("user", [user_input_needed.to_function_approval_response(user_approval.lower() == "y")])
|
||||
Message("user", [user_input_needed.to_function_approval_response(user_approval.lower() == "y")])
|
||||
)
|
||||
|
||||
result = await agent.run(new_inputs, store=False)
|
||||
@@ -48,7 +48,7 @@ async def handle_approvals_with_thread(query: str, agent: "SupportsAgentRun", th
|
||||
)
|
||||
user_approval = input("Approve function call? (y/n): ")
|
||||
new_input.append(
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")],
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@ All examples in this folder use the `AzureAIAgentsProvider` class which provides
|
||||
|
||||
- **`create_agent()`** - Create a new agent on the Azure AI service
|
||||
- **`get_agent()`** - Retrieve an existing agent by ID or from a pre-fetched Agent object
|
||||
- **`as_agent()`** - Wrap an SDK Agent object as a ChatAgent without HTTP calls
|
||||
- **`as_agent()`** - Wrap an SDK Agent object as a Agent without HTTP calls
|
||||
|
||||
```python
|
||||
from agent_framework.azure import AzureAIAgentsProvider
|
||||
|
||||
@@ -17,7 +17,7 @@ servers, including user approval workflows for function call security.
|
||||
|
||||
async def handle_approvals_with_thread(query: str, agent: "SupportsAgentRun", thread: "AgentThread") -> AgentResponse:
|
||||
"""Here we let the thread deal with the previous responses, and we just rerun with the approval."""
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework import Message
|
||||
|
||||
result = await agent.run(query, thread=thread, store=True)
|
||||
while len(result.user_input_requests) > 0:
|
||||
@@ -29,7 +29,7 @@ async def handle_approvals_with_thread(query: str, agent: "SupportsAgentRun", th
|
||||
)
|
||||
user_approval = input("Approve function call? (y/n): ")
|
||||
new_input.append(
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")],
|
||||
)
|
||||
|
||||
@@ -51,7 +51,7 @@ async def mcp_tools_on_agent_level() -> None:
|
||||
print("=== Tools Defined on Agent Level ===")
|
||||
|
||||
# Tools are provided when creating the agent
|
||||
# The ChatAgent will connect to the MCP server through its context manager
|
||||
# The Agent will connect to the MCP server through its context manager
|
||||
# and discover tools at runtime
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
|
||||
+2
-2
@@ -45,7 +45,7 @@ def get_time() -> str:
|
||||
|
||||
async def handle_approvals_with_thread(query: str, agent: "SupportsAgentRun", thread: "AgentThread"):
|
||||
"""Here we let the thread deal with the previous responses, and we just rerun with the approval."""
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework import Message
|
||||
|
||||
result = await agent.run(query, thread=thread, store=True)
|
||||
while len(result.user_input_requests) > 0:
|
||||
@@ -57,7 +57,7 @@ async def handle_approvals_with_thread(query: str, agent: "SupportsAgentRun", th
|
||||
)
|
||||
user_approval = input("Approve function call? (y/n): ")
|
||||
new_input.append(
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")],
|
||||
)
|
||||
|
||||
@@ -6,17 +6,17 @@ This folder contains examples demonstrating different ways to create and use age
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| [`azure_assistants_basic.py`](azure_assistants_basic.py) | The simplest way to create an agent using `ChatAgent` with `AzureOpenAIAssistantsClient`. Shows both streaming and non-streaming responses with automatic assistant creation and cleanup. |
|
||||
| [`azure_assistants_basic.py`](azure_assistants_basic.py) | The simplest way to create an agent using `Agent` with `AzureOpenAIAssistantsClient`. Shows both streaming and non-streaming responses with automatic assistant creation and cleanup. |
|
||||
| [`azure_assistants_with_code_interpreter.py`](azure_assistants_with_code_interpreter.py) | Shows how to use the HostedCodeInterpreterTool with Azure agents to write and execute Python code. Includes helper methods for accessing code interpreter data from response chunks. |
|
||||
| [`azure_assistants_with_existing_assistant.py`](azure_assistants_with_existing_assistant.py) | Shows how to work with a pre-existing assistant by providing the assistant ID to the Azure Assistants client. Demonstrates proper cleanup of manually created assistants. |
|
||||
| [`azure_assistants_with_explicit_settings.py`](azure_assistants_with_explicit_settings.py) | Shows how to initialize an agent with a specific assistants client, configuring settings explicitly including endpoint and deployment name. |
|
||||
| [`azure_assistants_with_function_tools.py`](azure_assistants_with_function_tools.py) | Demonstrates how to use function tools with agents. Shows both agent-level tools (defined when creating the agent) and query-level tools (provided with specific queries). |
|
||||
| [`azure_assistants_with_thread.py`](azure_assistants_with_thread.py) | Demonstrates thread management with Azure agents, including automatic thread creation for stateless conversations and explicit thread management for maintaining conversation context across multiple interactions. |
|
||||
| [`azure_chat_client_basic.py`](azure_chat_client_basic.py) | The simplest way to create an agent using `ChatAgent` with `AzureOpenAIChatClient`. Shows both streaming and non-streaming responses for chat-based interactions with Azure OpenAI models. |
|
||||
| [`azure_chat_client_basic.py`](azure_chat_client_basic.py) | The simplest way to create an agent using `Agent` with `AzureOpenAIChatClient`. Shows both streaming and non-streaming responses for chat-based interactions with Azure OpenAI models. |
|
||||
| [`azure_chat_client_with_explicit_settings.py`](azure_chat_client_with_explicit_settings.py) | Shows how to initialize an agent with a specific chat client, configuring settings explicitly including endpoint and deployment name. |
|
||||
| [`azure_chat_client_with_function_tools.py`](azure_chat_client_with_function_tools.py) | Demonstrates how to use function tools with agents. Shows both agent-level tools (defined when creating the agent) and query-level tools (provided with specific queries). |
|
||||
| [`azure_chat_client_with_thread.py`](azure_chat_client_with_thread.py) | Demonstrates thread management with Azure agents, including automatic thread creation for stateless conversations and explicit thread management for maintaining conversation context across multiple interactions. |
|
||||
| [`azure_responses_client_basic.py`](azure_responses_client_basic.py) | The simplest way to create an agent using `ChatAgent` with `AzureOpenAIResponsesClient`. Shows both streaming and non-streaming responses for structured response generation with Azure OpenAI models. |
|
||||
| [`azure_responses_client_basic.py`](azure_responses_client_basic.py) | The simplest way to create an agent using `Agent` with `AzureOpenAIResponsesClient`. Shows both streaming and non-streaming responses for structured response generation with Azure OpenAI models. |
|
||||
| [`azure_responses_client_code_interpreter_files.py`](azure_responses_client_code_interpreter_files.py) | Demonstrates using HostedCodeInterpreterTool with file uploads for data analysis. Shows how to create, upload, and analyze CSV files using Python code execution with Azure OpenAI Responses. |
|
||||
| [`azure_responses_client_image_analysis.py`](azure_responses_client_image_analysis.py) | Shows how to use Azure OpenAI Responses for image analysis and vision tasks. Demonstrates multi-modal messages combining text and image content using remote URLs. |
|
||||
| [`azure_responses_client_with_code_interpreter.py`](azure_responses_client_with_code_interpreter.py) | Shows how to use the HostedCodeInterpreterTool with Azure agents to write and execute Python code. Includes helper methods for accessing code interpreter data from response chunks. |
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import AgentResponseUpdate, ChatAgent, ChatResponseUpdate, HostedCodeInterpreterTool
|
||||
from agent_framework import Agent, AgentResponseUpdate, ChatResponseUpdate, HostedCodeInterpreterTool
|
||||
from agent_framework.azure import AzureOpenAIAssistantsClient
|
||||
from azure.identity import AzureCliCredential
|
||||
from openai.types.beta.threads.runs import (
|
||||
@@ -46,8 +46,8 @@ async def main() -> None:
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
async with Agent(
|
||||
client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful assistant that can write and execute Python code to solve problems.",
|
||||
tools=HostedCodeInterpreterTool(),
|
||||
) as agent:
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@ import os
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent, tool
|
||||
from agent_framework import Agent, tool
|
||||
from agent_framework.azure import AzureOpenAIAssistantsClient
|
||||
from azure.identity import AzureCliCredential, get_bearer_token_provider
|
||||
from openai import AsyncAzureOpenAI
|
||||
@@ -46,8 +46,8 @@ async def main() -> None:
|
||||
)
|
||||
|
||||
try:
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIAssistantsClient(async_client=client, assistant_id=created_assistant.id),
|
||||
async with Agent(
|
||||
client=AzureOpenAIAssistantsClient(async_client=client, assistant_id=created_assistant.id),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent:
|
||||
|
||||
+7
-7
@@ -5,7 +5,7 @@ from datetime import datetime, timezone
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent, tool
|
||||
from agent_framework import Agent, tool
|
||||
from agent_framework.azure import AzureOpenAIAssistantsClient
|
||||
from azure.identity import AzureCliCredential
|
||||
from pydantic import Field
|
||||
@@ -43,8 +43,8 @@ async def tools_on_agent_level() -> None:
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
async with Agent(
|
||||
client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful assistant that can provide weather and time information.",
|
||||
tools=[get_weather, get_time], # Tools defined at agent creation
|
||||
) as agent:
|
||||
@@ -74,8 +74,8 @@ async def tools_on_run_level() -> None:
|
||||
# Agent created without tools
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
async with Agent(
|
||||
client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful assistant.",
|
||||
# No tools defined here
|
||||
) as agent:
|
||||
@@ -105,8 +105,8 @@ async def mixed_tools_example() -> None:
|
||||
# Agent created with some base tools
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
async with Agent(
|
||||
client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
instructions="You are a comprehensive assistant that can help with various information requests.",
|
||||
tools=[get_weather], # Base tool available for all queries
|
||||
) as agent:
|
||||
|
||||
@@ -4,7 +4,7 @@ import asyncio
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import AgentThread, ChatAgent, tool
|
||||
from agent_framework import Agent, AgentThread, tool
|
||||
from agent_framework.azure import AzureOpenAIAssistantsClient
|
||||
from azure.identity import AzureCliCredential
|
||||
from pydantic import Field
|
||||
@@ -33,8 +33,8 @@ async def example_with_automatic_thread_creation() -> None:
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
async with Agent(
|
||||
client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent:
|
||||
@@ -59,8 +59,8 @@ async def example_with_thread_persistence() -> None:
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
async with Agent(
|
||||
client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent:
|
||||
@@ -97,8 +97,8 @@ async def example_with_existing_thread_id() -> None:
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
async with Agent(
|
||||
client=AzureOpenAIAssistantsClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent:
|
||||
@@ -117,8 +117,8 @@ async def example_with_existing_thread_id() -> None:
|
||||
print("\n--- Continuing with the same thread ID in a new agent instance ---")
|
||||
|
||||
# Create a new agent instance but use the existing thread ID
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIAssistantsClient(thread_id=existing_thread_id, credential=AzureCliCredential()),
|
||||
async with Agent(
|
||||
client=AzureOpenAIAssistantsClient(thread_id=existing_thread_id, credential=AzureCliCredential()),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent:
|
||||
|
||||
+7
-7
@@ -5,7 +5,7 @@ from datetime import datetime, timezone
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent, tool
|
||||
from agent_framework import Agent, tool
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
from pydantic import Field
|
||||
@@ -43,8 +43,8 @@ async def tools_on_agent_level() -> None:
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful assistant that can provide weather and time information.",
|
||||
tools=[get_weather, get_time], # Tools defined at agent creation
|
||||
)
|
||||
@@ -75,8 +75,8 @@ async def tools_on_run_level() -> None:
|
||||
# Agent created without tools
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful assistant.",
|
||||
# No tools defined here
|
||||
)
|
||||
@@ -107,8 +107,8 @@ async def mixed_tools_example() -> None:
|
||||
# Agent created with some base tools
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
instructions="You are a comprehensive assistant that can help with various information requests.",
|
||||
tools=[get_weather], # Base tool available for all queries
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ import asyncio
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import AgentThread, ChatAgent, ChatMessageStore, tool
|
||||
from agent_framework import Agent, AgentThread, ChatMessageStore, tool
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
from pydantic import Field
|
||||
@@ -33,8 +33,8 @@ async def example_with_automatic_thread_creation() -> None:
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -60,8 +60,8 @@ async def example_with_thread_persistence() -> None:
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -95,8 +95,8 @@ async def example_with_existing_thread_messages() -> None:
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -117,8 +117,8 @@ async def example_with_existing_thread_messages() -> None:
|
||||
print("\n--- Continuing with the same thread in a new agent instance ---")
|
||||
|
||||
# Create a new agent instance but use the existing thread with its message history
|
||||
new_agent = ChatAgent(
|
||||
chat_client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
new_agent = Agent(
|
||||
client=AzureOpenAIChatClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@ import asyncio
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from agent_framework import ChatAgent, HostedCodeInterpreterTool
|
||||
from agent_framework import Agent, HostedCodeInterpreterTool
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
from azure.identity import AzureCliCredential
|
||||
from openai import AsyncAzureOpenAI
|
||||
@@ -76,8 +76,8 @@ async def main() -> None:
|
||||
temp_file_path, file_id = await create_sample_file_and_upload(openai_client)
|
||||
|
||||
# Create agent using Azure OpenAI Responses client
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(credential=credential),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIResponsesClient(credential=credential),
|
||||
instructions="You are a helpful assistant that can analyze data files using Python code.",
|
||||
tools=HostedCodeInterpreterTool(inputs=[{"file_id": file_id}]),
|
||||
)
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatMessage, Content
|
||||
from agent_framework import Content, Message
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -24,7 +24,7 @@ async def main():
|
||||
)
|
||||
|
||||
# 2. Create a simple message with both text and image content
|
||||
user_message = ChatMessage(
|
||||
user_message = Message(
|
||||
role="user",
|
||||
contents=[
|
||||
Content.from_text(text="What do you see in this image?"),
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatAgent, ChatResponse, HostedCodeInterpreterTool
|
||||
from agent_framework import Agent, ChatResponse, HostedCodeInterpreterTool
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
from azure.identity import AzureCliCredential
|
||||
from openai.types.responses.response import Response as OpenAIResponse
|
||||
@@ -22,8 +22,8 @@ async def main() -> None:
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful assistant that can write and execute Python code to solve problems.",
|
||||
tools=HostedCodeInterpreterTool(),
|
||||
)
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatAgent, Content, HostedFileSearchTool
|
||||
from agent_framework import Agent, Content, HostedFileSearchTool
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -53,8 +53,8 @@ async def main() -> None:
|
||||
|
||||
file_id, vector_store = await create_vector_store(client)
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=client,
|
||||
agent = Agent(
|
||||
client=client,
|
||||
instructions="You are a helpful assistant that can search through files to find information.",
|
||||
tools=[HostedFileSearchTool(inputs=vector_store)],
|
||||
)
|
||||
|
||||
+7
-7
@@ -5,7 +5,7 @@ from datetime import datetime, timezone
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent, tool
|
||||
from agent_framework import Agent, tool
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
from azure.identity import AzureCliCredential
|
||||
from pydantic import Field
|
||||
@@ -43,8 +43,8 @@ async def tools_on_agent_level() -> None:
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful assistant that can provide weather and time information.",
|
||||
tools=[get_weather, get_time], # Tools defined at agent creation
|
||||
)
|
||||
@@ -75,8 +75,8 @@ async def tools_on_run_level() -> None:
|
||||
# Agent created without tools
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful assistant.",
|
||||
# No tools defined here
|
||||
)
|
||||
@@ -107,8 +107,8 @@ async def mixed_tools_example() -> None:
|
||||
# Agent created with some base tools
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
instructions="You are a comprehensive assistant that can help with various information requests.",
|
||||
tools=[get_weather], # Base tool available for all queries
|
||||
)
|
||||
|
||||
+18
-18
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from agent_framework import ChatAgent, HostedMCPTool
|
||||
from agent_framework import Agent, HostedMCPTool
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
|
||||
|
||||
async def handle_approvals_without_thread(query: str, agent: "SupportsAgentRun"):
|
||||
"""When we don't have a thread, we need to ensure we return with the input, approval request and approval."""
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework import Message
|
||||
|
||||
result = await agent.run(query)
|
||||
while len(result.user_input_requests) > 0:
|
||||
@@ -30,10 +30,10 @@ async def handle_approvals_without_thread(query: str, agent: "SupportsAgentRun")
|
||||
f"User Input Request for function from {agent.name}: {user_input_needed.function_call.name}"
|
||||
f" with arguments: {user_input_needed.function_call.arguments}"
|
||||
)
|
||||
new_inputs.append(ChatMessage(role="assistant", contents=[user_input_needed]))
|
||||
new_inputs.append(Message(role="assistant", contents=[user_input_needed]))
|
||||
user_approval = input("Approve function call? (y/n): ")
|
||||
new_inputs.append(
|
||||
ChatMessage(role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")])
|
||||
Message(role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")])
|
||||
)
|
||||
|
||||
result = await agent.run(new_inputs)
|
||||
@@ -42,7 +42,7 @@ async def handle_approvals_without_thread(query: str, agent: "SupportsAgentRun")
|
||||
|
||||
async def handle_approvals_with_thread(query: str, agent: "SupportsAgentRun", thread: "AgentThread"):
|
||||
"""Here we let the thread deal with the previous responses, and we just rerun with the approval."""
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework import Message
|
||||
|
||||
result = await agent.run(query, thread=thread, store=True)
|
||||
while len(result.user_input_requests) > 0:
|
||||
@@ -54,7 +54,7 @@ async def handle_approvals_with_thread(query: str, agent: "SupportsAgentRun", th
|
||||
)
|
||||
user_approval = input("Approve function call? (y/n): ")
|
||||
new_input.append(
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")],
|
||||
)
|
||||
@@ -65,13 +65,13 @@ async def handle_approvals_with_thread(query: str, agent: "SupportsAgentRun", th
|
||||
|
||||
async def handle_approvals_with_thread_streaming(query: str, agent: "SupportsAgentRun", thread: "AgentThread"):
|
||||
"""Here we let the thread deal with the previous responses, and we just rerun with the approval."""
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework import Message
|
||||
|
||||
new_input: list[ChatMessage] = []
|
||||
new_input: list[Message] = []
|
||||
new_input_added = True
|
||||
while new_input_added:
|
||||
new_input_added = False
|
||||
new_input.append(ChatMessage(role="user", text=query))
|
||||
new_input.append(Message(role="user", text=query))
|
||||
async for update in agent.run(new_input, thread=thread, options={"store": True}, stream=True):
|
||||
if update.user_input_requests:
|
||||
for user_input_needed in update.user_input_requests:
|
||||
@@ -81,7 +81,7 @@ async def handle_approvals_with_thread_streaming(query: str, agent: "SupportsAge
|
||||
)
|
||||
user_approval = input("Approve function call? (y/n): ")
|
||||
new_input.append(
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")]
|
||||
)
|
||||
)
|
||||
@@ -96,8 +96,8 @@ async def run_hosted_mcp_without_thread_and_specific_approval() -> None:
|
||||
credential = AzureCliCredential()
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(
|
||||
async with Agent(
|
||||
client=AzureOpenAIResponsesClient(
|
||||
credential=credential,
|
||||
),
|
||||
name="DocsAgent",
|
||||
@@ -129,8 +129,8 @@ async def run_hosted_mcp_without_approval() -> None:
|
||||
credential = AzureCliCredential()
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(
|
||||
async with Agent(
|
||||
client=AzureOpenAIResponsesClient(
|
||||
credential=credential,
|
||||
),
|
||||
name="DocsAgent",
|
||||
@@ -163,8 +163,8 @@ async def run_hosted_mcp_with_thread() -> None:
|
||||
credential = AzureCliCredential()
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(
|
||||
async with Agent(
|
||||
client=AzureOpenAIResponsesClient(
|
||||
credential=credential,
|
||||
),
|
||||
name="DocsAgent",
|
||||
@@ -196,8 +196,8 @@ async def run_hosted_mcp_with_thread_streaming() -> None:
|
||||
credential = AzureCliCredential()
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
async with ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(
|
||||
async with Agent(
|
||||
client=AzureOpenAIResponsesClient(
|
||||
credential=credential,
|
||||
),
|
||||
name="DocsAgent",
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from agent_framework import ChatAgent, MCPStreamableHTTPTool
|
||||
from agent_framework import Agent, MCPStreamableHTTPTool
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -37,7 +37,7 @@ async def main():
|
||||
credential=credential,
|
||||
)
|
||||
|
||||
agent: ChatAgent = responses_client.as_agent(
|
||||
agent: Agent = responses_client.as_agent(
|
||||
name="DocsAgent",
|
||||
instructions=("You are a helpful assistant that can help with Microsoft documentation questions."),
|
||||
)
|
||||
|
||||
+9
-9
@@ -4,7 +4,7 @@ import asyncio
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import AgentThread, ChatAgent, tool
|
||||
from agent_framework import Agent, AgentThread, tool
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
from azure.identity import AzureCliCredential
|
||||
from pydantic import Field
|
||||
@@ -33,8 +33,8 @@ async def example_with_automatic_thread_creation() -> None:
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -62,8 +62,8 @@ async def example_with_thread_persistence_in_memory() -> None:
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -103,8 +103,8 @@ async def example_with_existing_thread_id() -> None:
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -125,8 +125,8 @@ async def example_with_existing_thread_id() -> None:
|
||||
if existing_thread_id:
|
||||
print("\n--- Continuing with the same thread ID in a new agent instance ---")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
agent = Agent(
|
||||
client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ This folder contains examples demonstrating how to implement custom agents and c
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| [`custom_agent.py`](custom_agent.py) | Shows how to create custom agents by extending the `BaseAgent` class. Demonstrates the `EchoAgent` implementation with both streaming and non-streaming responses, proper thread management, and message history handling. |
|
||||
| [`custom_chat_client.py`](../../chat_client/custom_chat_client.py) | Demonstrates how to create custom chat clients by extending the `BaseChatClient` class. Shows a `EchoingChatClient` implementation and how to integrate it with `ChatAgent` using the `as_agent()` method. |
|
||||
| [`custom_chat_client.py`](../../chat_client/custom_chat_client.py) | Demonstrates how to create custom chat clients by extending the `BaseChatClient` class. Shows a `EchoingChatClient` implementation and how to integrate it with `Agent` using the `as_agent()` method. |
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
@@ -20,7 +20,7 @@ This folder contains examples demonstrating how to implement custom agents and c
|
||||
### Custom Chat Clients
|
||||
- Custom chat clients allow you to integrate any backend service or create new LLM providers
|
||||
- You must implement `_inner_get_response()` with a stream parameter to handle both streaming and non-streaming responses
|
||||
- Custom chat clients can be used with `ChatAgent` to leverage all agent framework features
|
||||
- Custom chat clients can be used with `Agent` to leverage all agent framework features
|
||||
- Use the `as_agent()` method to easily create agents from your custom chat clients
|
||||
|
||||
Both approaches allow you to extend the framework for your specific use cases while maintaining compatibility with the broader Agent Framework ecosystem.
|
||||
|
||||
@@ -9,8 +9,8 @@ from agent_framework import (
|
||||
AgentResponseUpdate,
|
||||
AgentThread,
|
||||
BaseAgent,
|
||||
ChatMessage,
|
||||
Content,
|
||||
Message,
|
||||
Role,
|
||||
normalize_messages,
|
||||
)
|
||||
@@ -57,7 +57,7 @@ class EchoAgent(BaseAgent):
|
||||
|
||||
def run(
|
||||
self,
|
||||
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
|
||||
messages: str | Message | list[str] | list[Message] | None = None,
|
||||
*,
|
||||
stream: bool = False,
|
||||
thread: AgentThread | None = None,
|
||||
@@ -81,7 +81,7 @@ class EchoAgent(BaseAgent):
|
||||
|
||||
async def _run(
|
||||
self,
|
||||
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
|
||||
messages: str | Message | list[str] | list[Message] | None = None,
|
||||
*,
|
||||
thread: AgentThread | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -91,11 +91,9 @@ class EchoAgent(BaseAgent):
|
||||
normalized_messages = normalize_messages(messages)
|
||||
|
||||
if not normalized_messages:
|
||||
response_message = ChatMessage(
|
||||
response_message = Message(
|
||||
role=Role.ASSISTANT,
|
||||
contents=[
|
||||
Content.from_text(text="Hello! I'm a custom echo agent. Send me a message and I'll echo it back.")
|
||||
],
|
||||
contents=[Content.from_text(text="Hello! I'm a custom echo agent. Send me a message and I'll echo it back.")],
|
||||
)
|
||||
else:
|
||||
# For simplicity, echo the last user message
|
||||
@@ -105,7 +103,7 @@ class EchoAgent(BaseAgent):
|
||||
else:
|
||||
echo_text = f"{self.echo_prefix}[Non-text message received]"
|
||||
|
||||
response_message = ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(text=echo_text)])
|
||||
response_message = Message(role=Role.ASSISTANT, contents=[Content.from_text(text=echo_text)])
|
||||
|
||||
# Notify the thread of new messages if provided
|
||||
if thread is not None:
|
||||
@@ -115,7 +113,7 @@ class EchoAgent(BaseAgent):
|
||||
|
||||
async def _run_stream(
|
||||
self,
|
||||
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
|
||||
messages: str | Message | list[str] | list[Message] | None = None,
|
||||
*,
|
||||
thread: AgentThread | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -150,7 +148,7 @@ class EchoAgent(BaseAgent):
|
||||
|
||||
# Notify the thread of the complete response if provided
|
||||
if thread is not None:
|
||||
complete_response = ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(text=response_text)])
|
||||
complete_response = Message(role=Role.ASSISTANT, contents=[Content.from_text(text=response_text)])
|
||||
await self._notify_thread_of_new_messages(thread, normalized_messages, complete_response)
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatMessage, Content
|
||||
from agent_framework import Content, Message
|
||||
from agent_framework.ollama import OllamaChatClient
|
||||
|
||||
"""
|
||||
@@ -32,7 +32,7 @@ async def test_image() -> None:
|
||||
|
||||
image_uri = create_sample_image()
|
||||
|
||||
message = ChatMessage(
|
||||
message = Message(
|
||||
role="user",
|
||||
contents=[
|
||||
Content.from_text(text="What's in this image?"),
|
||||
|
||||
@@ -15,14 +15,14 @@ This folder contains examples demonstrating different ways to create and use age
|
||||
| [`openai_assistants_with_function_tools.py`](openai_assistants_with_function_tools.py) | Function tools with `OpenAIAssistantProvider` at both agent-level and query-level. |
|
||||
| [`openai_assistants_with_response_format.py`](openai_assistants_with_response_format.py) | Structured outputs with `OpenAIAssistantProvider` using Pydantic models. |
|
||||
| [`openai_assistants_with_thread.py`](openai_assistants_with_thread.py) | Thread management with `OpenAIAssistantProvider` for conversation context persistence. |
|
||||
| [`openai_chat_client_basic.py`](openai_chat_client_basic.py) | The simplest way to create an agent using `ChatAgent` with `OpenAIChatClient`. Shows both streaming and non-streaming responses for chat-based interactions with OpenAI models. |
|
||||
| [`openai_chat_client_basic.py`](openai_chat_client_basic.py) | The simplest way to create an agent using `Agent` with `OpenAIChatClient`. Shows both streaming and non-streaming responses for chat-based interactions with OpenAI models. |
|
||||
| [`openai_chat_client_with_explicit_settings.py`](openai_chat_client_with_explicit_settings.py) | Shows how to initialize an agent with a specific chat client, configuring settings explicitly including API key and model ID. |
|
||||
| [`openai_chat_client_with_function_tools.py`](openai_chat_client_with_function_tools.py) | Demonstrates how to use function tools with agents. Shows both agent-level tools (defined when creating the agent) and query-level tools (provided with specific queries). |
|
||||
| [`openai_chat_client_with_local_mcp.py`](openai_chat_client_with_local_mcp.py) | Shows how to integrate OpenAI agents with local Model Context Protocol (MCP) servers for enhanced functionality and tool integration. |
|
||||
| [`openai_chat_client_with_thread.py`](openai_chat_client_with_thread.py) | Demonstrates thread management with OpenAI agents, including automatic thread creation for stateless conversations and explicit thread management for maintaining conversation context across multiple interactions. |
|
||||
| [`openai_chat_client_with_web_search.py`](openai_chat_client_with_web_search.py) | Shows how to use web search capabilities with OpenAI agents to retrieve and use information from the internet in responses. |
|
||||
| [`openai_chat_client_with_runtime_json_schema.py`](openai_chat_client_with_runtime_json_schema.py) | Shows how to supply a runtime JSON Schema via `additional_chat_options` for structured output without defining a Pydantic model. |
|
||||
| [`openai_responses_client_basic.py`](openai_responses_client_basic.py) | The simplest way to create an agent using `ChatAgent` with `OpenAIResponsesClient`. Shows both streaming and non-streaming responses for structured response generation with OpenAI models. |
|
||||
| [`openai_responses_client_basic.py`](openai_responses_client_basic.py) | The simplest way to create an agent using `Agent` with `OpenAIResponsesClient`. Shows both streaming and non-streaming responses for structured response generation with OpenAI models. |
|
||||
| [`openai_responses_client_image_analysis.py`](openai_responses_client_image_analysis.py) | Demonstrates how to use vision capabilities with agents to analyze images. |
|
||||
| [`openai_responses_client_image_generation.py`](openai_responses_client_image_generation.py) | Demonstrates how to use image generation capabilities with OpenAI agents to create images based on text descriptions. Requires PIL (Pillow) for image display. |
|
||||
| [`openai_responses_client_reasoning.py`](openai_responses_client_reasoning.py) | Demonstrates how to use reasoning capabilities with OpenAI agents, showing how the agent can provide detailed reasoning for its responses. |
|
||||
|
||||
+7
-7
@@ -5,7 +5,7 @@ from datetime import datetime, timezone
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent, tool
|
||||
from agent_framework import Agent, tool
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
from pydantic import Field
|
||||
|
||||
@@ -40,8 +40,8 @@ async def tools_on_agent_level() -> None:
|
||||
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIChatClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIChatClient(),
|
||||
instructions="You are a helpful assistant that can provide weather and time information.",
|
||||
tools=[get_weather, get_time], # Tools defined at agent creation
|
||||
)
|
||||
@@ -70,8 +70,8 @@ async def tools_on_run_level() -> None:
|
||||
print("=== Tools Passed to Run Method ===")
|
||||
|
||||
# Agent created without tools
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIChatClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIChatClient(),
|
||||
instructions="You are a helpful assistant.",
|
||||
# No tools defined here
|
||||
)
|
||||
@@ -100,8 +100,8 @@ async def mixed_tools_example() -> None:
|
||||
print("=== Mixed Tools Example (Agent + Run Method) ===")
|
||||
|
||||
# Agent created with some base tools
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIChatClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIChatClient(),
|
||||
instructions="You are a comprehensive assistant that can help with various information requests.",
|
||||
tools=[get_weather], # Base tool available for all queries
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatAgent, MCPStreamableHTTPTool
|
||||
from agent_framework import Agent, MCPStreamableHTTPTool
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
|
||||
"""
|
||||
@@ -29,8 +29,8 @@ async def mcp_tools_on_run_level() -> None:
|
||||
name="Microsoft Learn MCP",
|
||||
url="https://learn.microsoft.com/api/mcp",
|
||||
) as mcp_server,
|
||||
ChatAgent(
|
||||
chat_client=OpenAIChatClient(),
|
||||
Agent(
|
||||
client=OpenAIChatClient(),
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
) as agent,
|
||||
|
||||
@@ -4,7 +4,7 @@ import asyncio
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import AgentThread, ChatAgent, ChatMessageStore, tool
|
||||
from agent_framework import Agent, AgentThread, ChatMessageStore, tool
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
from pydantic import Field
|
||||
|
||||
@@ -30,8 +30,8 @@ async def example_with_automatic_thread_creation() -> None:
|
||||
"""Example showing automatic thread creation (service-managed thread)."""
|
||||
print("=== Automatic Thread Creation Example ===")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIChatClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIChatClient(),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -55,8 +55,8 @@ async def example_with_thread_persistence() -> None:
|
||||
print("=== Thread Persistence Example ===")
|
||||
print("Using the same thread across multiple conversations to maintain context.\n")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIChatClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIChatClient(),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -88,8 +88,8 @@ async def example_with_existing_thread_messages() -> None:
|
||||
"""Example showing how to work with existing thread messages for OpenAI."""
|
||||
print("=== Existing Thread Messages Example ===")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIChatClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIChatClient(),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -110,8 +110,8 @@ async def example_with_existing_thread_messages() -> None:
|
||||
print("\n--- Continuing with the same thread in a new agent instance ---")
|
||||
|
||||
# Create a new agent instance but use the existing thread with its message history
|
||||
new_agent = ChatAgent(
|
||||
chat_client=OpenAIChatClient(),
|
||||
new_agent = Agent(
|
||||
client=OpenAIChatClient(),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatAgent, HostedWebSearchTool
|
||||
from agent_framework import Agent, HostedWebSearchTool
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
|
||||
"""
|
||||
@@ -22,8 +22,8 @@ async def main() -> None:
|
||||
}
|
||||
}
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIChatClient(model_id="gpt-4o-search-preview"),
|
||||
agent = Agent(
|
||||
client=OpenAIChatClient(model_id="gpt-4o-search-preview"),
|
||||
instructions="You are a helpful assistant that can search the web for current information.",
|
||||
tools=[HostedWebSearchTool(additional_properties=additional_properties)],
|
||||
)
|
||||
|
||||
@@ -6,11 +6,12 @@ from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import (
|
||||
ChatAgent,
|
||||
Agent,
|
||||
ChatContext,
|
||||
ChatMessage,
|
||||
ChatResponse,
|
||||
Message,
|
||||
MiddlewareTermination,
|
||||
Role,
|
||||
chat_middleware,
|
||||
tool,
|
||||
)
|
||||
@@ -46,8 +47,8 @@ async def security_and_override_middleware(
|
||||
# Override the response instead of calling AI
|
||||
context.result = ChatResponse(
|
||||
messages=[
|
||||
ChatMessage(
|
||||
role="assistant",
|
||||
Message(
|
||||
role=Role.ASSISTANT,
|
||||
text="I cannot process requests containing sensitive information. "
|
||||
"Please rephrase your question without including passwords, secrets, or other "
|
||||
"sensitive data.",
|
||||
@@ -55,8 +56,8 @@ async def security_and_override_middleware(
|
||||
]
|
||||
)
|
||||
|
||||
# Set terminate flag to stop execution
|
||||
raise MiddlewareTermination
|
||||
# Terminate middleware execution with the blocked response
|
||||
raise MiddlewareTermination(result=context.result)
|
||||
|
||||
# Continue to next middleware or AI execution
|
||||
await call_next(context)
|
||||
@@ -79,8 +80,8 @@ async def non_streaming_example() -> None:
|
||||
"""Example of non-streaming response (get the complete result at once)."""
|
||||
print("=== Non-streaming Response Example ===")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -95,8 +96,8 @@ async def streaming_example() -> None:
|
||||
"""Example of streaming response (get results as they are generated)."""
|
||||
print("=== Streaming Response Example ===")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(
|
||||
middleware=[security_and_override_middleware],
|
||||
),
|
||||
instructions="You are a helpful weather agent.",
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatMessage, Content
|
||||
from agent_framework import Content, Message
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
|
||||
"""
|
||||
@@ -23,7 +23,7 @@ async def main():
|
||||
)
|
||||
|
||||
# 2. Create a simple message with both text and image content
|
||||
user_message = ChatMessage(
|
||||
user_message = Message(
|
||||
role="user",
|
||||
contents=[
|
||||
Content.from_text(text="What do you see in this image?"),
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
|
||||
from agent_framework import (
|
||||
ChatAgent,
|
||||
Agent,
|
||||
HostedCodeInterpreterTool,
|
||||
)
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
@@ -20,8 +20,8 @@ async def main() -> None:
|
||||
"""Example showing how to use the HostedCodeInterpreterTool with OpenAI Responses."""
|
||||
print("=== OpenAI Responses Agent with Code Interpreter Example ===")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
instructions="You are a helpful assistant that can write and execute Python code to solve problems.",
|
||||
tools=HostedCodeInterpreterTool(),
|
||||
)
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@ import asyncio
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from agent_framework import ChatAgent, HostedCodeInterpreterTool
|
||||
from agent_framework import Agent, HostedCodeInterpreterTool
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
from openai import AsyncOpenAI
|
||||
|
||||
@@ -66,8 +66,8 @@ async def main() -> None:
|
||||
temp_file_path, file_id = await create_sample_file_and_upload(openai_client)
|
||||
|
||||
# Create agent using OpenAI Responses client
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
instructions="You are a helpful assistant that can analyze data files using Python code.",
|
||||
tools=HostedCodeInterpreterTool(inputs=[{"file_id": file_id}]),
|
||||
)
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatAgent, Content, HostedFileSearchTool
|
||||
from agent_framework import Agent, Content, HostedFileSearchTool
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
|
||||
"""
|
||||
@@ -47,8 +47,8 @@ async def main() -> None:
|
||||
print(f"User: {message}")
|
||||
file_id, vector_store = await create_vector_store(client)
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=client,
|
||||
agent = Agent(
|
||||
client=client,
|
||||
instructions="You are a helpful assistant that can search through files to find information.",
|
||||
tools=[HostedFileSearchTool(inputs=vector_store)],
|
||||
)
|
||||
|
||||
+7
-7
@@ -5,7 +5,7 @@ from datetime import datetime, timezone
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent, tool
|
||||
from agent_framework import Agent, tool
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
from pydantic import Field
|
||||
|
||||
@@ -40,8 +40,8 @@ async def tools_on_agent_level() -> None:
|
||||
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
instructions="You are a helpful assistant that can provide weather and time information.",
|
||||
tools=[get_weather, get_time], # Tools defined at agent creation
|
||||
)
|
||||
@@ -70,8 +70,8 @@ async def tools_on_run_level() -> None:
|
||||
print("=== Tools Passed to Run Method ===")
|
||||
|
||||
# Agent created without tools
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
instructions="You are a helpful assistant.",
|
||||
# No tools defined here
|
||||
)
|
||||
@@ -100,8 +100,8 @@ async def mixed_tools_example() -> None:
|
||||
print("=== Mixed Tools Example (Agent + Run Method) ===")
|
||||
|
||||
# Agent created with some base tools
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
instructions="You are a comprehensive assistant that can help with various information requests.",
|
||||
tools=[get_weather], # Base tool available for all queries
|
||||
)
|
||||
|
||||
+18
-18
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from agent_framework import ChatAgent, HostedMCPTool
|
||||
from agent_framework import Agent, HostedMCPTool
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
|
||||
"""
|
||||
@@ -19,7 +19,7 @@ if TYPE_CHECKING:
|
||||
|
||||
async def handle_approvals_without_thread(query: str, agent: "SupportsAgentRun"):
|
||||
"""When we don't have a thread, we need to ensure we return with the input, approval request and approval."""
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework import Message
|
||||
|
||||
result = await agent.run(query)
|
||||
while len(result.user_input_requests) > 0:
|
||||
@@ -29,10 +29,10 @@ async def handle_approvals_without_thread(query: str, agent: "SupportsAgentRun")
|
||||
f"User Input Request for function from {agent.name}: {user_input_needed.function_call.name}"
|
||||
f" with arguments: {user_input_needed.function_call.arguments}"
|
||||
)
|
||||
new_inputs.append(ChatMessage(role="assistant", contents=[user_input_needed]))
|
||||
new_inputs.append(Message(role="assistant", contents=[user_input_needed]))
|
||||
user_approval = input("Approve function call? (y/n): ")
|
||||
new_inputs.append(
|
||||
ChatMessage(role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")])
|
||||
Message(role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")])
|
||||
)
|
||||
|
||||
result = await agent.run(new_inputs)
|
||||
@@ -41,7 +41,7 @@ async def handle_approvals_without_thread(query: str, agent: "SupportsAgentRun")
|
||||
|
||||
async def handle_approvals_with_thread(query: str, agent: "SupportsAgentRun", thread: "AgentThread"):
|
||||
"""Here we let the thread deal with the previous responses, and we just rerun with the approval."""
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework import Message
|
||||
|
||||
result = await agent.run(query, thread=thread, store=True)
|
||||
while len(result.user_input_requests) > 0:
|
||||
@@ -53,7 +53,7 @@ async def handle_approvals_with_thread(query: str, agent: "SupportsAgentRun", th
|
||||
)
|
||||
user_approval = input("Approve function call? (y/n): ")
|
||||
new_input.append(
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")],
|
||||
)
|
||||
@@ -64,13 +64,13 @@ async def handle_approvals_with_thread(query: str, agent: "SupportsAgentRun", th
|
||||
|
||||
async def handle_approvals_with_thread_streaming(query: str, agent: "SupportsAgentRun", thread: "AgentThread"):
|
||||
"""Here we let the thread deal with the previous responses, and we just rerun with the approval."""
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework import Message
|
||||
|
||||
new_input: list[ChatMessage] = []
|
||||
new_input: list[Message] = []
|
||||
new_input_added = True
|
||||
while new_input_added:
|
||||
new_input_added = False
|
||||
new_input.append(ChatMessage(role="user", text=query))
|
||||
new_input.append(Message(role="user", text=query))
|
||||
async for update in agent.run(new_input, thread=thread, stream=True, options={"store": True}):
|
||||
if update.user_input_requests:
|
||||
for user_input_needed in update.user_input_requests:
|
||||
@@ -80,7 +80,7 @@ async def handle_approvals_with_thread_streaming(query: str, agent: "SupportsAge
|
||||
)
|
||||
user_approval = input("Approve function call? (y/n): ")
|
||||
new_input.append(
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user", contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")]
|
||||
)
|
||||
)
|
||||
@@ -95,8 +95,8 @@ async def run_hosted_mcp_without_thread_and_specific_approval() -> None:
|
||||
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
async with ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
async with Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
tools=HostedMCPTool(
|
||||
@@ -126,8 +126,8 @@ async def run_hosted_mcp_without_approval() -> None:
|
||||
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
async with ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
async with Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
tools=HostedMCPTool(
|
||||
@@ -158,8 +158,8 @@ async def run_hosted_mcp_with_thread() -> None:
|
||||
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
async with ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
async with Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
tools=HostedMCPTool(
|
||||
@@ -189,8 +189,8 @@ async def run_hosted_mcp_with_thread_streaming() -> None:
|
||||
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
async with ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
async with Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
tools=HostedMCPTool(
|
||||
|
||||
+5
-5
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatAgent, MCPStreamableHTTPTool
|
||||
from agent_framework import Agent, MCPStreamableHTTPTool
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
|
||||
"""
|
||||
@@ -22,8 +22,8 @@ async def streaming_with_mcp(show_raw_stream: bool = False) -> None:
|
||||
print("=== Tools Defined on Agent Level ===")
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
async with ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
async with Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
tools=MCPStreamableHTTPTool( # Tools defined at agent creation
|
||||
@@ -60,8 +60,8 @@ async def run_with_mcp() -> None:
|
||||
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
async with ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
async with Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
tools=MCPStreamableHTTPTool( # Tools defined at agent creation
|
||||
|
||||
@@ -4,7 +4,7 @@ import asyncio
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import AgentThread, ChatAgent, tool
|
||||
from agent_framework import Agent, AgentThread, tool
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
from pydantic import Field
|
||||
|
||||
@@ -30,8 +30,8 @@ async def example_with_automatic_thread_creation() -> None:
|
||||
"""Example showing automatic thread creation."""
|
||||
print("=== Automatic Thread Creation Example ===")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -57,8 +57,8 @@ async def example_with_thread_persistence_in_memory() -> None:
|
||||
"""
|
||||
print("=== Thread Persistence Example (In-Memory) ===")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -96,8 +96,8 @@ async def example_with_existing_thread_id() -> None:
|
||||
# First, create a conversation and capture the thread ID
|
||||
existing_thread_id = None
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
@@ -117,8 +117,8 @@ async def example_with_existing_thread_id() -> None:
|
||||
if existing_thread_id:
|
||||
print("\n--- Continuing with the same thread ID in a new agent instance ---")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
)
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatAgent, HostedWebSearchTool
|
||||
from agent_framework import Agent, HostedWebSearchTool
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
|
||||
"""
|
||||
@@ -22,8 +22,8 @@ async def main() -> None:
|
||||
}
|
||||
}
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
instructions="You are a helpful assistant that can search the web for current information.",
|
||||
tools=[HostedWebSearchTool(additional_properties=additional_properties)],
|
||||
)
|
||||
|
||||
@@ -76,8 +76,8 @@ Expected response:
|
||||
{
|
||||
"status": "healthy",
|
||||
"agents": [
|
||||
{"name": "WeatherAgent", "type": "ChatAgent"},
|
||||
{"name": "MathAgent", "type": "ChatAgent"}
|
||||
{"name": "WeatherAgent", "type": "Agent"},
|
||||
{"name": "MathAgent", "type": "Agent"}
|
||||
],
|
||||
"agent_count": 2
|
||||
}
|
||||
|
||||
@@ -56,15 +56,15 @@ def calculate_tip(bill_amount: float, tip_percentage: float = 15.0) -> dict[str,
|
||||
|
||||
|
||||
# 1. Create multiple agents, each with its own instruction set and tools.
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
weather_agent = chat_client.as_agent(
|
||||
weather_agent = client.as_agent(
|
||||
name="WeatherAgent",
|
||||
instructions="You are a helpful weather assistant. Provide current weather information.",
|
||||
tools=[get_weather],
|
||||
)
|
||||
|
||||
math_agent = chat_client.as_agent(
|
||||
math_agent = client.as_agent(
|
||||
name="MathAgent",
|
||||
instructions="You are a helpful math assistant. Help users with calculations like tip calculations.",
|
||||
tools=[calculate_tip],
|
||||
|
||||
+3
-3
@@ -30,14 +30,14 @@ CHEMIST_AGENT_NAME = "ChemistAgent"
|
||||
|
||||
# 2. Instantiate both agents that the orchestration will run concurrently.
|
||||
def _create_agents() -> list[Any]:
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
physicist = chat_client.as_agent(
|
||||
physicist = client.as_agent(
|
||||
name=PHYSICIST_AGENT_NAME,
|
||||
instructions="You are an expert in physics. You answer questions from a physics perspective.",
|
||||
)
|
||||
|
||||
chemist = chat_client.as_agent(
|
||||
chemist = client.as_agent(
|
||||
name=CHEMIST_AGENT_NAME,
|
||||
instructions="You are an expert in chemistry. You answer questions from a chemistry perspective.",
|
||||
)
|
||||
|
||||
+3
-3
@@ -45,14 +45,14 @@ class EmailPayload(BaseModel):
|
||||
|
||||
# 2. Instantiate both agents so they can be registered with AgentFunctionApp.
|
||||
def _create_agents() -> list[Any]:
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
spam_agent = chat_client.as_agent(
|
||||
spam_agent = client.as_agent(
|
||||
name=SPAM_AGENT_NAME,
|
||||
instructions="You are a spam detection assistant that identifies spam emails.",
|
||||
)
|
||||
|
||||
email_agent = chat_client.as_agent(
|
||||
email_agent = client.as_agent(
|
||||
name=EMAIL_AGENT_NAME,
|
||||
instructions="You are an email assistant that helps users draft responses to emails with professionalism.",
|
||||
)
|
||||
|
||||
@@ -142,20 +142,20 @@ The sample shows how to enable MCP tool triggers with flexible agent configurati
|
||||
from agent_framework.azure import AgentFunctionApp, AzureOpenAIChatClient
|
||||
|
||||
# Create Azure OpenAI Chat Client
|
||||
chat_client = AzureOpenAIChatClient()
|
||||
client = AzureOpenAIChatClient()
|
||||
|
||||
# Define agents with different roles
|
||||
joker_agent = chat_client.as_agent(
|
||||
joker_agent = client.as_agent(
|
||||
name="Joker",
|
||||
instructions="You are good at telling jokes.",
|
||||
)
|
||||
|
||||
stock_agent = chat_client.as_agent(
|
||||
stock_agent = client.as_agent(
|
||||
name="StockAdvisor",
|
||||
instructions="Check stock prices.",
|
||||
)
|
||||
|
||||
plant_agent = chat_client.as_agent(
|
||||
plant_agent = client.as_agent(
|
||||
name="PlantAdvisor",
|
||||
instructions="Recommend plants.",
|
||||
description="Get plant recommendations.",
|
||||
|
||||
@@ -28,23 +28,23 @@ from agent_framework.azure import AgentFunctionApp, AzureOpenAIChatClient
|
||||
|
||||
# Create Azure OpenAI Chat Client
|
||||
# This uses AzureCliCredential for authentication (requires 'az login')
|
||||
chat_client = AzureOpenAIChatClient()
|
||||
client = AzureOpenAIChatClient()
|
||||
|
||||
# Define three AI agents with different roles
|
||||
# Agent 1: Joker - HTTP trigger only (default)
|
||||
agent1 = chat_client.as_agent(
|
||||
agent1 = client.as_agent(
|
||||
name="Joker",
|
||||
instructions="You are good at telling jokes.",
|
||||
)
|
||||
|
||||
# Agent 2: StockAdvisor - MCP tool trigger only
|
||||
agent2 = chat_client.as_agent(
|
||||
agent2 = client.as_agent(
|
||||
name="StockAdvisor",
|
||||
instructions="Check stock prices.",
|
||||
)
|
||||
|
||||
# Agent 3: PlantAdvisor - Both HTTP and MCP tool triggers
|
||||
agent3 = chat_client.as_agent(
|
||||
agent3 = client.as_agent(
|
||||
name="PlantAdvisor",
|
||||
instructions="Recommend plants.",
|
||||
description="Get plant recommendations.",
|
||||
|
||||
@@ -14,7 +14,7 @@ This folder contains simple examples demonstrating direct usage of various chat
|
||||
| [`openai_assistants_client.py`](openai_assistants_client.py) | Direct usage of OpenAI Assistants Client for basic chat interactions with OpenAI assistants. |
|
||||
| [`openai_chat_client.py`](openai_chat_client.py) | Direct usage of OpenAI Chat Client for chat interactions with OpenAI models. |
|
||||
| [`openai_responses_client.py`](openai_responses_client.py) | Direct usage of OpenAI Responses Client for structured response generation with OpenAI models. |
|
||||
| [`custom_chat_client.py`](custom_chat_client.py) | Demonstrates how to create custom chat clients by extending the `BaseChatClient` class. Shows a `EchoingChatClient` implementation and how to integrate it with `ChatAgent` using the `as_agent()` method. |
|
||||
| [`custom_chat_client.py`](custom_chat_client.py) | Demonstrates how to create custom chat clients by extending the `BaseChatClient` class. Shows a `EchoingChatClient` implementation and how to integrate it with `Agent` using the `as_agent()` method. |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
|
||||
@@ -21,10 +21,10 @@ async def main() -> None:
|
||||
- OpenAI model ID: Use "model_id" parameter or "OPENAI_CHAT_MODEL_ID" environment variable
|
||||
- OpenAI API key: Use "api_key" parameter or "OPENAI_API_KEY" environment variable
|
||||
"""
|
||||
chat_client = OpenAIChatClient()
|
||||
client = OpenAIChatClient()
|
||||
|
||||
try:
|
||||
task = asyncio.create_task(chat_client.get_response(messages=["Tell me a fantasy story."]))
|
||||
task = asyncio.create_task(client.get_response(messages=["Tell me a fantasy story."]))
|
||||
await asyncio.sleep(1)
|
||||
task.cancel()
|
||||
await task
|
||||
|
||||
@@ -8,12 +8,12 @@ from typing import Any, ClassVar, Generic
|
||||
|
||||
from agent_framework import (
|
||||
BaseChatClient,
|
||||
ChatMessage,
|
||||
ChatMiddlewareLayer,
|
||||
ChatResponse,
|
||||
ChatResponseUpdate,
|
||||
Content,
|
||||
FunctionInvocationLayer,
|
||||
Message,
|
||||
ResponseStream,
|
||||
Role,
|
||||
)
|
||||
@@ -61,7 +61,7 @@ class EchoingChatClient(BaseChatClient[OptionsCoT], Generic[OptionsCoT]):
|
||||
def _inner_get_response(
|
||||
self,
|
||||
*,
|
||||
messages: Sequence[ChatMessage],
|
||||
messages: Sequence[Message],
|
||||
stream: bool = False,
|
||||
options: Mapping[str, Any],
|
||||
**kwargs: Any,
|
||||
@@ -82,7 +82,7 @@ class EchoingChatClient(BaseChatClient[OptionsCoT], Generic[OptionsCoT]):
|
||||
else:
|
||||
response_text = f"{self.prefix} [No text message found]"
|
||||
|
||||
response_message = ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(response_text)])
|
||||
response_message = Message(role=Role.ASSISTANT, contents=[Content.from_text(response_text)])
|
||||
|
||||
response = ChatResponse(
|
||||
messages=[response_message],
|
||||
@@ -124,7 +124,7 @@ class EchoingChatClientWithLayers( # type: ignore[misc,type-var]
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Demonstrates how to implement and use a custom chat client with ChatAgent."""
|
||||
"""Demonstrates how to implement and use a custom chat client with Agent."""
|
||||
print("=== Custom Chat Client Example ===\n")
|
||||
|
||||
# Create the custom chat client
|
||||
|
||||
@@ -139,14 +139,14 @@ Different agents with isolated or shared memory configurations.
|
||||
To create a custom context provider, implement the `ContextProvider` protocol:
|
||||
|
||||
```python
|
||||
from agent_framework import ContextProvider, Context, ChatMessage
|
||||
from agent_framework import ContextProvider, Context, Message
|
||||
from collections.abc import MutableSequence, Sequence
|
||||
from typing import Any
|
||||
|
||||
class MyContextProvider(ContextProvider):
|
||||
async def invoking(
|
||||
self,
|
||||
messages: ChatMessage | MutableSequence[ChatMessage],
|
||||
messages: Message | MutableSequence[Message],
|
||||
**kwargs: Any
|
||||
) -> Context:
|
||||
"""Provide context before the agent processes the request."""
|
||||
@@ -155,8 +155,8 @@ class MyContextProvider(ContextProvider):
|
||||
|
||||
async def invoked(
|
||||
self,
|
||||
request_messages: ChatMessage | Sequence[ChatMessage],
|
||||
response_messages: ChatMessage | Sequence[ChatMessage] | None = None,
|
||||
request_messages: Message | Sequence[Message],
|
||||
response_messages: Message | Sequence[Message] | None = None,
|
||||
invoke_exception: Exception | None = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
|
||||
@@ -17,7 +17,7 @@ from contextlib import AsyncExitStack
|
||||
from types import TracebackType
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from agent_framework import ChatAgent, ChatMessage, Context, ContextProvider
|
||||
from agent_framework import Agent, Context, ContextProvider, Message
|
||||
from agent_framework.azure import AzureAIClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
@@ -47,7 +47,7 @@ class AggregateContextProvider(ContextProvider):
|
||||
Examples:
|
||||
.. code-block:: python
|
||||
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework import Agent
|
||||
|
||||
# Create multiple context providers
|
||||
provider1 = CustomContextProvider1()
|
||||
@@ -58,7 +58,7 @@ class AggregateContextProvider(ContextProvider):
|
||||
aggregate = AggregateContextProvider([provider1, provider2, provider3])
|
||||
|
||||
# Pass the aggregate to the agent
|
||||
agent = ChatAgent(chat_client=client, name="assistant", context_provider=aggregate)
|
||||
agent = Agent(client=client, name="assistant", context_provider=aggregate)
|
||||
|
||||
# You can also add more providers later
|
||||
provider4 = CustomContextProvider4()
|
||||
@@ -90,10 +90,10 @@ class AggregateContextProvider(ContextProvider):
|
||||
await asyncio.gather(*[x.thread_created(thread_id) for x in self.providers])
|
||||
|
||||
@override
|
||||
async def invoking(self, messages: ChatMessage | MutableSequence[ChatMessage], **kwargs: Any) -> Context:
|
||||
async def invoking(self, messages: Message | MutableSequence[Message], **kwargs: Any) -> Context:
|
||||
contexts = await asyncio.gather(*[provider.invoking(messages, **kwargs) for provider in self.providers])
|
||||
instructions: str = ""
|
||||
return_messages: list[ChatMessage] = []
|
||||
return_messages: list[Message] = []
|
||||
tools: list["ToolProtocol"] = []
|
||||
for ctx in contexts:
|
||||
if ctx.instructions:
|
||||
@@ -107,8 +107,8 @@ class AggregateContextProvider(ContextProvider):
|
||||
@override
|
||||
async def invoked(
|
||||
self,
|
||||
request_messages: ChatMessage | Sequence[ChatMessage],
|
||||
response_messages: ChatMessage | Sequence[ChatMessage] | None = None,
|
||||
request_messages: Message | Sequence[Message],
|
||||
response_messages: Message | Sequence[Message] | None = None,
|
||||
invoke_exception: Exception | None = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
@@ -167,7 +167,7 @@ class TimeContextProvider(ContextProvider):
|
||||
"""A simple context provider that adds time-related instructions."""
|
||||
|
||||
@override
|
||||
async def invoking(self, messages: ChatMessage | MutableSequence[ChatMessage], **kwargs: Any) -> Context:
|
||||
async def invoking(self, messages: Message | MutableSequence[Message], **kwargs: Any) -> Context:
|
||||
from datetime import datetime
|
||||
|
||||
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
@@ -181,7 +181,7 @@ class PersonaContextProvider(ContextProvider):
|
||||
self.persona = persona
|
||||
|
||||
@override
|
||||
async def invoking(self, messages: ChatMessage | MutableSequence[ChatMessage], **kwargs: Any) -> Context:
|
||||
async def invoking(self, messages: Message | MutableSequence[Message], **kwargs: Any) -> Context:
|
||||
return Context(instructions=f"Your persona: {self.persona}. ")
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ class PreferencesContextProvider(ContextProvider):
|
||||
self.preferences: dict[str, str] = {}
|
||||
|
||||
@override
|
||||
async def invoking(self, messages: ChatMessage | MutableSequence[ChatMessage], **kwargs: Any) -> Context:
|
||||
async def invoking(self, messages: Message | MutableSequence[Message], **kwargs: Any) -> Context:
|
||||
if not self.preferences:
|
||||
return Context()
|
||||
prefs_str = ", ".join(f"{k}: {v}" for k, v in self.preferences.items())
|
||||
@@ -201,14 +201,14 @@ class PreferencesContextProvider(ContextProvider):
|
||||
@override
|
||||
async def invoked(
|
||||
self,
|
||||
request_messages: ChatMessage | Sequence[ChatMessage],
|
||||
response_messages: ChatMessage | Sequence[ChatMessage] | None = None,
|
||||
request_messages: Message | Sequence[Message],
|
||||
response_messages: Message | Sequence[Message] | None = None,
|
||||
invoke_exception: Exception | None = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
# Simple example: extract and store preferences from user messages
|
||||
# In a real implementation, you might use structured extraction
|
||||
msgs = [request_messages] if isinstance(request_messages, ChatMessage) else list(request_messages)
|
||||
msgs = [request_messages] if isinstance(request_messages, Message) else list(request_messages)
|
||||
|
||||
for msg in msgs:
|
||||
content = msg.text if hasattr(msg, "text") else ""
|
||||
@@ -230,7 +230,7 @@ class PreferencesContextProvider(ContextProvider):
|
||||
async def main():
|
||||
"""Demonstrate using AggregateContextProvider to combine multiple providers."""
|
||||
async with AzureCliCredential() as credential:
|
||||
chat_client = AzureAIClient(credential=credential)
|
||||
client = AzureAIClient(credential=credential)
|
||||
|
||||
# Create individual context providers
|
||||
time_provider = TimeContextProvider()
|
||||
@@ -245,8 +245,8 @@ async def main():
|
||||
])
|
||||
|
||||
# Create the agent with the aggregate provider
|
||||
async with ChatAgent(
|
||||
chat_client=chat_client,
|
||||
async with Agent(
|
||||
client=client,
|
||||
instructions="You are a helpful assistant.",
|
||||
context_provider=aggregate_provider,
|
||||
) as agent:
|
||||
|
||||
@@ -126,7 +126,7 @@ AZURE_OPENAI_RESOURCE_URL=https://myresource.openai.azure.com
|
||||
### Semantic Mode
|
||||
|
||||
```python
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework import Agent
|
||||
from agent_framework.azure import AzureAIAgentClient, AzureAISearchContextProvider
|
||||
from azure.identity.aio import DefaultAzureCredential
|
||||
|
||||
@@ -141,8 +141,8 @@ search_provider = AzureAISearchContextProvider(
|
||||
|
||||
# Create agent with search context
|
||||
async with AzureAIAgentClient(credential=DefaultAzureCredential()) as client:
|
||||
async with ChatAgent(
|
||||
chat_client=client,
|
||||
async with Agent(
|
||||
client=client,
|
||||
model=model_deployment,
|
||||
context_provider=search_provider,
|
||||
) as agent:
|
||||
@@ -166,8 +166,8 @@ search_provider = AzureAISearchContextProvider(
|
||||
)
|
||||
|
||||
# Use with agent (same as semantic mode)
|
||||
async with ChatAgent(
|
||||
chat_client=client,
|
||||
async with Agent(
|
||||
client=client,
|
||||
model=model_deployment,
|
||||
context_provider=search_provider,
|
||||
) as agent:
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework import Agent
|
||||
from agent_framework.azure import AzureAIAgentClient, AzureAISearchContextProvider
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
@@ -112,8 +112,8 @@ async def main() -> None:
|
||||
model_deployment_name=model_deployment,
|
||||
credential=AzureCliCredential(),
|
||||
) as client,
|
||||
ChatAgent(
|
||||
chat_client=client,
|
||||
Agent(
|
||||
client=client,
|
||||
name="SearchAgent",
|
||||
instructions=(
|
||||
"You are a helpful assistant with advanced reasoning capabilities. "
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework import Agent
|
||||
from agent_framework.azure import AzureAIAgentClient, AzureAISearchContextProvider
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
@@ -69,8 +69,8 @@ async def main() -> None:
|
||||
model_deployment_name=model_deployment,
|
||||
credential=AzureCliCredential(),
|
||||
) as client,
|
||||
ChatAgent(
|
||||
chat_client=client,
|
||||
Agent(
|
||||
client=client,
|
||||
name="SearchAgent",
|
||||
instructions=(
|
||||
"You are a helpful assistant. Use the provided context from the "
|
||||
|
||||
@@ -30,7 +30,7 @@ Run:
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from agent_framework import ChatMessage, tool
|
||||
from agent_framework import Message, tool
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
from agent_framework_redis._provider import RedisProvider
|
||||
from redisvl.extensions.cache.embeddings import EmbeddingsCache
|
||||
@@ -128,9 +128,9 @@ async def main() -> None:
|
||||
|
||||
# Build sample chat messages to persist to Redis
|
||||
messages = [
|
||||
ChatMessage("user", ["runA CONVO: User Message"]),
|
||||
ChatMessage("assistant", ["runA CONVO: Assistant Message"]),
|
||||
ChatMessage("system", ["runA CONVO: System Message"]),
|
||||
Message("user", ["runA CONVO: User Message"]),
|
||||
Message("assistant", ["runA CONVO: Assistant Message"]),
|
||||
Message("system", ["runA CONVO: System Message"]),
|
||||
]
|
||||
|
||||
# Declare/start a conversation/thread and write messages under 'runA'.
|
||||
@@ -142,7 +142,7 @@ async def main() -> None:
|
||||
# Retrieve relevant memories for a hypothetical model call. The provider uses
|
||||
# the current request messages as the retrieval query and returns context to
|
||||
# be injected into the model's instructions.
|
||||
ctx = await provider.invoking([ChatMessage("system", ["B: Assistant Message"])])
|
||||
ctx = await provider.invoking([Message("system", ["B: Assistant Message"])])
|
||||
|
||||
# Inspect retrieved memories that would be injected into instructions
|
||||
# (Debug-only output so you can verify retrieval works as expected.)
|
||||
|
||||
@@ -4,7 +4,7 @@ import asyncio
|
||||
from collections.abc import MutableSequence, Sequence
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import ChatAgent, ChatClientProtocol, ChatMessage, Context, ContextProvider
|
||||
from agent_framework import Agent, Context, ContextProvider, Message, SupportsChatGetResponse
|
||||
from agent_framework.azure import AzureAIClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
from pydantic import BaseModel
|
||||
@@ -16,13 +16,13 @@ class UserInfo(BaseModel):
|
||||
|
||||
|
||||
class UserInfoMemory(ContextProvider):
|
||||
def __init__(self, chat_client: ChatClientProtocol, user_info: UserInfo | None = None, **kwargs: Any):
|
||||
def __init__(self, client: SupportsChatGetResponse, user_info: UserInfo | None = None, **kwargs: Any):
|
||||
"""Create the memory.
|
||||
|
||||
If you pass in kwargs, they will be attempted to be used to create a UserInfo object.
|
||||
"""
|
||||
|
||||
self._chat_client = chat_client
|
||||
self._chat_client = client
|
||||
if user_info:
|
||||
self.user_info = user_info
|
||||
elif kwargs:
|
||||
@@ -32,8 +32,8 @@ class UserInfoMemory(ContextProvider):
|
||||
|
||||
async def invoked(
|
||||
self,
|
||||
request_messages: ChatMessage | Sequence[ChatMessage],
|
||||
response_messages: ChatMessage | Sequence[ChatMessage] | None = None,
|
||||
request_messages: Message | Sequence[Message],
|
||||
response_messages: Message | Sequence[Message] | None = None,
|
||||
invoke_exception: Exception | None = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
@@ -64,7 +64,7 @@ class UserInfoMemory(ContextProvider):
|
||||
except Exception:
|
||||
pass # Failed to extract, continue without updating
|
||||
|
||||
async def invoking(self, messages: ChatMessage | MutableSequence[ChatMessage], **kwargs: Any) -> Context:
|
||||
async def invoking(self, messages: Message | MutableSequence[Message], **kwargs: Any) -> Context:
|
||||
"""Provide user information context before each agent call."""
|
||||
instructions: list[str] = []
|
||||
|
||||
@@ -92,14 +92,14 @@ class UserInfoMemory(ContextProvider):
|
||||
|
||||
async def main():
|
||||
async with AzureCliCredential() as credential:
|
||||
chat_client = AzureAIClient(credential=credential)
|
||||
client = AzureAIClient(credential=credential)
|
||||
|
||||
# Create the memory provider
|
||||
memory_provider = UserInfoMemory(chat_client)
|
||||
memory_provider = UserInfoMemory(client)
|
||||
|
||||
# Create the agent with memory
|
||||
async with ChatAgent(
|
||||
chat_client=chat_client,
|
||||
async with Agent(
|
||||
client=client,
|
||||
instructions="You are a friendly assistant. Always address the user by their name.",
|
||||
context_provider=memory_provider,
|
||||
) as agent:
|
||||
|
||||
@@ -175,7 +175,7 @@ agent = agent_factory.create_agent_from_yaml_path(Path("custom_provider.yaml"))
|
||||
|
||||
This allows you to extend the declarative framework with custom chat client implementations. The mapping requires:
|
||||
- **package**: The Python package/module to import from
|
||||
- **name**: The class name of your ChatClientProtocol implementation
|
||||
- **name**: The class name of your SupportsChatGetResponse implementation
|
||||
- **model_id_field**: The constructor parameter name that accepts the value of the `model.id` field from the YAML
|
||||
|
||||
You can reference your custom provider using either `Provider.ApiType` format or just `Provider` in your YAML configuration, as long as it matches the registered mapping.
|
||||
|
||||
@@ -26,7 +26,7 @@ async def main():
|
||||
|
||||
# create the AgentFactory with a chat client and bindings
|
||||
agent_factory = AgentFactory(
|
||||
chat_client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
client=AzureOpenAIResponsesClient(credential=AzureCliCredential()),
|
||||
bindings={"get_weather": get_weather},
|
||||
)
|
||||
# create the agent from the yaml
|
||||
|
||||
@@ -44,7 +44,7 @@ Each agent/workflow follows a strict structure required by DevUI's discovery sys
|
||||
|
||||
```
|
||||
agent_name/
|
||||
├── __init__.py # Must export: agent = ChatAgent(...)
|
||||
├── __init__.py # Must export: agent = Agent(...)
|
||||
├── agent.py # Agent implementation
|
||||
└── .env.example # Example environment variables
|
||||
```
|
||||
@@ -100,13 +100,13 @@ Example:
|
||||
|
||||
```python
|
||||
# my_agent/__init__.py
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework import Agent
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
|
||||
agent = ChatAgent(
|
||||
agent = Agent(
|
||||
name="MyAgent",
|
||||
description="My custom agent",
|
||||
chat_client=OpenAIChatClient(),
|
||||
client=OpenAIChatClient(),
|
||||
# ... your configuration
|
||||
)
|
||||
```
|
||||
|
||||
@@ -21,7 +21,7 @@ import logging
|
||||
import os
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent, tool
|
||||
from agent_framework import Agent, tool
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -68,7 +68,7 @@ def extract_key_points(
|
||||
|
||||
|
||||
# Agent using Azure OpenAI Responses API (supports PDF uploads!)
|
||||
agent = ChatAgent(
|
||||
agent = Agent(
|
||||
name="AzureResponsesAgent",
|
||||
description="An agent that can analyze PDFs, images, and other documents using Azure OpenAI Responses API",
|
||||
instructions="""
|
||||
@@ -85,7 +85,7 @@ agent = ChatAgent(
|
||||
For PDFs, you can read and understand the text, tables, and structure.
|
||||
For images, you can describe what you see and extract any text.
|
||||
""",
|
||||
chat_client=AzureOpenAIResponsesClient(
|
||||
client=AzureOpenAIResponsesClient(
|
||||
deployment_name=_deployment_name,
|
||||
endpoint=_endpoint,
|
||||
api_version="2025-03-01-preview", # Required for Responses API
|
||||
|
||||
@@ -8,7 +8,7 @@ Make sure to run 'az login' before starting devui.
|
||||
import os
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent, tool
|
||||
from agent_framework import Agent, tool
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
from pydantic import Field
|
||||
@@ -43,9 +43,9 @@ def get_forecast(
|
||||
|
||||
|
||||
# Agent instance following Agent Framework conventions
|
||||
agent = ChatAgent(
|
||||
agent = Agent(
|
||||
name="FoundryWeatherAgent",
|
||||
chat_client=AzureAIAgentClient(
|
||||
client=AzureAIAgentClient(
|
||||
project_endpoint=os.environ.get("AZURE_AI_PROJECT_ENDPOINT"),
|
||||
model_deployment_name=os.environ.get("FOUNDRY_MODEL_DEPLOYMENT_NAME"),
|
||||
credential=AzureCliCredential(),
|
||||
|
||||
@@ -10,7 +10,7 @@ import logging
|
||||
import os
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent, Executor, WorkflowBuilder, WorkflowContext, handler, tool
|
||||
from agent_framework import Agent, Executor, WorkflowBuilder, WorkflowContext, handler, tool
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.devui import serve
|
||||
from typing_extensions import Never
|
||||
@@ -68,7 +68,7 @@ def main():
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Create Azure OpenAI chat client
|
||||
chat_client = AzureOpenAIChatClient(
|
||||
client = AzureOpenAIChatClient(
|
||||
api_key=os.environ.get("AZURE_OPENAI_API_KEY"),
|
||||
azure_endpoint=os.environ.get("AZURE_OPENAI_ENDPOINT"),
|
||||
api_version=os.environ.get("AZURE_OPENAI_API_VERSION", "2024-10-21"),
|
||||
@@ -76,22 +76,22 @@ def main():
|
||||
)
|
||||
|
||||
# Create agents
|
||||
weather_agent = ChatAgent(
|
||||
weather_agent = Agent(
|
||||
name="weather-assistant",
|
||||
description="Provides weather information and time",
|
||||
instructions=(
|
||||
"You are a helpful weather and time assistant. Use the available tools to "
|
||||
"provide accurate weather information and current time for any location."
|
||||
),
|
||||
chat_client=chat_client,
|
||||
client=client,
|
||||
tools=[get_weather, get_time],
|
||||
)
|
||||
|
||||
simple_agent = ChatAgent(
|
||||
simple_agent = Agent(
|
||||
name="general-assistant",
|
||||
description="A simple conversational agent",
|
||||
instructions="You are a helpful assistant.",
|
||||
chat_client=chat_client,
|
||||
client=client,
|
||||
)
|
||||
|
||||
# Create a basic workflow: Input -> UpperCase -> AddExclamation -> Output
|
||||
|
||||
@@ -7,15 +7,16 @@ from collections.abc import AsyncIterable, Awaitable, Callable
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import (
|
||||
ChatAgent,
|
||||
Agent,
|
||||
ChatContext,
|
||||
ChatMessage,
|
||||
ChatResponse,
|
||||
ChatResponseUpdate,
|
||||
Content,
|
||||
FunctionInvocationContext,
|
||||
Message,
|
||||
MiddlewareTermination,
|
||||
ResponseStream,
|
||||
Role,
|
||||
chat_middleware,
|
||||
function_middleware,
|
||||
tool,
|
||||
@@ -44,7 +45,7 @@ async def security_filter_middleware(
|
||||
|
||||
# Check only the last message (most recent user input)
|
||||
last_message = context.messages[-1] if context.messages else None
|
||||
if last_message and last_message.role == "user" and last_message.text:
|
||||
if last_message and last_message.role == Role.USER and last_message.text:
|
||||
message_lower = last_message.text.lower()
|
||||
for term in blocked_terms:
|
||||
if term in message_lower:
|
||||
@@ -55,26 +56,29 @@ async def security_filter_middleware(
|
||||
)
|
||||
|
||||
if context.stream:
|
||||
# Streaming mode: return async generator
|
||||
# Streaming mode: wrap in ResponseStream
|
||||
async def blocked_stream(msg: str = error_message) -> AsyncIterable[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(
|
||||
contents=[Content.from_text(text=msg)],
|
||||
role="assistant",
|
||||
role=Role.ASSISTANT,
|
||||
)
|
||||
|
||||
context.result = ResponseStream(blocked_stream(), finalizer=ChatResponse.from_updates)
|
||||
response = ChatResponse(
|
||||
messages=[Message(role=Role.ASSISTANT, text=error_message)]
|
||||
)
|
||||
context.result = ResponseStream(blocked_stream(), finalizer=lambda _, r=response: r)
|
||||
else:
|
||||
# Non-streaming mode: return complete response
|
||||
context.result = ChatResponse(
|
||||
messages=[
|
||||
ChatMessage(
|
||||
role="assistant",
|
||||
Message(
|
||||
role=Role.ASSISTANT,
|
||||
text=error_message,
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
raise MiddlewareTermination
|
||||
raise MiddlewareTermination(result=context.result)
|
||||
|
||||
await call_next(context)
|
||||
|
||||
@@ -92,7 +96,7 @@ async def atlantis_location_filter_middleware(
|
||||
"Blocked! Hold up right there!! Tell the user that "
|
||||
"'Atlantis is a special place, we must never ask about the weather there!!'"
|
||||
)
|
||||
raise MiddlewareTermination
|
||||
raise MiddlewareTermination(result=context.result)
|
||||
|
||||
await call_next(context)
|
||||
|
||||
@@ -136,7 +140,7 @@ def send_email(
|
||||
|
||||
|
||||
# Agent instance following Agent Framework conventions
|
||||
agent = ChatAgent(
|
||||
agent = Agent(
|
||||
name="AzureWeatherAgent",
|
||||
description="A helpful agent that provides weather information and forecasts",
|
||||
instructions="""
|
||||
@@ -144,7 +148,7 @@ agent = ChatAgent(
|
||||
and forecasts for any location. Always be helpful and provide detailed
|
||||
weather information when asked.
|
||||
""",
|
||||
chat_client=AzureOpenAIChatClient(
|
||||
client=AzureOpenAIChatClient(
|
||||
api_key=os.environ.get("AZURE_OPENAI_API_KEY", ""),
|
||||
),
|
||||
tools=[get_weather, get_forecast, send_email],
|
||||
|
||||
@@ -59,10 +59,10 @@ def is_approved(message: Any) -> bool:
|
||||
|
||||
|
||||
# Create Azure OpenAI chat client
|
||||
chat_client = AzureOpenAIChatClient(api_key=os.environ.get("AZURE_OPENAI_API_KEY", ""))
|
||||
client = AzureOpenAIChatClient(api_key=os.environ.get("AZURE_OPENAI_API_KEY", ""))
|
||||
|
||||
# Create Writer agent - generates content
|
||||
writer = chat_client.as_agent(
|
||||
writer = client.as_agent(
|
||||
name="Writer",
|
||||
instructions=(
|
||||
"You are an excellent content writer. "
|
||||
@@ -72,7 +72,7 @@ writer = chat_client.as_agent(
|
||||
)
|
||||
|
||||
# Create Reviewer agent - evaluates and provides structured feedback
|
||||
reviewer = chat_client.as_agent(
|
||||
reviewer = client.as_agent(
|
||||
name="Reviewer",
|
||||
instructions=(
|
||||
"You are an expert content reviewer. "
|
||||
@@ -90,7 +90,7 @@ reviewer = chat_client.as_agent(
|
||||
)
|
||||
|
||||
# Create Editor agent - improves content based on feedback
|
||||
editor = chat_client.as_agent(
|
||||
editor = client.as_agent(
|
||||
name="Editor",
|
||||
instructions=(
|
||||
"You are a skilled editor. "
|
||||
@@ -101,7 +101,7 @@ editor = chat_client.as_agent(
|
||||
)
|
||||
|
||||
# Create Publisher agent - formats content for publication
|
||||
publisher = chat_client.as_agent(
|
||||
publisher = client.as_agent(
|
||||
name="Publisher",
|
||||
instructions=(
|
||||
"You are a publishing agent. "
|
||||
@@ -111,7 +111,7 @@ publisher = chat_client.as_agent(
|
||||
)
|
||||
|
||||
# Create Summarizer agent - creates final publication report
|
||||
summarizer = chat_client.as_agent(
|
||||
summarizer = client.as_agent(
|
||||
name="Summarizer",
|
||||
instructions=(
|
||||
"You are a summarizer agent. "
|
||||
|
||||
@@ -15,7 +15,7 @@ import asyncio
|
||||
import logging
|
||||
import os
|
||||
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework import Agent
|
||||
from agent_framework.azure import AzureOpenAIChatClient, DurableAIAgentWorker
|
||||
from azure.identity import AzureCliCredential, DefaultAzureCredential
|
||||
from durabletask.azuremanaged.worker import DurableTaskSchedulerWorker
|
||||
@@ -25,11 +25,11 @@ logging.basicConfig(level=logging.WARNING)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def create_joker_agent() -> ChatAgent:
|
||||
def create_joker_agent() -> Agent:
|
||||
"""Create the Joker agent using Azure OpenAI.
|
||||
|
||||
Returns:
|
||||
ChatAgent: The configured Joker agent
|
||||
Agent: The configured Joker agent
|
||||
"""
|
||||
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
|
||||
name="Joker",
|
||||
|
||||
@@ -65,7 +65,7 @@ def create_weather_agent():
|
||||
"""Create the Weather agent using Azure OpenAI.
|
||||
|
||||
Returns:
|
||||
ChatAgent: The configured Weather agent with weather tool
|
||||
Agent: The configured Weather agent with weather tool
|
||||
"""
|
||||
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
|
||||
name=WEATHER_AGENT_NAME,
|
||||
@@ -78,7 +78,7 @@ def create_math_agent():
|
||||
"""Create the Math agent using Azure OpenAI.
|
||||
|
||||
Returns:
|
||||
ChatAgent: The configured Math agent with calculation tools
|
||||
Agent: The configured Math agent with calculation tools
|
||||
"""
|
||||
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
|
||||
name=MATH_AGENT_NAME,
|
||||
|
||||
@@ -18,7 +18,7 @@ import os
|
||||
from datetime import timedelta
|
||||
|
||||
import redis.asyncio as aioredis
|
||||
from agent_framework import AgentResponseUpdate, ChatAgent
|
||||
from agent_framework import Agent, AgentResponseUpdate
|
||||
from agent_framework.azure import (
|
||||
AgentCallbackContext,
|
||||
AgentResponseCallbackProtocol,
|
||||
@@ -143,11 +143,11 @@ class RedisStreamCallback(AgentResponseCallbackProtocol):
|
||||
logger.error(f"Error writing end-of-stream marker: {ex}", exc_info=True)
|
||||
|
||||
|
||||
def create_travel_agent() -> "ChatAgent":
|
||||
def create_travel_agent() -> "Agent":
|
||||
"""Create the TravelPlanner agent using Azure OpenAI.
|
||||
|
||||
Returns:
|
||||
ChatAgent: The configured TravelPlanner agent with travel planning tools.
|
||||
Agent: The configured TravelPlanner agent with travel planning tools.
|
||||
"""
|
||||
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
|
||||
name="TravelPlanner",
|
||||
|
||||
+3
-3
@@ -17,7 +17,7 @@ import logging
|
||||
import os
|
||||
from collections.abc import Generator
|
||||
|
||||
from agent_framework import AgentResponse, ChatAgent
|
||||
from agent_framework import Agent, AgentResponse
|
||||
from agent_framework.azure import AzureOpenAIChatClient, DurableAIAgentOrchestrationContext, DurableAIAgentWorker
|
||||
from azure.identity import AzureCliCredential, DefaultAzureCredential
|
||||
from durabletask.azuremanaged.worker import DurableTaskSchedulerWorker
|
||||
@@ -31,14 +31,14 @@ logger = logging.getLogger(__name__)
|
||||
WRITER_AGENT_NAME = "WriterAgent"
|
||||
|
||||
|
||||
def create_writer_agent() -> "ChatAgent":
|
||||
def create_writer_agent() -> "Agent":
|
||||
"""Create the Writer agent using Azure OpenAI.
|
||||
|
||||
This agent refines short pieces of text, enhancing initial sentences
|
||||
and polishing improved versions further.
|
||||
|
||||
Returns:
|
||||
ChatAgent: The configured Writer agent
|
||||
Agent: The configured Writer agent
|
||||
"""
|
||||
instructions = (
|
||||
"You refine short pieces of text. When given an initial sentence you enhance it;\n"
|
||||
|
||||
+5
-5
@@ -18,7 +18,7 @@ import os
|
||||
from collections.abc import Generator
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import AgentResponse, ChatAgent
|
||||
from agent_framework import Agent, AgentResponse
|
||||
from agent_framework.azure import AzureOpenAIChatClient, DurableAIAgentOrchestrationContext, DurableAIAgentWorker
|
||||
from azure.identity import AzureCliCredential, DefaultAzureCredential
|
||||
from durabletask.azuremanaged.worker import DurableTaskSchedulerWorker
|
||||
@@ -33,11 +33,11 @@ PHYSICIST_AGENT_NAME = "PhysicistAgent"
|
||||
CHEMIST_AGENT_NAME = "ChemistAgent"
|
||||
|
||||
|
||||
def create_physicist_agent() -> "ChatAgent":
|
||||
def create_physicist_agent() -> "Agent":
|
||||
"""Create the Physicist agent using Azure OpenAI.
|
||||
|
||||
Returns:
|
||||
ChatAgent: The configured Physicist agent
|
||||
Agent: The configured Physicist agent
|
||||
"""
|
||||
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
|
||||
name=PHYSICIST_AGENT_NAME,
|
||||
@@ -45,11 +45,11 @@ def create_physicist_agent() -> "ChatAgent":
|
||||
)
|
||||
|
||||
|
||||
def create_chemist_agent() -> "ChatAgent":
|
||||
def create_chemist_agent() -> "Agent":
|
||||
"""Create the Chemist agent using Azure OpenAI.
|
||||
|
||||
Returns:
|
||||
ChatAgent: The configured Chemist agent
|
||||
Agent: The configured Chemist agent
|
||||
"""
|
||||
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
|
||||
name=CHEMIST_AGENT_NAME,
|
||||
|
||||
+5
-5
@@ -18,7 +18,7 @@ import os
|
||||
from collections.abc import Generator
|
||||
from typing import Any, cast
|
||||
|
||||
from agent_framework import AgentResponse, ChatAgent
|
||||
from agent_framework import Agent, AgentResponse
|
||||
from agent_framework.azure import AzureOpenAIChatClient, DurableAIAgentOrchestrationContext, DurableAIAgentWorker
|
||||
from azure.identity import AzureCliCredential, DefaultAzureCredential
|
||||
from durabletask.azuremanaged.worker import DurableTaskSchedulerWorker
|
||||
@@ -51,11 +51,11 @@ class EmailPayload(BaseModel):
|
||||
email_content: str
|
||||
|
||||
|
||||
def create_spam_agent() -> "ChatAgent":
|
||||
def create_spam_agent() -> "Agent":
|
||||
"""Create the Spam Detection agent using Azure OpenAI.
|
||||
|
||||
Returns:
|
||||
ChatAgent: The configured Spam Detection agent
|
||||
Agent: The configured Spam Detection agent
|
||||
"""
|
||||
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
|
||||
name=SPAM_AGENT_NAME,
|
||||
@@ -63,11 +63,11 @@ def create_spam_agent() -> "ChatAgent":
|
||||
)
|
||||
|
||||
|
||||
def create_email_agent() -> "ChatAgent":
|
||||
def create_email_agent() -> "Agent":
|
||||
"""Create the Email Assistant agent using Azure OpenAI.
|
||||
|
||||
Returns:
|
||||
ChatAgent: The configured Email Assistant agent
|
||||
Agent: The configured Email Assistant agent
|
||||
"""
|
||||
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
|
||||
name=EMAIL_AGENT_NAME,
|
||||
|
||||
+3
-3
@@ -19,7 +19,7 @@ from collections.abc import Generator
|
||||
from datetime import timedelta
|
||||
from typing import Any, cast
|
||||
|
||||
from agent_framework import AgentResponse, ChatAgent
|
||||
from agent_framework import Agent, AgentResponse
|
||||
from agent_framework.azure import AzureOpenAIChatClient, DurableAIAgentOrchestrationContext, DurableAIAgentWorker
|
||||
from azure.identity import AzureCliCredential, DefaultAzureCredential
|
||||
from durabletask.azuremanaged.worker import DurableTaskSchedulerWorker
|
||||
@@ -54,11 +54,11 @@ class HumanApproval(BaseModel):
|
||||
feedback: str = ""
|
||||
|
||||
|
||||
def create_writer_agent() -> "ChatAgent":
|
||||
def create_writer_agent() -> "Agent":
|
||||
"""Create the Writer agent using Azure OpenAI.
|
||||
|
||||
Returns:
|
||||
ChatAgent: The configured Writer agent
|
||||
Agent: The configured Writer agent
|
||||
"""
|
||||
instructions = (
|
||||
"You are a professional content writer who creates high-quality articles on various topics. "
|
||||
|
||||
@@ -17,7 +17,7 @@ from typing import Any
|
||||
|
||||
import openai
|
||||
import pandas as pd
|
||||
from agent_framework import ChatAgent, ChatMessage
|
||||
from agent_framework import Agent, Message
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.ai.projects import AIProjectClient
|
||||
from azure.identity import AzureCliCredential
|
||||
@@ -142,7 +142,7 @@ def run_eval(
|
||||
async def execute_query_with_self_reflection(
|
||||
*,
|
||||
client: openai.OpenAI,
|
||||
agent: ChatAgent,
|
||||
agent: Agent,
|
||||
eval_object: openai.types.EvalCreateResponse,
|
||||
full_user_query: str,
|
||||
context: str,
|
||||
@@ -152,7 +152,7 @@ async def execute_query_with_self_reflection(
|
||||
Execute a query with self-reflection loop.
|
||||
|
||||
Args:
|
||||
agent: ChatAgent instance to use for generating responses
|
||||
agent: Agent instance to use for generating responses
|
||||
full_user_query: Complete prompt including system prompt, user request, and context
|
||||
context: Context document for groundedness evaluation
|
||||
evaluator: Groundedness evaluator function
|
||||
@@ -170,7 +170,7 @@ async def execute_query_with_self_reflection(
|
||||
- total_groundedness_eval_time: Time spent on evaluations (seconds)
|
||||
- total_end_to_end_time: Total execution time (seconds)
|
||||
"""
|
||||
messages = [ChatMessage("user", [full_user_query])]
|
||||
messages = [Message("user", [full_user_query])]
|
||||
|
||||
best_score = 0
|
||||
max_score = 5
|
||||
@@ -223,14 +223,14 @@ async def execute_query_with_self_reflection(
|
||||
print(f" → No improvement (score: {score}/{max_score}). Trying again...")
|
||||
|
||||
# Add to conversation history
|
||||
messages.append(ChatMessage("assistant", [agent_response]))
|
||||
messages.append(Message("assistant", [agent_response]))
|
||||
|
||||
# Request improvement
|
||||
reflection_prompt = (
|
||||
f"The groundedness score of your response is {score}/{max_score}. "
|
||||
f"Reflect on your answer and improve it to get the maximum score of {max_score} "
|
||||
)
|
||||
messages.append(ChatMessage("user", [reflection_prompt]))
|
||||
messages.append(Message("user", [reflection_prompt]))
|
||||
|
||||
end_time = time.time()
|
||||
latency = end_time - start_time
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import os
|
||||
|
||||
from agent_framework import ChatAgent, MCPStreamableHTTPTool
|
||||
from agent_framework import Agent, MCPStreamableHTTPTool
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
from httpx import AsyncClient
|
||||
|
||||
@@ -43,8 +43,8 @@ async def api_key_auth_example() -> None:
|
||||
url=mcp_server_url,
|
||||
http_client=http_client, # Pass HTTP client with authentication headers
|
||||
) as mcp_tool,
|
||||
ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
name="Agent",
|
||||
instructions="You are a helpful assistant.",
|
||||
tools=mcp_tool,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from agent_framework import ChatAgent, HostedMCPTool
|
||||
from agent_framework import Agent, HostedMCPTool
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
from dotenv import load_dotenv
|
||||
|
||||
@@ -54,8 +54,8 @@ async def github_mcp_example() -> None:
|
||||
)
|
||||
|
||||
# 5. Create agent with the GitHub MCP tool
|
||||
async with ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
async with Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
name="GitHubAgent",
|
||||
instructions=(
|
||||
"You are a helpful assistant that can help users interact with GitHub. "
|
||||
|
||||
@@ -7,9 +7,9 @@ from typing import Annotated
|
||||
|
||||
from agent_framework import (
|
||||
ChatContext,
|
||||
ChatMessage,
|
||||
ChatMiddleware,
|
||||
ChatResponse,
|
||||
Message,
|
||||
MiddlewareTermination,
|
||||
chat_middleware,
|
||||
tool,
|
||||
@@ -69,7 +69,7 @@ class InputObserverMiddleware(ChatMiddleware):
|
||||
print(f"[InputObserverMiddleware] Total messages: {len(context.messages)}")
|
||||
|
||||
# Modify user messages by creating new messages with enhanced text
|
||||
modified_messages: list[ChatMessage] = []
|
||||
modified_messages: list[Message] = []
|
||||
modified_count = 0
|
||||
|
||||
for message in context.messages:
|
||||
@@ -81,7 +81,7 @@ class InputObserverMiddleware(ChatMiddleware):
|
||||
updated_text = self.replacement
|
||||
print(f"[InputObserverMiddleware] Updated: '{original_text}' -> '{updated_text}'")
|
||||
|
||||
modified_message = ChatMessage(message.role, [updated_text])
|
||||
modified_message = Message(message.role, [updated_text])
|
||||
modified_messages.append(modified_message)
|
||||
modified_count += 1
|
||||
else:
|
||||
@@ -118,7 +118,7 @@ async def security_and_override_middleware(
|
||||
# Override the response instead of calling AI
|
||||
context.result = ChatResponse(
|
||||
messages=[
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="assistant",
|
||||
text="I cannot process requests containing sensitive information. "
|
||||
"Please rephrase your question without including passwords, secrets, or other "
|
||||
|
||||
@@ -10,9 +10,9 @@ from agent_framework import (
|
||||
AgentContext,
|
||||
AgentMiddleware,
|
||||
AgentResponse,
|
||||
ChatMessage,
|
||||
FunctionInvocationContext,
|
||||
FunctionMiddleware,
|
||||
Message,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
@@ -61,7 +61,7 @@ class SecurityAgentMiddleware(AgentMiddleware):
|
||||
print("[SecurityAgentMiddleware] Security Warning: Detected sensitive information, blocking request.")
|
||||
# Override the result with warning message
|
||||
context.result = AgentResponse(
|
||||
messages=[ChatMessage("assistant", ["Detected sensitive information, the request is blocked."])]
|
||||
messages=[Message("assistant", ["Detected sensitive information, the request is blocked."])]
|
||||
)
|
||||
# Simply don't call call_next() to prevent execution
|
||||
return
|
||||
|
||||
@@ -9,7 +9,7 @@ from agent_framework import (
|
||||
AgentContext,
|
||||
AgentMiddleware,
|
||||
AgentResponse,
|
||||
ChatMessage,
|
||||
Message,
|
||||
MiddlewareTermination,
|
||||
tool,
|
||||
)
|
||||
@@ -62,7 +62,7 @@ class PreTerminationMiddleware(AgentMiddleware):
|
||||
# Set a custom response
|
||||
context.result = AgentResponse(
|
||||
messages=[
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="assistant",
|
||||
text=(
|
||||
f"Sorry, I cannot process requests containing '{blocked_word}'. "
|
||||
@@ -72,8 +72,8 @@ class PreTerminationMiddleware(AgentMiddleware):
|
||||
]
|
||||
)
|
||||
|
||||
# Set terminate flag to prevent further processing
|
||||
raise MiddlewareTermination
|
||||
# Terminate to prevent further processing
|
||||
raise MiddlewareTermination(result=context.result)
|
||||
|
||||
await call_next(context)
|
||||
|
||||
|
||||
@@ -11,10 +11,11 @@ from agent_framework import (
|
||||
AgentResponse,
|
||||
AgentResponseUpdate,
|
||||
ChatContext,
|
||||
ChatMessage,
|
||||
ChatResponse,
|
||||
ChatResponseUpdate,
|
||||
Message,
|
||||
ResponseStream,
|
||||
Role,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
@@ -78,9 +79,9 @@ async def weather_override_middleware(context: ChatContext, call_next: Callable[
|
||||
context.result.with_transform_hook(_update_hook)
|
||||
else:
|
||||
# For non-streaming: just replace with a new message
|
||||
current_text = context.result.text or "" # type: ignore
|
||||
current_text = context.result.text if isinstance(context.result, ChatResponse) else ""
|
||||
custom_message = f"Weather Advisory: [0] {''.join(chunks)} Original message was: {current_text}"
|
||||
context.result = ChatResponse(messages=[ChatMessage(role="assistant", text=custom_message)])
|
||||
context.result = ChatResponse(messages=[Message(role=Role.ASSISTANT, text=custom_message)])
|
||||
|
||||
|
||||
async def validate_weather_middleware(context: ChatContext, call_next: Callable[[ChatContext], Awaitable[None]]) -> None:
|
||||
@@ -95,12 +96,12 @@ async def validate_weather_middleware(context: ChatContext, call_next: Callable[
|
||||
if context.stream and isinstance(context.result, ResponseStream):
|
||||
|
||||
def _append_validation_note(response: ChatResponse) -> ChatResponse:
|
||||
response.messages.append(ChatMessage(role="assistant", text=validation_note))
|
||||
response.messages.append(Message(role=Role.ASSISTANT, text=validation_note))
|
||||
return response
|
||||
|
||||
context.result.with_result_hook(_append_validation_note)
|
||||
context.result.with_finalizer(_append_validation_note)
|
||||
elif isinstance(context.result, ChatResponse):
|
||||
context.result.messages.append(ChatMessage(role="assistant", text=validation_note))
|
||||
context.result.messages.append(Message(role=Role.ASSISTANT, text=validation_note))
|
||||
|
||||
|
||||
async def agent_cleanup_middleware(context: AgentContext, call_next: Callable[[AgentContext], Awaitable[None]]) -> None:
|
||||
@@ -117,7 +118,7 @@ async def agent_cleanup_middleware(context: AgentContext, call_next: Callable[[A
|
||||
def _sanitize(response: AgentResponse) -> AgentResponse:
|
||||
found_prefix = state["found_prefix"]
|
||||
found_validation = False
|
||||
cleaned_messages: list[ChatMessage] = []
|
||||
cleaned_messages: list[Message] = []
|
||||
|
||||
for message in response.messages:
|
||||
text = message.text
|
||||
@@ -138,7 +139,7 @@ async def agent_cleanup_middleware(context: AgentContext, call_next: Callable[[A
|
||||
text = re.sub(r"\[\d+\]\s*", "", text)
|
||||
|
||||
cleaned_messages.append(
|
||||
ChatMessage(
|
||||
Message(
|
||||
role=message.role,
|
||||
text=text.strip(),
|
||||
author_name=message.author_name,
|
||||
@@ -153,7 +154,7 @@ async def agent_cleanup_middleware(context: AgentContext, call_next: Callable[[A
|
||||
if not found_validation:
|
||||
raise RuntimeError("Expected validation note not found in agent response.")
|
||||
|
||||
cleaned_messages.append(ChatMessage(role="assistant", text=" Agent: OK"))
|
||||
cleaned_messages.append(Message(role=Role.ASSISTANT, text=" Agent: OK"))
|
||||
response.messages = cleaned_messages
|
||||
return response
|
||||
|
||||
@@ -172,7 +173,7 @@ async def agent_cleanup_middleware(context: AgentContext, call_next: Callable[[A
|
||||
return update
|
||||
|
||||
context.result.with_transform_hook(_clean_update)
|
||||
context.result.with_result_hook(_sanitize)
|
||||
context.result.with_finalizer(_sanitize)
|
||||
elif isinstance(context.result, AgentResponse):
|
||||
context.result = _sanitize(context.result)
|
||||
|
||||
@@ -191,19 +192,6 @@ async def main() -> None:
|
||||
tools=get_weather,
|
||||
middleware=[agent_cleanup_middleware],
|
||||
)
|
||||
# Streaming example
|
||||
print("\n--- Streaming Example ---")
|
||||
query = "What's the weather like in Portland?"
|
||||
print(f"User: {query}")
|
||||
print("Agent: ", end="", flush=True)
|
||||
response = agent.run(query, stream=True)
|
||||
# add the hooks to print what you want to see
|
||||
response.with_transform_hook(lambda chunk: print(chunk.text, end="", flush=True)).with_result_hook(
|
||||
lambda final: print(f"\nFinal streamed response: {final.text}", flush=True)
|
||||
)
|
||||
# consume the stream to trigger the hooks
|
||||
await response.get_final_response()
|
||||
|
||||
# Non-streaming example
|
||||
print("\n--- Non-streaming Example ---")
|
||||
query = "What's the weather like in Seattle?"
|
||||
@@ -211,6 +199,18 @@ async def main() -> None:
|
||||
result = await agent.run(query)
|
||||
print(f"Agent: {result}")
|
||||
|
||||
# Streaming example
|
||||
print("\n--- Streaming Example ---")
|
||||
query = "What's the weather like in Portland?"
|
||||
print(f"User: {query}")
|
||||
print("Agent: ", end="", flush=True)
|
||||
response = agent.run(query, stream=True)
|
||||
async for chunk in response:
|
||||
if chunk.text:
|
||||
print(chunk.text, end="", flush=True)
|
||||
print("\n")
|
||||
print(f"Final Result: {(await response.get_final_response()).text}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatMessage, Content
|
||||
from agent_framework import Content, Message
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -24,7 +24,7 @@ async def test_image() -> None:
|
||||
client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
image_uri = create_sample_image()
|
||||
message = ChatMessage(
|
||||
message = Message(
|
||||
role="user",
|
||||
contents=[
|
||||
Content.from_text(text="What's in this image?"),
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
from agent_framework import ChatMessage, Content
|
||||
from agent_framework import Content, Message
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
@@ -33,7 +33,7 @@ async def test_image() -> None:
|
||||
client = AzureOpenAIResponsesClient(credential=AzureCliCredential())
|
||||
|
||||
image_uri = create_sample_image()
|
||||
message = ChatMessage(
|
||||
message = Message(
|
||||
role="user",
|
||||
contents=[
|
||||
Content.from_text(text="What's in this image?"),
|
||||
@@ -50,7 +50,7 @@ async def test_pdf() -> None:
|
||||
client = AzureOpenAIResponsesClient(credential=AzureCliCredential())
|
||||
|
||||
pdf_bytes = load_sample_pdf()
|
||||
message = ChatMessage(
|
||||
message = Message(
|
||||
role="user",
|
||||
contents=[
|
||||
Content.from_text(text="What information can you extract from this document?"),
|
||||
|
||||
@@ -5,7 +5,7 @@ import base64
|
||||
import struct
|
||||
from pathlib import Path
|
||||
|
||||
from agent_framework import ChatMessage, Content
|
||||
from agent_framework import Content, Message
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
|
||||
ASSETS_DIR = Path(__file__).resolve().parent.parent / "sample_assets"
|
||||
@@ -45,7 +45,7 @@ async def test_image() -> None:
|
||||
client = OpenAIChatClient(model_id="gpt-4o")
|
||||
|
||||
image_uri = create_sample_image()
|
||||
message = ChatMessage(
|
||||
message = Message(
|
||||
role="user",
|
||||
contents=[
|
||||
Content.from_text(text="What's in this image?"),
|
||||
@@ -62,7 +62,7 @@ async def test_audio() -> None:
|
||||
client = OpenAIChatClient(model_id="gpt-4o-audio-preview")
|
||||
|
||||
audio_uri = create_sample_audio()
|
||||
message = ChatMessage(
|
||||
message = Message(
|
||||
role="user",
|
||||
contents=[
|
||||
Content.from_text(text="What do you hear in this audio?"),
|
||||
@@ -79,7 +79,7 @@ async def test_pdf() -> None:
|
||||
client = OpenAIChatClient(model_id="gpt-4o")
|
||||
|
||||
pdf_bytes = load_sample_pdf()
|
||||
message = ChatMessage(
|
||||
message = Message(
|
||||
role="user",
|
||||
contents=[
|
||||
Content.from_text(text="What information can you extract from this document?"),
|
||||
|
||||
@@ -12,7 +12,7 @@ from opentelemetry.trace.span import format_trace_id
|
||||
from pydantic import Field
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from agent_framework import ChatClientProtocol
|
||||
from agent_framework import SupportsChatGetResponse
|
||||
|
||||
|
||||
"""
|
||||
@@ -51,7 +51,7 @@ async def get_weather(
|
||||
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
|
||||
|
||||
|
||||
async def run_chat_client(client: "ChatClientProtocol", stream: bool = False) -> None:
|
||||
async def run_chat_client(client: "SupportsChatGetResponse", stream: bool = False) -> None:
|
||||
"""Run an AI service.
|
||||
|
||||
This function runs an AI service and prints the output.
|
||||
|
||||
@@ -4,7 +4,7 @@ import asyncio
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent, tool
|
||||
from agent_framework import Agent, tool
|
||||
from agent_framework.observability import configure_otel_providers, get_tracer
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
from opentelemetry.trace import SpanKind
|
||||
@@ -39,8 +39,8 @@ async def main():
|
||||
with get_tracer().start_as_current_span("Scenario: Agent Chat", kind=SpanKind.CLIENT) as current_span:
|
||||
print(f"Trace ID: {format_trace_id(current_span.get_span_context().trace_id)}")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIChatClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIChatClient(),
|
||||
tools=get_weather,
|
||||
name="WeatherAgent",
|
||||
instructions="You are a weather assistant.",
|
||||
|
||||
@@ -16,7 +16,7 @@ from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
import dotenv
|
||||
from agent_framework import ChatAgent, tool
|
||||
from agent_framework import Agent, tool
|
||||
from agent_framework.observability import create_resource, enable_instrumentation, get_tracer
|
||||
from agent_framework.openai import OpenAIResponsesClient
|
||||
from azure.ai.projects.aio import AIProjectClient
|
||||
@@ -30,7 +30,7 @@ from pydantic import Field
|
||||
This sample shows you can can setup telemetry in Microsoft Foundry for a custom agent.
|
||||
First ensure you have a Foundry workspace with Application Insights enabled.
|
||||
And use the Operate tab to Register an Agent.
|
||||
Set the OpenTelemetry agent ID to the value used below in the ChatAgent creation: `weather-agent` (or change both).
|
||||
Set the OpenTelemetry agent ID to the value used below in the Agent creation: `weather-agent` (or change both).
|
||||
The sample uses the Azure Monitor OpenTelemetry exporter to send traces to Application Insights.
|
||||
So ensure you have the `azure-monitor-opentelemetry` package installed.
|
||||
"""
|
||||
@@ -85,8 +85,8 @@ async def main():
|
||||
with get_tracer().start_as_current_span("Weather Agent Chat", kind=SpanKind.CLIENT) as current_span:
|
||||
print(f"Trace ID: {format_trace_id(current_span.get_span_context().trace_id)}")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=OpenAIResponsesClient(),
|
||||
agent = Agent(
|
||||
client=OpenAIResponsesClient(),
|
||||
tools=get_weather,
|
||||
name="WeatherAgent",
|
||||
instructions="You are a weather assistant.",
|
||||
|
||||
@@ -6,7 +6,7 @@ from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
import dotenv
|
||||
from agent_framework import ChatAgent, tool
|
||||
from agent_framework import Agent, tool
|
||||
from agent_framework.azure import AzureAIClient
|
||||
from agent_framework.observability import get_tracer
|
||||
from azure.ai.projects.aio import AIProjectClient
|
||||
@@ -56,8 +56,8 @@ async def main():
|
||||
with get_tracer().start_as_current_span("Single Agent Chat", kind=SpanKind.CLIENT) as current_span:
|
||||
print(f"Trace ID: {format_trace_id(current_span.get_span_context().trace_id)}")
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=client,
|
||||
agent = Agent(
|
||||
client=client,
|
||||
tools=get_weather,
|
||||
name="WeatherAgent",
|
||||
instructions="You are a weather assistant.",
|
||||
|
||||
+6
-6
@@ -14,7 +14,7 @@ from opentelemetry.trace.span import format_trace_id
|
||||
from pydantic import Field
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from agent_framework import ChatClientProtocol
|
||||
from agent_framework import SupportsChatGetResponse
|
||||
|
||||
"""
|
||||
This sample, show how you can configure observability of an application via the
|
||||
@@ -28,7 +28,7 @@ output traces, logs, and metrics to the console.
|
||||
"""
|
||||
|
||||
# Define the scenarios that can be run to show the telemetry data collected by the SDK
|
||||
SCENARIOS = ["chat_client", "chat_client_stream", "tool", "all"]
|
||||
SCENARIOS = ["client", "client_stream", "tool", "all"]
|
||||
|
||||
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@@ -42,7 +42,7 @@ async def get_weather(
|
||||
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
|
||||
|
||||
|
||||
async def run_chat_client(client: "ChatClientProtocol", stream: bool = False) -> None:
|
||||
async def run_chat_client(client: "SupportsChatGetResponse", stream: bool = False) -> None:
|
||||
"""Run an AI service.
|
||||
|
||||
This function runs an AI service and prints the output.
|
||||
@@ -97,7 +97,7 @@ async def run_tool() -> None:
|
||||
print(f"Weather in Amsterdam:\n{weather}")
|
||||
|
||||
|
||||
async def main(scenario: Literal["chat_client", "chat_client_stream", "tool", "all"] = "all"):
|
||||
async def main(scenario: Literal["client", "client_stream", "tool", "all"] = "all"):
|
||||
"""Run the selected scenario(s)."""
|
||||
|
||||
# This will enable tracing and create the necessary tracing, logging and metrics providers
|
||||
@@ -113,10 +113,10 @@ async def main(scenario: Literal["chat_client", "chat_client_stream", "tool", "a
|
||||
if scenario == "tool" or scenario == "all":
|
||||
with suppress(Exception):
|
||||
await run_tool()
|
||||
if scenario == "chat_client_stream" or scenario == "all":
|
||||
if scenario == "client_stream" or scenario == "all":
|
||||
with suppress(Exception):
|
||||
await run_chat_client(client, stream=True)
|
||||
if scenario == "chat_client" or scenario == "all":
|
||||
if scenario == "client" or scenario == "all":
|
||||
with suppress(Exception):
|
||||
await run_chat_client(client, stream=False)
|
||||
|
||||
|
||||
+6
-6
@@ -14,7 +14,7 @@ from opentelemetry.trace.span import format_trace_id
|
||||
from pydantic import Field
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from agent_framework import ChatClientProtocol
|
||||
from agent_framework import SupportsChatGetResponse
|
||||
|
||||
"""
|
||||
This sample shows how you can configure observability with custom exporters passed directly
|
||||
@@ -28,7 +28,7 @@ Use this approach when you need custom exporter configuration beyond what enviro
|
||||
"""
|
||||
|
||||
# Define the scenarios that can be run to show the telemetry data collected by the SDK
|
||||
SCENARIOS = ["chat_client", "chat_client_stream", "tool", "all"]
|
||||
SCENARIOS = ["client", "client_stream", "tool", "all"]
|
||||
|
||||
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
|
||||
@@ -42,7 +42,7 @@ async def get_weather(
|
||||
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
|
||||
|
||||
|
||||
async def run_chat_client(client: "ChatClientProtocol", stream: bool = False) -> None:
|
||||
async def run_chat_client(client: "SupportsChatGetResponse", stream: bool = False) -> None:
|
||||
"""Run an AI service.
|
||||
|
||||
This function runs an AI service and prints the output.
|
||||
@@ -97,7 +97,7 @@ async def run_tool() -> None:
|
||||
print(f"Weather in Amsterdam:\n{weather}")
|
||||
|
||||
|
||||
async def main(scenario: Literal["chat_client", "chat_client_stream", "tool", "all"] = "all"):
|
||||
async def main(scenario: Literal["client", "client_stream", "tool", "all"] = "all"):
|
||||
"""Run the selected scenario(s)."""
|
||||
|
||||
# Setup the logging with the more complete format
|
||||
@@ -148,10 +148,10 @@ async def main(scenario: Literal["chat_client", "chat_client_stream", "tool", "a
|
||||
if scenario == "tool" or scenario == "all":
|
||||
with suppress(Exception):
|
||||
await run_tool()
|
||||
if scenario == "chat_client_stream" or scenario == "all":
|
||||
if scenario == "client_stream" or scenario == "all":
|
||||
with suppress(Exception):
|
||||
await run_chat_client(client, stream=True)
|
||||
if scenario == "chat_client" or scenario == "all":
|
||||
if scenario == "client" or scenario == "all":
|
||||
with suppress(Exception):
|
||||
await run_chat_client(client, stream=False)
|
||||
|
||||
|
||||
@@ -30,32 +30,29 @@ from agent_framework.orchestrations import (
|
||||
|
||||
| Sample | File | Concepts |
|
||||
| ------------------------------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| Concurrent Orchestration (Default Aggregator) | [concurrent_agents.py](./concurrent_agents.py) | Fan-out to multiple agents; fan-in with default aggregator returning combined ChatMessages |
|
||||
| Concurrent Orchestration (Default Aggregator) | [concurrent_agents.py](./concurrent_agents.py) | Fan-out to multiple agents; fan-in with default aggregator returning combined Messages |
|
||||
| Concurrent Orchestration (Custom Aggregator) | [concurrent_custom_aggregator.py](./concurrent_custom_aggregator.py) | Override aggregator via callback; summarize results with an LLM |
|
||||
| Concurrent Orchestration (Custom Agent Executors) | [concurrent_custom_agent_executors.py](./concurrent_custom_agent_executors.py) | Child executors own ChatAgents; concurrent fan-out/fan-in via ConcurrentBuilder |
|
||||
| Concurrent Orchestration (Participant Factory) | [concurrent_participant_factory.py](./concurrent_participant_factory.py) | Use participant factories for state isolation between workflow instances |
|
||||
| Concurrent Orchestration (Custom Agent Executors) | [concurrent_custom_agent_executors.py](./concurrent_custom_agent_executors.py) | Child executors own Agents; concurrent fan-out/fan-in via ConcurrentBuilder |
|
||||
| Group Chat with Agent Manager | [group_chat_agent_manager.py](./group_chat_agent_manager.py) | Agent-based manager using `with_orchestrator(agent=)` to select next speaker |
|
||||
| Group Chat Philosophical Debate | [group_chat_philosophical_debate.py](./group_chat_philosophical_debate.py) | Agent manager moderates long-form, multi-round debate across diverse participants |
|
||||
| Group Chat with Simple Function Selector | [group_chat_simple_selector.py](./group_chat_simple_selector.py) | Group chat with a simple function selector for next speaker |
|
||||
| Handoff (Simple) | [handoff_simple.py](./handoff_simple.py) | Single-tier routing: triage agent routes to specialists, control returns to user after each specialist response |
|
||||
| Handoff (Autonomous) | [handoff_autonomous.py](./handoff_autonomous.py) | Autonomous mode: specialists iterate independently until invoking a handoff tool using `.with_autonomous_mode()` |
|
||||
| Handoff (Participant Factory) | [handoff_participant_factory.py](./handoff_participant_factory.py) | Use participant factories for state isolation between workflow instances |
|
||||
| Handoff with Code Interpreter | [handoff_with_code_interpreter_file.py](./handoff_with_code_interpreter_file.py) | Retrieve file IDs from code interpreter output in handoff workflow |
|
||||
| Magentic Workflow (Multi-Agent) | [magentic.py](./magentic.py) | Orchestrate multiple agents with Magentic manager and streaming |
|
||||
| Magentic + Human Plan Review | [magentic_human_plan_review.py](./magentic_human_plan_review.py) | Human reviews/updates the plan before execution |
|
||||
| Magentic + Checkpoint Resume | [magentic_checkpoint.py](./magentic_checkpoint.py) | Resume Magentic orchestration from saved checkpoints |
|
||||
| Sequential Orchestration (Agents) | [sequential_agents.py](./sequential_agents.py) | Chain agents sequentially with shared conversation context |
|
||||
| Sequential Orchestration (Custom Executor) | [sequential_custom_executors.py](./sequential_custom_executors.py) | Mix agents with a summarizer that appends a compact summary |
|
||||
| Sequential Orchestration (Participant Factories) | [sequential_participant_factory.py](./sequential_participant_factory.py) | Use participant factories for state isolation between workflow instances |
|
||||
|
||||
## Tips
|
||||
|
||||
**Magentic checkpointing tip**: Treat `MagenticBuilder.participants` keys as stable identifiers. When resuming from a checkpoint, the rebuilt workflow must reuse the same participant names; otherwise the checkpoint cannot be applied and the run will fail fast.
|
||||
|
||||
**Handoff workflow tip**: Handoff workflows maintain the full conversation history including any `ChatMessage.additional_properties` emitted by your agents. This ensures routing metadata remains intact across all agent transitions. For specialist-to-specialist handoffs, use `.add_handoff(source, targets)` to configure which agents can route to which others with a fluent, type-safe API.
|
||||
**Handoff workflow tip**: Handoff workflows maintain the full conversation history including any `Message.additional_properties` emitted by your agents. This ensures routing metadata remains intact across all agent transitions. For specialist-to-specialist handoffs, use `.add_handoff(source, targets)` to configure which agents can route to which others with a fluent, type-safe API.
|
||||
|
||||
**Sequential orchestration note**: Sequential orchestration uses a few small adapter nodes for plumbing:
|
||||
- `input-conversation` normalizes input to `list[ChatMessage]`
|
||||
- `input-conversation` normalizes input to `list[Message]`
|
||||
- `to-conversation:<participant>` converts agent responses into the shared conversation
|
||||
- `complete` publishes the final output event (type='output')
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework import Message
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import ConcurrentBuilder
|
||||
from azure.identity import AzureCliCredential
|
||||
@@ -14,7 +14,7 @@ Sample: Concurrent fan-out/fan-in (agent-only API) with default aggregator
|
||||
Build a high-level concurrent workflow using ConcurrentBuilder and three domain agents.
|
||||
The default dispatcher fans out the same user prompt to all agents in parallel.
|
||||
The default aggregator fans in their results and yields output containing
|
||||
a list[ChatMessage] representing the concatenated conversations from all agents.
|
||||
a list[Message] representing the concatenated conversations from all agents.
|
||||
|
||||
Demonstrates:
|
||||
- Minimal wiring with ConcurrentBuilder(participants=[...]).build()
|
||||
@@ -29,9 +29,9 @@ Prerequisites:
|
||||
|
||||
async def main() -> None:
|
||||
# 1) Create three domain agents using AzureOpenAIChatClient
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
researcher = chat_client.as_agent(
|
||||
researcher = client.as_agent(
|
||||
instructions=(
|
||||
"You're an expert market and product researcher. Given a prompt, provide concise, factual insights,"
|
||||
" opportunities, and risks."
|
||||
@@ -39,7 +39,7 @@ async def main() -> None:
|
||||
name="researcher",
|
||||
)
|
||||
|
||||
marketer = chat_client.as_agent(
|
||||
marketer = client.as_agent(
|
||||
instructions=(
|
||||
"You're a creative marketing strategist. Craft compelling value propositions and target messaging"
|
||||
" aligned to the prompt."
|
||||
@@ -47,7 +47,7 @@ async def main() -> None:
|
||||
name="marketer",
|
||||
)
|
||||
|
||||
legal = chat_client.as_agent(
|
||||
legal = client.as_agent(
|
||||
instructions=(
|
||||
"You're a cautious legal/compliance reviewer. Highlight constraints, disclaimers, and policy concerns"
|
||||
" based on the prompt."
|
||||
@@ -66,7 +66,7 @@ async def main() -> None:
|
||||
if outputs:
|
||||
print("===== Final Aggregated Conversation (messages) =====")
|
||||
for output in outputs:
|
||||
messages: list[ChatMessage] | Any = output
|
||||
messages: list[Message] | Any = output
|
||||
for i, msg in enumerate(messages, start=1):
|
||||
name = msg.author_name if msg.author_name else "user"
|
||||
print(f"{'-' * 60}\n\n{i:02d} [{name}]:\n{msg.text}")
|
||||
|
||||
+19
-19
@@ -4,11 +4,11 @@ import asyncio
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import (
|
||||
Agent,
|
||||
AgentExecutorRequest,
|
||||
AgentExecutorResponse,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
Executor,
|
||||
Message,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
)
|
||||
@@ -20,15 +20,15 @@ from azure.identity import AzureCliCredential
|
||||
Sample: Concurrent Orchestration with Custom Agent Executors
|
||||
|
||||
This sample shows a concurrent fan-out/fan-in pattern using child Executor classes
|
||||
that each own their ChatAgent. The executors accept AgentExecutorRequest inputs
|
||||
that each own their Agent. The executors accept AgentExecutorRequest inputs
|
||||
and emit AgentExecutorResponse outputs, which allows reuse of the high-level
|
||||
ConcurrentBuilder API and the default aggregator.
|
||||
|
||||
Demonstrates:
|
||||
- Executors that create their ChatAgent in __init__ (via AzureOpenAIChatClient)
|
||||
- Executors that create their Agent in __init__ (via AzureOpenAIChatClient)
|
||||
- A @handler that converts AgentExecutorRequest -> AgentExecutorResponse
|
||||
- ConcurrentBuilder(participants=[...]) to build fan-out/fan-in
|
||||
- Default aggregator returning list[ChatMessage] (one user + one assistant per agent)
|
||||
- Default aggregator returning list[Message] (one user + one assistant per agent)
|
||||
- Workflow completion when all participants become idle
|
||||
|
||||
Prerequisites:
|
||||
@@ -37,10 +37,10 @@ Prerequisites:
|
||||
|
||||
|
||||
class ResearcherExec(Executor):
|
||||
agent: ChatAgent
|
||||
agent: Agent
|
||||
|
||||
def __init__(self, chat_client: AzureOpenAIChatClient, id: str = "researcher"):
|
||||
self.agent = chat_client.as_agent(
|
||||
def __init__(self, client: AzureOpenAIChatClient, id: str = "researcher"):
|
||||
self.agent = client.as_agent(
|
||||
instructions=(
|
||||
"You're an expert market and product researcher. Given a prompt, provide concise, factual insights,"
|
||||
" opportunities, and risks."
|
||||
@@ -57,10 +57,10 @@ class ResearcherExec(Executor):
|
||||
|
||||
|
||||
class MarketerExec(Executor):
|
||||
agent: ChatAgent
|
||||
agent: Agent
|
||||
|
||||
def __init__(self, chat_client: AzureOpenAIChatClient, id: str = "marketer"):
|
||||
self.agent = chat_client.as_agent(
|
||||
def __init__(self, client: AzureOpenAIChatClient, id: str = "marketer"):
|
||||
self.agent = client.as_agent(
|
||||
instructions=(
|
||||
"You're a creative marketing strategist. Craft compelling value propositions and target messaging"
|
||||
" aligned to the prompt."
|
||||
@@ -77,10 +77,10 @@ class MarketerExec(Executor):
|
||||
|
||||
|
||||
class LegalExec(Executor):
|
||||
agent: ChatAgent
|
||||
agent: Agent
|
||||
|
||||
def __init__(self, chat_client: AzureOpenAIChatClient, id: str = "legal"):
|
||||
self.agent = chat_client.as_agent(
|
||||
def __init__(self, client: AzureOpenAIChatClient, id: str = "legal"):
|
||||
self.agent = client.as_agent(
|
||||
instructions=(
|
||||
"You're a cautious legal/compliance reviewer. Highlight constraints, disclaimers, and policy concerns"
|
||||
" based on the prompt."
|
||||
@@ -97,11 +97,11 @@ class LegalExec(Executor):
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
researcher = ResearcherExec(chat_client)
|
||||
marketer = MarketerExec(chat_client)
|
||||
legal = LegalExec(chat_client)
|
||||
researcher = ResearcherExec(client)
|
||||
marketer = MarketerExec(client)
|
||||
legal = LegalExec(client)
|
||||
|
||||
workflow = ConcurrentBuilder(participants=[researcher, marketer, legal]).build()
|
||||
|
||||
@@ -110,7 +110,7 @@ async def main() -> None:
|
||||
|
||||
if outputs:
|
||||
print("===== Final Aggregated Conversation (messages) =====")
|
||||
messages: list[ChatMessage] | Any = outputs[0] # Get the first (and typically only) output
|
||||
messages: list[Message] | Any = outputs[0] # Get the first (and typically only) output
|
||||
for i, msg in enumerate(messages, start=1):
|
||||
name = msg.author_name if msg.author_name else "user"
|
||||
print(f"{'-' * 60}\n\n{i:02d} [{name}]:\n{msg.text}")
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework import Message
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import ConcurrentBuilder
|
||||
from azure.identity import AzureCliCredential
|
||||
@@ -20,7 +20,7 @@ The workflow completes when all participants become idle.
|
||||
Demonstrates:
|
||||
- ConcurrentBuilder(participants=[...]).with_aggregator(callback)
|
||||
- Fan-out to agents and fan-in at an aggregator
|
||||
- Aggregation implemented via an LLM call (chat_client.get_response)
|
||||
- Aggregation implemented via an LLM call (client.get_response)
|
||||
- Workflow output yielded with the synthesized summary string
|
||||
|
||||
Prerequisites:
|
||||
@@ -29,23 +29,23 @@ Prerequisites:
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
researcher = chat_client.as_agent(
|
||||
researcher = client.as_agent(
|
||||
instructions=(
|
||||
"You're an expert market and product researcher. Given a prompt, provide concise, factual insights,"
|
||||
" opportunities, and risks."
|
||||
),
|
||||
name="researcher",
|
||||
)
|
||||
marketer = chat_client.as_agent(
|
||||
marketer = client.as_agent(
|
||||
instructions=(
|
||||
"You're a creative marketing strategist. Craft compelling value propositions and target messaging"
|
||||
" aligned to the prompt."
|
||||
),
|
||||
name="marketer",
|
||||
)
|
||||
legal = chat_client.as_agent(
|
||||
legal = client.as_agent(
|
||||
instructions=(
|
||||
"You're a cautious legal/compliance reviewer. Highlight constraints, disclaimers, and policy concerns"
|
||||
" based on the prompt."
|
||||
@@ -66,16 +66,16 @@ async def main() -> None:
|
||||
expert_sections.append(f"{getattr(r, 'executor_id', 'expert')}: (error: {type(e).__name__}: {e})")
|
||||
|
||||
# Ask the model to synthesize a concise summary of the experts' outputs
|
||||
system_msg = ChatMessage(
|
||||
system_msg = Message(
|
||||
"system",
|
||||
text=(
|
||||
"You are a helpful assistant that consolidates multiple domain expert outputs "
|
||||
"into one cohesive, concise summary with clear takeaways. Keep it under 200 words."
|
||||
),
|
||||
)
|
||||
user_msg = ChatMessage("user", text="\n\n".join(expert_sections))
|
||||
user_msg = Message("user", text="\n\n".join(expert_sections))
|
||||
|
||||
response = await chat_client.get_response([system_msg, user_msg])
|
||||
response = await client.get_response([system_msg, user_msg])
|
||||
# Return the model's final assistant text as the completion result
|
||||
return response.messages[-1].text if response.messages else ""
|
||||
|
||||
@@ -83,7 +83,7 @@ async def main() -> None:
|
||||
# - participants([...]) accepts SupportsAgentRun (agents) or Executor instances.
|
||||
# Each participant becomes a parallel branch (fan-out) from an internal dispatcher.
|
||||
# - with_aggregator(...) overrides the default aggregator:
|
||||
# • Default aggregator -> returns list[ChatMessage] (one user + one assistant per agent)
|
||||
# • Default aggregator -> returns list[Message] (one user + one assistant per agent)
|
||||
# • Custom callback -> return value becomes workflow output (string here)
|
||||
# The callback can be sync or async; it receives list[AgentExecutorResponse].
|
||||
workflow = (
|
||||
|
||||
@@ -4,9 +4,9 @@ import asyncio
|
||||
from typing import cast
|
||||
|
||||
from agent_framework import (
|
||||
Agent,
|
||||
AgentResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
Message,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import GroupChatBuilder
|
||||
@@ -17,7 +17,7 @@ Sample: Group Chat with Agent-Based Manager
|
||||
|
||||
What it does:
|
||||
- Demonstrates the new set_manager() API for agent-based coordination
|
||||
- Manager is a full ChatAgent with access to tools, context, and observability
|
||||
- Manager is a full Agent with access to tools, context, and observability
|
||||
- Coordinates a researcher and writer agent to solve tasks collaboratively
|
||||
|
||||
Prerequisites:
|
||||
@@ -36,32 +36,32 @@ Guidelines:
|
||||
|
||||
async def main() -> None:
|
||||
# Create a chat client using Azure OpenAI and Azure CLI credentials for all agents
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
# Orchestrator agent that manages the conversation
|
||||
# Note: This agent (and the underlying chat client) must support structured outputs.
|
||||
# The group chat workflow relies on this to parse the orchestrator's decisions.
|
||||
# `response_format` is set internally by the GroupChat workflow when the agent is invoked.
|
||||
orchestrator_agent = ChatAgent(
|
||||
orchestrator_agent = Agent(
|
||||
name="Orchestrator",
|
||||
description="Coordinates multi-agent collaboration by selecting speakers",
|
||||
instructions=ORCHESTRATOR_AGENT_INSTRUCTIONS,
|
||||
chat_client=chat_client,
|
||||
client=client,
|
||||
)
|
||||
|
||||
# Participant agents
|
||||
researcher = ChatAgent(
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
description="Collects relevant background information",
|
||||
instructions="Gather concise facts that help a teammate answer the question.",
|
||||
chat_client=chat_client,
|
||||
client=client,
|
||||
)
|
||||
|
||||
writer = ChatAgent(
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
description="Synthesizes polished answers from gathered information",
|
||||
instructions="Compose clear and structured answers using any notes provided.",
|
||||
chat_client=chat_client,
|
||||
client=client,
|
||||
)
|
||||
|
||||
# Build the group chat workflow
|
||||
@@ -103,7 +103,7 @@ async def main() -> None:
|
||||
print(data.text, end="", flush=True)
|
||||
elif event.type == "output":
|
||||
# The output of the group chat workflow is a collection of chat messages from all participants
|
||||
outputs = cast(list[ChatMessage], event.data)
|
||||
outputs = cast(list[Message], event.data)
|
||||
print("\n" + "=" * 80)
|
||||
print("\nFinal Conversation Transcript:\n")
|
||||
for message in outputs:
|
||||
|
||||
@@ -5,9 +5,9 @@ import logging
|
||||
from typing import cast
|
||||
|
||||
from agent_framework import (
|
||||
Agent,
|
||||
AgentResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
Message,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import GroupChatBuilder
|
||||
@@ -48,7 +48,7 @@ def _get_chat_client() -> AzureOpenAIChatClient:
|
||||
async def main() -> None:
|
||||
# Create debate moderator with structured output for speaker selection
|
||||
# Note: Participant names and descriptions are automatically injected by the orchestrator
|
||||
moderator = ChatAgent(
|
||||
moderator = Agent(
|
||||
name="Moderator",
|
||||
description="Guides philosophical discussion by selecting next speaker",
|
||||
instructions="""
|
||||
@@ -75,10 +75,10 @@ Finish when:
|
||||
|
||||
In your final_message, provide a brief synthesis highlighting key themes that emerged.
|
||||
""",
|
||||
chat_client=_get_chat_client(),
|
||||
client=_get_chat_client(),
|
||||
)
|
||||
|
||||
farmer = ChatAgent(
|
||||
farmer = Agent(
|
||||
name="Farmer",
|
||||
description="A rural farmer from Southeast Asia",
|
||||
instructions="""
|
||||
@@ -91,10 +91,10 @@ Share your perspective authentically. Feel free to:
|
||||
- Use concrete examples from your experience
|
||||
- Keep responses thoughtful but concise (2-4 sentences)
|
||||
""",
|
||||
chat_client=_get_chat_client(),
|
||||
client=_get_chat_client(),
|
||||
)
|
||||
|
||||
developer = ChatAgent(
|
||||
developer = Agent(
|
||||
name="Developer",
|
||||
description="An urban software developer from the United States",
|
||||
instructions="""
|
||||
@@ -107,10 +107,10 @@ Share your perspective authentically. Feel free to:
|
||||
- Use concrete examples from your experience
|
||||
- Keep responses thoughtful but concise (2-4 sentences)
|
||||
""",
|
||||
chat_client=_get_chat_client(),
|
||||
client=_get_chat_client(),
|
||||
)
|
||||
|
||||
teacher = ChatAgent(
|
||||
teacher = Agent(
|
||||
name="Teacher",
|
||||
description="A retired history teacher from Eastern Europe",
|
||||
instructions="""
|
||||
@@ -124,10 +124,10 @@ Share your perspective authentically. Feel free to:
|
||||
- Use concrete examples from history or your teaching experience
|
||||
- Keep responses thoughtful but concise (2-4 sentences)
|
||||
""",
|
||||
chat_client=_get_chat_client(),
|
||||
client=_get_chat_client(),
|
||||
)
|
||||
|
||||
activist = ChatAgent(
|
||||
activist = Agent(
|
||||
name="Activist",
|
||||
description="A young activist from South America",
|
||||
instructions="""
|
||||
@@ -140,10 +140,10 @@ Share your perspective authentically. Feel free to:
|
||||
- Use concrete examples from your activism
|
||||
- Keep responses thoughtful but concise (2-4 sentences)
|
||||
""",
|
||||
chat_client=_get_chat_client(),
|
||||
client=_get_chat_client(),
|
||||
)
|
||||
|
||||
spiritual_leader = ChatAgent(
|
||||
spiritual_leader = Agent(
|
||||
name="SpiritualLeader",
|
||||
description="A spiritual leader from the Middle East",
|
||||
instructions="""
|
||||
@@ -156,10 +156,10 @@ Share your perspective authentically. Feel free to:
|
||||
- Use examples from spiritual teachings or community work
|
||||
- Keep responses thoughtful but concise (2-4 sentences)
|
||||
""",
|
||||
chat_client=_get_chat_client(),
|
||||
client=_get_chat_client(),
|
||||
)
|
||||
|
||||
artist = ChatAgent(
|
||||
artist = Agent(
|
||||
name="Artist",
|
||||
description="An artist from Africa",
|
||||
instructions="""
|
||||
@@ -172,10 +172,10 @@ Share your perspective authentically. Feel free to:
|
||||
- Use examples from your art or cultural traditions
|
||||
- Keep responses thoughtful but concise (2-4 sentences)
|
||||
""",
|
||||
chat_client=_get_chat_client(),
|
||||
client=_get_chat_client(),
|
||||
)
|
||||
|
||||
immigrant = ChatAgent(
|
||||
immigrant = Agent(
|
||||
name="Immigrant",
|
||||
description="An immigrant entrepreneur from Asia living in Canada",
|
||||
instructions="""
|
||||
@@ -188,10 +188,10 @@ Share your perspective authentically. Feel free to:
|
||||
- Use examples from your immigrant and entrepreneurial journey
|
||||
- Keep responses thoughtful but concise (2-4 sentences)
|
||||
""",
|
||||
chat_client=_get_chat_client(),
|
||||
client=_get_chat_client(),
|
||||
)
|
||||
|
||||
doctor = ChatAgent(
|
||||
doctor = Agent(
|
||||
name="Doctor",
|
||||
description="A doctor from Scandinavia",
|
||||
instructions="""
|
||||
@@ -204,7 +204,7 @@ Share your perspective authentically. Feel free to:
|
||||
- Use examples from healthcare and societal systems
|
||||
- Keep responses thoughtful but concise (2-4 sentences)
|
||||
""",
|
||||
chat_client=_get_chat_client(),
|
||||
client=_get_chat_client(),
|
||||
)
|
||||
|
||||
# termination_condition: stop after 10 assistant messages
|
||||
@@ -255,7 +255,7 @@ Share your perspective authentically. Feel free to:
|
||||
print(data.text, end="", flush=True)
|
||||
elif event.type == "output":
|
||||
# The output of the group chat workflow is a collection of chat messages from all participants
|
||||
outputs = cast(list[ChatMessage], event.data)
|
||||
outputs = cast(list[Message], event.data)
|
||||
print("\n" + "=" * 80)
|
||||
print("\nFinal Conversation Transcript:\n")
|
||||
for message in outputs:
|
||||
|
||||
@@ -4,9 +4,9 @@ import asyncio
|
||||
from typing import cast
|
||||
|
||||
from agent_framework import (
|
||||
Agent,
|
||||
AgentResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
Message,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import GroupChatBuilder, GroupChatState
|
||||
@@ -33,20 +33,20 @@ def round_robin_selector(state: GroupChatState) -> str:
|
||||
|
||||
async def main() -> None:
|
||||
# Create a chat client using Azure OpenAI and Azure CLI credentials for all agents
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
# Participant agents
|
||||
expert = ChatAgent(
|
||||
expert = Agent(
|
||||
name="PythonExpert",
|
||||
instructions=(
|
||||
"You are an expert in Python in a workgroup. "
|
||||
"Your job is to answer Python related questions and refine your answer "
|
||||
"based on feedback from all the other participants."
|
||||
),
|
||||
chat_client=chat_client,
|
||||
client=client,
|
||||
)
|
||||
|
||||
verifier = ChatAgent(
|
||||
verifier = Agent(
|
||||
name="AnswerVerifier",
|
||||
instructions=(
|
||||
"You are a programming expert in a workgroup. "
|
||||
@@ -54,10 +54,10 @@ async def main() -> None:
|
||||
"out statements that are technically true but practically dangerous."
|
||||
"If there is nothing woth pointing out, respond with 'The answer looks good to me.'"
|
||||
),
|
||||
chat_client=chat_client,
|
||||
client=client,
|
||||
)
|
||||
|
||||
clarifier = ChatAgent(
|
||||
clarifier = Agent(
|
||||
name="AnswerClarifier",
|
||||
instructions=(
|
||||
"You are an accessibility expert in a workgroup. "
|
||||
@@ -65,10 +65,10 @@ async def main() -> None:
|
||||
"out jargons or complex terms that may be difficult for a beginner to understand."
|
||||
"If there is nothing worth pointing out, respond with 'The answer looks clear to me.'"
|
||||
),
|
||||
chat_client=chat_client,
|
||||
client=client,
|
||||
)
|
||||
|
||||
skeptic = ChatAgent(
|
||||
skeptic = Agent(
|
||||
name="Skeptic",
|
||||
instructions=(
|
||||
"You are a devil's advocate in a workgroup. "
|
||||
@@ -76,7 +76,7 @@ async def main() -> None:
|
||||
"out caveats, exceptions, and alternative perspectives."
|
||||
"If there is nothing worth pointing out, respond with 'I have no further questions.'"
|
||||
),
|
||||
chat_client=chat_client,
|
||||
client=client,
|
||||
)
|
||||
|
||||
# Build the group chat workflow
|
||||
@@ -124,7 +124,7 @@ async def main() -> None:
|
||||
print(data.text, end="", flush=True)
|
||||
elif event.type == "output":
|
||||
# The output of the group chat workflow is a collection of chat messages from all participants
|
||||
outputs = cast(list[ChatMessage], event.data)
|
||||
outputs = cast(list[Message], event.data)
|
||||
print("\n" + "=" * 80)
|
||||
print("\nFinal Conversation Transcript:\n")
|
||||
for message in outputs:
|
||||
|
||||
@@ -5,9 +5,9 @@ import logging
|
||||
from typing import cast
|
||||
|
||||
from agent_framework import (
|
||||
Agent,
|
||||
AgentResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
Message,
|
||||
resolve_agent_id,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
@@ -37,10 +37,10 @@ Key Concepts:
|
||||
|
||||
|
||||
def create_agents(
|
||||
chat_client: AzureOpenAIChatClient,
|
||||
) -> tuple[ChatAgent, ChatAgent, ChatAgent]:
|
||||
client: AzureOpenAIChatClient,
|
||||
) -> tuple[Agent, Agent, Agent]:
|
||||
"""Create coordinator and specialists for autonomous iteration."""
|
||||
coordinator = chat_client.as_agent(
|
||||
coordinator = client.as_agent(
|
||||
instructions=(
|
||||
"You are a coordinator. You break down a user query into a research task and a summary task. "
|
||||
"Assign the two tasks to the appropriate specialists, one after the other."
|
||||
@@ -48,7 +48,7 @@ def create_agents(
|
||||
name="coordinator",
|
||||
)
|
||||
|
||||
research_agent = chat_client.as_agent(
|
||||
research_agent = client.as_agent(
|
||||
instructions=(
|
||||
"You are a research specialist that explores topics thoroughly using web search. "
|
||||
"When given a research task, break it down into multiple aspects and explore each one. "
|
||||
@@ -60,7 +60,7 @@ def create_agents(
|
||||
name="research_agent",
|
||||
)
|
||||
|
||||
summary_agent = chat_client.as_agent(
|
||||
summary_agent = client.as_agent(
|
||||
instructions=(
|
||||
"You summarize research findings. Provide a concise, well-organized summary. When done, return "
|
||||
"control to the coordinator."
|
||||
@@ -73,8 +73,8 @@ def create_agents(
|
||||
|
||||
async def main() -> None:
|
||||
"""Run an autonomous handoff workflow with specialist iteration enabled."""
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
coordinator, research_agent, summary_agent = create_agents(chat_client)
|
||||
client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
coordinator, research_agent, summary_agent = create_agents(client)
|
||||
|
||||
# Build the workflow with autonomous mode
|
||||
# In autonomous mode, agents continue iterating until they invoke a handoff tool
|
||||
@@ -129,7 +129,7 @@ async def main() -> None:
|
||||
print(data.text, end="", flush=True)
|
||||
elif event.type == "output":
|
||||
# The output of the handoff workflow is a collection of chat messages from all participants
|
||||
outputs = cast(list[ChatMessage], event.data)
|
||||
outputs = cast(list[Message], event.data)
|
||||
print("\n" + "=" * 80)
|
||||
print("\nFinal Conversation Transcript:\n")
|
||||
for message in outputs:
|
||||
|
||||
@@ -4,9 +4,9 @@ import asyncio
|
||||
from typing import Annotated, cast
|
||||
|
||||
from agent_framework import (
|
||||
Agent,
|
||||
AgentResponse,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
Message,
|
||||
WorkflowEvent,
|
||||
WorkflowRunState,
|
||||
tool,
|
||||
@@ -54,17 +54,17 @@ def process_return(order_number: Annotated[str, "Order number to process return
|
||||
return f"Return initiated successfully for order {order_number}. You will receive return instructions via email."
|
||||
|
||||
|
||||
def create_agents(chat_client: AzureOpenAIChatClient) -> tuple[ChatAgent, ChatAgent, ChatAgent, ChatAgent]:
|
||||
def create_agents(client: AzureOpenAIChatClient) -> tuple[Agent, Agent, Agent, Agent]:
|
||||
"""Create and configure the triage and specialist agents.
|
||||
|
||||
Args:
|
||||
chat_client: The AzureOpenAIChatClient to use for creating agents.
|
||||
client: The AzureOpenAIChatClient to use for creating agents.
|
||||
|
||||
Returns:
|
||||
Tuple of (triage_agent, refund_agent, order_agent, return_agent)
|
||||
"""
|
||||
# Triage agent: Acts as the frontline dispatcher
|
||||
triage_agent = chat_client.as_agent(
|
||||
triage_agent = client.as_agent(
|
||||
instructions=(
|
||||
"You are frontline support triage. Route customer issues to the appropriate specialist agents "
|
||||
"based on the problem described."
|
||||
@@ -73,7 +73,7 @@ def create_agents(chat_client: AzureOpenAIChatClient) -> tuple[ChatAgent, ChatAg
|
||||
)
|
||||
|
||||
# Refund specialist: Handles refund requests
|
||||
refund_agent = chat_client.as_agent(
|
||||
refund_agent = client.as_agent(
|
||||
instructions="You process refund requests.",
|
||||
name="refund_agent",
|
||||
# In a real application, an agent can have multiple tools; here we keep it simple
|
||||
@@ -81,7 +81,7 @@ def create_agents(chat_client: AzureOpenAIChatClient) -> tuple[ChatAgent, ChatAg
|
||||
)
|
||||
|
||||
# Order/shipping specialist: Resolves delivery issues
|
||||
order_agent = chat_client.as_agent(
|
||||
order_agent = client.as_agent(
|
||||
instructions="You handle order and shipping inquiries.",
|
||||
name="order_agent",
|
||||
# In a real application, an agent can have multiple tools; here we keep it simple
|
||||
@@ -89,7 +89,7 @@ def create_agents(chat_client: AzureOpenAIChatClient) -> tuple[ChatAgent, ChatAg
|
||||
)
|
||||
|
||||
# Return specialist: Handles return requests
|
||||
return_agent = chat_client.as_agent(
|
||||
return_agent = client.as_agent(
|
||||
instructions="You manage product return requests.",
|
||||
name="return_agent",
|
||||
# In a real application, an agent can have multiple tools; here we keep it simple
|
||||
@@ -138,7 +138,7 @@ def _handle_events(events: list[WorkflowEvent]) -> list[WorkflowEvent[HandoffAge
|
||||
print(f"- {speaker}: {message.text}")
|
||||
elif event.type == "output":
|
||||
# The output of the handoff workflow is a collection of chat messages from all participants
|
||||
conversation = cast(list[ChatMessage], event.data)
|
||||
conversation = cast(list[Message], event.data)
|
||||
if isinstance(conversation, list):
|
||||
print("\n=== Final Conversation Snapshot ===")
|
||||
for message in conversation:
|
||||
@@ -189,10 +189,10 @@ async def main() -> None:
|
||||
replace the scripted_responses with actual user input collection.
|
||||
"""
|
||||
# Initialize the Azure OpenAI chat client
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
# Create all agents: triage + specialists
|
||||
triage, refund, order, support = create_agents(chat_client)
|
||||
triage, refund, order, support = create_agents(client)
|
||||
|
||||
# Build the handoff workflow
|
||||
# - participants: All agents that can participate in the workflow
|
||||
|
||||
@@ -31,10 +31,10 @@ from contextlib import asynccontextmanager
|
||||
from typing import cast
|
||||
|
||||
from agent_framework import (
|
||||
Agent,
|
||||
AgentResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
HostedCodeInterpreterTool,
|
||||
Message,
|
||||
WorkflowEvent,
|
||||
WorkflowRunState,
|
||||
)
|
||||
@@ -83,7 +83,7 @@ def _handle_events(events: list[WorkflowEvent]) -> tuple[list[WorkflowEvent[Hand
|
||||
file_ids.append(file_id)
|
||||
print(f"[Found file annotation: file_id={file_id}]")
|
||||
elif event.type == "output":
|
||||
conversation = cast(list[ChatMessage], event.data)
|
||||
conversation = cast(list[Message], event.data)
|
||||
if isinstance(conversation, list):
|
||||
print("\n=== Final Conversation Snapshot ===")
|
||||
for message in conversation:
|
||||
@@ -95,7 +95,7 @@ def _handle_events(events: list[WorkflowEvent]) -> tuple[list[WorkflowEvent[Hand
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def create_agents_v1(credential: AzureCliCredential) -> AsyncIterator[tuple[ChatAgent, ChatAgent]]:
|
||||
async def create_agents_v1(credential: AzureCliCredential) -> AsyncIterator[tuple[Agent, Agent]]:
|
||||
"""Create agents using V1 AzureAIAgentClient."""
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
|
||||
@@ -122,7 +122,7 @@ async def create_agents_v1(credential: AzureCliCredential) -> AsyncIterator[tupl
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def create_agents_v2(credential: AzureCliCredential) -> AsyncIterator[tuple[ChatAgent, ChatAgent]]:
|
||||
async def create_agents_v2(credential: AzureCliCredential) -> AsyncIterator[tuple[Agent, Agent]]:
|
||||
"""Create agents using V2 AzureAIClient.
|
||||
|
||||
Each agent needs its own client instance because the V2 client binds
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user