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
@@ -5,11 +5,11 @@ import os
from typing import Any
from agent_framework import ( # Core chat primitives used to build requests
Agent,
AgentExecutor,
AgentExecutorRequest, # Input message bundle for an AgentExecutor
AgentExecutorResponse,
ChatAgent, # Output from an AgentExecutor
ChatMessage,
Message,
WorkflowBuilder, # Fluent builder for wiring executors and edges
WorkflowContext, # Per-run context and event bus
executor, # Decorator to declare a Python function as a workflow executor
@@ -122,13 +122,13 @@ async def to_email_assistant_request(
Extracts DetectionResult.email_content and forwards it as a user message.
"""
# Bridge executor. Converts a structured DetectionResult into a ChatMessage and forwards it as a new request.
# Bridge executor. Converts a structured DetectionResult into a Message and forwards it as a new request.
detection = DetectionResult.model_validate_json(response.agent_response.text)
user_msg = ChatMessage("user", text=detection.email_content)
user_msg = Message("user", text=detection.email_content)
await ctx.send_message(AgentExecutorRequest(messages=[user_msg], should_respond=True))
def create_spam_detector_agent() -> ChatAgent:
def create_spam_detector_agent() -> Agent:
"""Helper to create a spam detection agent."""
# AzureCliCredential uses your current az login. This avoids embedding secrets in code.
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
@@ -142,7 +142,7 @@ def create_spam_detector_agent() -> ChatAgent:
)
def create_email_assistant_agent() -> ChatAgent:
def create_email_assistant_agent() -> Agent:
"""Helper to create an email assistant agent."""
# AzureCliCredential uses your current az login. This avoids embedding secrets in code.
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
@@ -185,7 +185,7 @@ async def main() -> None:
# Execute the workflow. Since the start is an AgentExecutor, pass an AgentExecutorRequest.
# The workflow completes when it becomes idle (no more work to do).
request = AgentExecutorRequest(messages=[ChatMessage("user", text=email)], should_respond=True)
request = AgentExecutorRequest(messages=[Message("user", text=email)], should_respond=True)
events = await workflow.run(request)
outputs = events.get_outputs()
if outputs:
@@ -9,11 +9,11 @@ from typing import Literal
from uuid import uuid4
from agent_framework import (
Agent,
AgentExecutor,
AgentExecutorRequest,
AgentExecutorResponse,
ChatAgent,
ChatMessage,
Message,
WorkflowBuilder,
WorkflowContext,
WorkflowEvent,
@@ -91,7 +91,7 @@ async def store_email(email_text: str, ctx: WorkflowContext[AgentExecutorRequest
ctx.set_state(CURRENT_EMAIL_ID_KEY, new_email.email_id)
await ctx.send_message(
AgentExecutorRequest(messages=[ChatMessage("user", text=new_email.email_content)], should_respond=True)
AgentExecutorRequest(messages=[Message("user", text=new_email.email_content)], should_respond=True)
)
@@ -118,7 +118,7 @@ async def submit_to_email_assistant(analysis: AnalysisResult, ctx: WorkflowConte
email: Email = ctx.get_state(f"{EMAIL_STATE_PREFIX}{analysis.email_id}")
await ctx.send_message(
AgentExecutorRequest(messages=[ChatMessage("user", text=email.email_content)], should_respond=True)
AgentExecutorRequest(messages=[Message("user", text=email.email_content)], should_respond=True)
)
@@ -133,7 +133,7 @@ async def summarize_email(analysis: AnalysisResult, ctx: WorkflowContext[AgentEx
# Only called for long NotSpam emails by selection_func
email: Email = ctx.get_state(f"{EMAIL_STATE_PREFIX}{analysis.email_id}")
await ctx.send_message(
AgentExecutorRequest(messages=[ChatMessage("user", text=email.email_content)], should_respond=True)
AgentExecutorRequest(messages=[Message("user", text=email.email_content)], should_respond=True)
)
@@ -180,7 +180,7 @@ async def database_access(analysis: AnalysisResult, ctx: WorkflowContext[Never,
await ctx.add_event(DatabaseEvent(f"Email {analysis.email_id} saved to database."))
def create_email_analysis_agent() -> ChatAgent:
def create_email_analysis_agent() -> Agent:
"""Creates the email analysis agent."""
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
instructions=(
@@ -193,7 +193,7 @@ def create_email_analysis_agent() -> ChatAgent:
)
def create_email_assistant_agent() -> ChatAgent:
def create_email_assistant_agent() -> Agent:
"""Creates the email assistant agent."""
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
instructions=("You are an email assistant that helps users draft responses to emails with professionalism."),
@@ -202,7 +202,7 @@ def create_email_assistant_agent() -> ChatAgent:
)
def create_email_summary_agent() -> ChatAgent:
def create_email_summary_agent() -> Agent:
"""Creates the email summary agent."""
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
instructions=("You are an assistant that helps users summarize emails."),
@@ -4,12 +4,12 @@ import asyncio
from enum import Enum
from agent_framework import (
Agent,
AgentExecutor,
AgentExecutorRequest,
AgentExecutorResponse,
ChatAgent,
ChatMessage,
Executor,
Message,
WorkflowBuilder,
WorkflowContext,
handler,
@@ -95,7 +95,7 @@ class SubmitToJudgeAgent(Executor):
f"Target: {self._target}\nGuess: {guess}\nResponse:"
)
await ctx.send_message(
AgentExecutorRequest(messages=[ChatMessage("user", text=prompt)], should_respond=True),
AgentExecutorRequest(messages=[Message("user", text=prompt)], should_respond=True),
target_id=self._judge_agent_id,
)
@@ -114,7 +114,7 @@ class ParseJudgeResponse(Executor):
await ctx.send_message(NumberSignal.BELOW)
def create_judge_agent() -> ChatAgent:
def create_judge_agent() -> Agent:
"""Create a judge agent that evaluates guesses."""
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
instructions=("You strictly respond with one of: MATCHED, ABOVE, BELOW based on the given target and guess."),
@@ -7,13 +7,13 @@ from typing import Any, Literal
from uuid import uuid4
from agent_framework import ( # Core chat primitives used to form LLM requests
Agent,
AgentExecutor,
AgentExecutorRequest, # Message bundle sent to an AgentExecutor
AgentExecutorResponse, # Result returned by an AgentExecutor
Case,
ChatAgent, # Case entry for a switch-case edge group
ChatMessage,
Default, # Default branch when no cases match
Message,
WorkflowBuilder, # Fluent builder for assembling the graph
WorkflowContext, # Per-run context and event bus
executor, # Decorator to turn a function into a workflow executor
@@ -99,7 +99,7 @@ async def store_email(email_text: str, ctx: WorkflowContext[AgentExecutorRequest
# Kick off the detector by forwarding the email as a user message to the spam_detection_agent.
await ctx.send_message(
AgentExecutorRequest(messages=[ChatMessage("user", text=new_email.email_content)], should_respond=True)
AgentExecutorRequest(messages=[Message("user", text=new_email.email_content)], should_respond=True)
)
@@ -120,7 +120,7 @@ async def submit_to_email_assistant(detection: DetectionResult, ctx: WorkflowCon
# Load the original content from workflow state using the id carried in DetectionResult.
email: Email = ctx.get_state(f"{EMAIL_STATE_PREFIX}{detection.email_id}")
await ctx.send_message(
AgentExecutorRequest(messages=[ChatMessage("user", text=email.email_content)], should_respond=True)
AgentExecutorRequest(messages=[Message("user", text=email.email_content)], should_respond=True)
)
@@ -152,7 +152,7 @@ async def handle_uncertain(detection: DetectionResult, ctx: WorkflowContext[Neve
raise RuntimeError("This executor should only handle Uncertain messages.")
def create_spam_detection_agent() -> ChatAgent:
def create_spam_detection_agent() -> Agent:
"""Create and return the spam detection agent."""
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
instructions=(
@@ -166,7 +166,7 @@ def create_spam_detection_agent() -> ChatAgent:
)
def create_email_assistant_agent() -> ChatAgent:
def create_email_assistant_agent() -> Agent:
"""Create and return the email assistant agent."""
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
instructions=("You are an email assistant that helps users draft responses to emails with professionalism."),