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:
Eduard van Valkenburg
2026-02-11 00:04:32 +01:00
committed by GitHub
Unverified
parent a4c9e43afb
commit 0521f5bed8
418 changed files with 5385 additions and 5389 deletions
@@ -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,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,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:
@@ -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")],
)