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
@@ -161,7 +161,7 @@ Notes
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')
These may appear in event streams (executor_invoked/executor_completed). They're analogous to
@@ -27,15 +27,15 @@ Prerequisites:
async def main():
"""Build and run a simple two node agent workflow: Writer then Reviewer."""
# Create the Azure chat client. AzureCliCredential uses your current az login.
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
writer_agent = chat_client.as_agent(
client = AzureOpenAIChatClient(credential=AzureCliCredential())
writer_agent = client.as_agent(
instructions=(
"You are an excellent content writer. You create new content and edit contents based on the feedback."
),
name="writer",
)
reviewer_agent = chat_client.as_agent(
reviewer_agent = client.as_agent(
instructions=(
"You are an excellent content reviewer."
"Provide actionable feedback to the writer about the provided content."
@@ -2,7 +2,7 @@
import asyncio
from agent_framework import AgentResponseUpdate, ChatMessage, WorkflowBuilder
from agent_framework import AgentResponseUpdate, Message, WorkflowBuilder
from agent_framework.azure import AzureOpenAIChatClient
from azure.identity import AzureCliCredential
@@ -26,15 +26,15 @@ Prerequisites:
async def main():
"""Build the two node workflow and run it with streaming to observe events."""
# Create the Azure chat client. AzureCliCredential uses your current az login.
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
writer_agent = chat_client.as_agent(
client = AzureOpenAIChatClient(credential=AzureCliCredential())
writer_agent = client.as_agent(
instructions=(
"You are an excellent content writer. You create new content and edit contents based on the feedback."
),
name="writer",
)
reviewer_agent = chat_client.as_agent(
reviewer_agent = client.as_agent(
instructions=(
"You are an excellent content reviewer."
"Provide actionable feedback to the writer about the provided content."
@@ -52,7 +52,7 @@ async def main():
# Run the workflow with the user's initial message and stream events as they occur.
async for event in workflow.run(
ChatMessage("user", ["Create a slogan for a new electric SUV that is affordable and fun to drive."]),
Message("user", ["Create a slogan for a new electric SUV that is affordable and fun to drive."]),
stream=True,
):
# The outputs of the workflow are whatever the agents produce. So the events are expected to
@@ -7,7 +7,7 @@ from agent_framework import (
AgentExecutorRequest,
AgentExecutorResponse,
AgentResponseUpdate,
ChatMessage,
Message,
WorkflowBuilder,
WorkflowContext,
executor,
@@ -84,7 +84,7 @@ async def enrich_with_references(
f"{external_note}\n\n"
"Please update the prior assistant answer so it weaves this note into the guidance."
)
conversation.append(ChatMessage("user", [follow_up]))
conversation.append(Message("user", [follow_up]))
# Output a new AgentExecutorRequest for the next agent in the workflow.
# Agents in workflows handle this type and will generate a response based on the request.
@@ -6,14 +6,14 @@ from dataclasses import dataclass, field
from typing import Annotated
from agent_framework import (
Agent,
AgentExecutor,
AgentExecutorRequest,
AgentExecutorResponse,
AgentResponse,
AgentResponseUpdate,
ChatAgent,
ChatMessage,
Executor,
Message,
WorkflowBuilder,
WorkflowContext,
WorkflowEvent,
@@ -90,7 +90,7 @@ class DraftFeedbackRequest:
prompt: str = ""
draft_text: str = ""
conversation: list[ChatMessage] = field(default_factory=list) # type: ignore[reportUnknownVariableType]
conversation: list[Message] = field(default_factory=list) # type: ignore[reportUnknownVariableType]
class Coordinator(Executor):
@@ -116,7 +116,7 @@ class Coordinator(Executor):
# Writer agent response; request human feedback.
# Preserve the full conversation so the final editor
# can see tool traces and the initial prompt.
conversation: list[ChatMessage]
conversation: list[Message]
if draft.full_conversation is not None:
conversation = list(draft.full_conversation)
else:
@@ -147,7 +147,7 @@ class Coordinator(Executor):
# Human approved the draft as-is; forward it unchanged.
await ctx.send_message(
AgentExecutorRequest(
messages=original_request.conversation + [ChatMessage("user", text="The draft is approved as-is.")],
messages=original_request.conversation + [Message("user", text="The draft is approved as-is.")],
should_respond=True,
),
target_id=self.final_editor_id,
@@ -155,20 +155,20 @@ class Coordinator(Executor):
return
# Human provided feedback; prompt the writer to revise.
conversation: list[ChatMessage] = list(original_request.conversation)
conversation: list[Message] = list(original_request.conversation)
instruction = (
"A human reviewer shared the following guidance:\n"
f"{note or 'No specific guidance provided.'}\n\n"
"Rewrite the draft from the previous assistant message into a polished final version. "
"Keep the response under 120 words and reflect any requested tone adjustments."
)
conversation.append(ChatMessage("user", text=instruction))
conversation.append(Message("user", text=instruction))
await ctx.send_message(
AgentExecutorRequest(messages=conversation, should_respond=True), target_id=self.writer_id
)
def create_writer_agent() -> ChatAgent:
def create_writer_agent() -> Agent:
"""Creates a writer agent with tools."""
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
name="writer_agent",
@@ -182,7 +182,7 @@ def create_writer_agent() -> ChatAgent:
)
def create_final_editor_agent() -> ChatAgent:
def create_final_editor_agent() -> Agent:
"""Creates a final editor agent."""
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
name="final_editor_agent",
@@ -38,9 +38,9 @@ def clear_and_redraw(buffers: dict[str, str], agent_order: list[str]) -> None:
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."
@@ -48,7 +48,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."
@@ -56,7 +56,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."
@@ -3,9 +3,9 @@
import asyncio
from agent_framework import (
ChatAgent,
ChatMessage,
Agent,
Executor,
Message,
WorkflowBuilder,
WorkflowContext,
handler,
@@ -37,11 +37,11 @@ class Writer(Executor):
"""Custom executor that owns a domain specific agent responsible for generating content.
This class demonstrates:
- Attaching a ChatAgent to an Executor so it participates as a node in a workflow.
- Attaching a Agent to an Executor so it participates as a node in a workflow.
- Using a @handler method to accept a typed input and forward a typed output via ctx.send_message.
"""
agent: ChatAgent
agent: Agent
def __init__(self, id: str = "writer"):
# Create a domain specific agent using your configured AzureOpenAIChatClient.
@@ -54,12 +54,12 @@ class Writer(Executor):
super().__init__(id=id)
@handler
async def handle(self, message: ChatMessage, ctx: WorkflowContext[list[ChatMessage], str]) -> None:
async def handle(self, message: Message, ctx: WorkflowContext[list[Message], str]) -> None:
"""Generate content using the agent and forward the updated conversation.
Contract for this handler:
- message is the inbound user ChatMessage.
- ctx is a WorkflowContext that expects a list[ChatMessage] to be sent downstream.
- message is the inbound user Message.
- ctx is a WorkflowContext that expects a list[Message] to be sent downstream.
Pattern shown here:
1) Seed the conversation with the inbound message.
@@ -67,7 +67,7 @@ class Writer(Executor):
3) Forward the cumulative messages to the next executor with ctx.send_message.
"""
# Start the conversation with the incoming user message.
messages: list[ChatMessage] = [message]
messages: list[Message] = [message]
# Run the agent and extend the conversation with the agent's messages.
response = await self.agent.run(messages)
messages.extend(response.messages)
@@ -83,7 +83,7 @@ class Reviewer(Executor):
- Yielding the final text outcome to complete the workflow.
"""
agent: ChatAgent
agent: Agent
def __init__(self, id: str = "reviewer"):
# Create a domain specific agent that evaluates and refines content.
@@ -95,7 +95,7 @@ class Reviewer(Executor):
super().__init__(id=id)
@handler
async def handle(self, messages: list[ChatMessage], ctx: WorkflowContext[list[ChatMessage], str]) -> None:
async def handle(self, messages: list[Message], ctx: WorkflowContext[list[Message], str]) -> None:
"""Review the full conversation transcript and complete with a final string.
This node consumes all messages so far. It uses its agent to produce the final text,
@@ -118,7 +118,7 @@ async def main():
# Run the workflow with the user's initial message.
# For foundational clarity, use run (non streaming) and print the workflow output.
events = await workflow.run(
ChatMessage("user", ["Create a slogan for a new electric SUV that is affordable and fun to drive."])
Message("user", ["Create a slogan for a new electric SUV that is affordable and fun to drive."])
)
# The terminal node yields output; print its contents.
outputs = events.get_outputs()
@@ -2,7 +2,7 @@
import asyncio
from agent_framework import ChatAgent
from agent_framework import Agent
from agent_framework.openai import OpenAIChatClient, OpenAIResponsesClient
from agent_framework.orchestrations import GroupChatBuilder
@@ -19,18 +19,18 @@ Prerequisites:
async def main() -> None:
researcher = ChatAgent(
researcher = Agent(
name="Researcher",
description="Collects relevant background information.",
instructions="Gather concise facts that help a teammate answer the question.",
chat_client=OpenAIChatClient(model_id="gpt-4o-mini"),
client=OpenAIChatClient(model_id="gpt-4o-mini"),
)
writer = ChatAgent(
writer = Agent(
name="Writer",
description="Synthesizes a polished answer using the gathered notes.",
instructions="Compose clear and structured answers using any notes provided.",
chat_client=OpenAIResponsesClient(),
client=OpenAIResponsesClient(),
)
# intermediate_outputs=True: Enable intermediate outputs to observe the conversation as it unfolds
@@ -4,10 +4,10 @@ import asyncio
from typing import Annotated
from agent_framework import (
Agent,
AgentResponse,
ChatAgent,
ChatMessage,
Content,
Message,
WorkflowAgent,
tool,
)
@@ -57,17 +57,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."
@@ -76,7 +76,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
@@ -84,7 +84,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
@@ -92,7 +92,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
@@ -147,10 +147,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
@@ -213,7 +213,7 @@ async def main() -> None:
function_results = [
Content.from_function_result(call_id=req_id, result=response) for req_id, response in responses.items()
]
response = await agent.run(ChatMessage("tool", function_results))
response = await agent.run(Message("tool", function_results))
pending_requests = handle_response_and_requests(response)
@@ -3,7 +3,7 @@
import asyncio
from agent_framework import (
ChatAgent,
Agent,
HostedCodeInterpreterTool,
)
from agent_framework.openai import OpenAIChatClient, OpenAIResponsesClient
@@ -22,30 +22,30 @@ Prerequisites:
async def main() -> None:
researcher_agent = ChatAgent(
researcher_agent = Agent(
name="ResearcherAgent",
description="Specialist in research and information gathering",
instructions=(
"You are a Researcher. You find information without additional computation or quantitative analysis."
),
# This agent requires the gpt-4o-search-preview model to perform web searches.
chat_client=OpenAIChatClient(model_id="gpt-4o-search-preview"),
client=OpenAIChatClient(model_id="gpt-4o-search-preview"),
)
coder_agent = ChatAgent(
coder_agent = Agent(
name="CoderAgent",
description="A helpful assistant that writes and executes code to process and analyze data.",
instructions="You solve questions using code. Please provide detailed analysis and computation process.",
chat_client=OpenAIResponsesClient(),
client=OpenAIResponsesClient(),
tools=HostedCodeInterpreterTool(),
)
# Create a manager agent for orchestration
manager_agent = ChatAgent(
manager_agent = Agent(
name="MagenticManager",
description="Orchestrator that coordinates the research and coding workflow",
instructions="You coordinate a team to complete complex tasks efficiently.",
chat_client=OpenAIChatClient(),
client=OpenAIChatClient(),
)
print("\nBuilding Magentic Workflow...")
@@ -27,14 +27,14 @@ Prerequisites:
async def main() -> None:
# 1) Create agents
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
client = AzureOpenAIChatClient(credential=AzureCliCredential())
writer = chat_client.as_agent(
writer = client.as_agent(
instructions=("You are a concise copywriter. Provide a single, punchy marketing sentence based on the prompt."),
name="writer",
)
reviewer = chat_client.as_agent(
reviewer = client.as_agent(
instructions=("You are a thoughtful reviewer. Give brief feedback on the previous assistant message."),
name="reviewer",
)
@@ -16,9 +16,9 @@ if str(_SAMPLES_ROOT) not in sys.path:
sys.path.insert(0, str(_SAMPLES_ROOT))
from agent_framework import ( # noqa: E402
ChatMessage,
Content,
Executor,
Message,
WorkflowAgent,
WorkflowBuilder,
WorkflowContext,
@@ -159,7 +159,7 @@ async def main() -> None:
result=human_response,
)
# Send the human review result back to the agent.
response = await agent.run(ChatMessage("tool", [human_review_function_result]))
response = await agent.run(Message("tool", [human_review_function_result]))
print(f"📤 Agent Response: {response.messages[-1].text}")
print("=" * 50)
@@ -80,10 +80,10 @@ async def main() -> None:
print("=" * 70)
# Create chat client
chat_client = OpenAIChatClient()
client = OpenAIChatClient()
# Create agent with tools that use kwargs
agent = chat_client.as_agent(
agent = client.as_agent(
name="assistant",
instructions=(
"You are a helpful assistant. Use the available tools to help users. "
@@ -6,9 +6,9 @@ from uuid import uuid4
from agent_framework import (
AgentResponse,
ChatClientProtocol,
ChatMessage,
Executor,
Message,
SupportsChatGetResponse,
WorkflowBuilder,
WorkflowContext,
handler,
@@ -44,8 +44,8 @@ class ReviewRequest:
"""Structured request passed from Worker to Reviewer for evaluation."""
request_id: str
user_messages: list[ChatMessage]
agent_messages: list[ChatMessage]
user_messages: list[Message]
agent_messages: list[Message]
@dataclass
@@ -60,9 +60,9 @@ class ReviewResponse:
class Reviewer(Executor):
"""Executor that reviews agent responses and provides structured feedback."""
def __init__(self, id: str, chat_client: ChatClientProtocol) -> None:
def __init__(self, id: str, client: SupportsChatGetResponse) -> None:
super().__init__(id=id)
self._chat_client = chat_client
self._chat_client = client
@handler
async def review(self, request: ReviewRequest, ctx: WorkflowContext[ReviewResponse]) -> None:
@@ -75,7 +75,7 @@ class Reviewer(Executor):
# Construct review instructions and context.
messages = [
ChatMessage(
Message(
role="system",
text=(
"You are a reviewer for an AI agent. Provide feedback on the "
@@ -93,7 +93,7 @@ class Reviewer(Executor):
messages.extend(request.agent_messages)
# Add explicit review instruction.
messages.append(ChatMessage("user", ["Please review the agent's responses."]))
messages.append(Message("user", ["Please review the agent's responses."]))
print("Reviewer: Sending review request to LLM...")
response = await self._chat_client.get_response(messages=messages, options={"response_format": _Response})
@@ -112,17 +112,17 @@ class Reviewer(Executor):
class Worker(Executor):
"""Executor that generates responses and incorporates feedback when necessary."""
def __init__(self, id: str, chat_client: ChatClientProtocol) -> None:
def __init__(self, id: str, client: SupportsChatGetResponse) -> None:
super().__init__(id=id)
self._chat_client = chat_client
self._pending_requests: dict[str, tuple[ReviewRequest, list[ChatMessage]]] = {}
self._chat_client = client
self._pending_requests: dict[str, tuple[ReviewRequest, list[Message]]] = {}
@handler
async def handle_user_messages(self, user_messages: list[ChatMessage], ctx: WorkflowContext[ReviewRequest]) -> None:
async def handle_user_messages(self, user_messages: list[Message], ctx: WorkflowContext[ReviewRequest]) -> None:
print("Worker: Received user messages, generating response...")
# Initialize chat with system prompt.
messages = [ChatMessage("system", ["You are a helpful assistant."])]
messages = [Message("system", ["You are a helpful assistant."])]
messages.extend(user_messages)
print("Worker: Calling LLM to generate response...")
@@ -161,8 +161,8 @@ class Worker(Executor):
print("Worker: Regenerating response with feedback...")
# Incorporate review feedback.
messages.append(ChatMessage("system", [review.feedback]))
messages.append(ChatMessage("system", ["Please incorporate the feedback and regenerate the response."]))
messages.append(Message("system", [review.feedback]))
messages.append(Message("system", ["Please incorporate the feedback and regenerate the response."]))
messages.extend(request.user_messages)
# Retry with updated prompt.
@@ -37,9 +37,9 @@ Prerequisites:
async def main() -> None:
# Create a chat client
chat_client = OpenAIChatClient()
client = OpenAIChatClient()
assistant = chat_client.as_agent(
assistant = client.as_agent(
name="assistant",
instructions=(
"You are a helpful assistant. Answer questions based on the conversation "
@@ -47,7 +47,7 @@ async def main() -> None:
),
)
summarizer = chat_client.as_agent(
summarizer = client.as_agent(
name="summarizer",
instructions=(
"You are a summarizer. After the assistant responds, provide a brief "
@@ -119,9 +119,9 @@ async def demonstrate_thread_serialization() -> None:
This shows how conversation history can be persisted and restored,
enabling long-running conversational workflows.
"""
chat_client = OpenAIChatClient()
client = OpenAIChatClient()
memory_assistant = chat_client.as_agent(
memory_assistant = client.as_agent(
name="memory_assistant",
instructions="You are a helpful assistant with good memory. Remember details from our conversation.",
)
@@ -20,9 +20,9 @@ from agent_framework import (
AgentExecutor,
AgentExecutorRequest,
AgentExecutorResponse,
ChatMessage,
Executor,
FileCheckpointStorage,
Message,
Workflow,
WorkflowBuilder,
WorkflowCheckpoint,
@@ -97,7 +97,7 @@ class BriefPreparer(Executor):
# Hand the prompt to the writer agent. We always route through the
# workflow context so the runtime can capture messages for checkpointing.
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._agent_id,
)
@@ -159,7 +159,7 @@ class ReviewGateway(Executor):
f"Human guidance: {reply}"
)
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._writer_id,
)
@@ -7,11 +7,11 @@ from pathlib import Path
from typing import cast
from agent_framework import (
Agent,
AgentResponse,
ChatAgent,
ChatMessage,
Content,
FileCheckpointStorage,
Message,
Workflow,
WorkflowEvent,
tool,
@@ -57,7 +57,7 @@ def submit_refund(refund_description: str, amount: str, order_id: str) -> str:
return f"refund recorded for order {order_id} (amount: {amount}) with details: {refund_description}"
def create_agents(client: AzureOpenAIChatClient) -> tuple[ChatAgent, ChatAgent, ChatAgent]:
def create_agents(client: AzureOpenAIChatClient) -> tuple[Agent, Agent, Agent]:
"""Create a simple handoff scenario: triage, refund, and order specialists."""
triage = client.as_agent(
@@ -91,7 +91,7 @@ def create_agents(client: AzureOpenAIChatClient) -> tuple[ChatAgent, ChatAgent,
return triage, refund, order
def create_workflow(checkpoint_storage: FileCheckpointStorage) -> tuple[Workflow, ChatAgent, ChatAgent, ChatAgent]:
def create_workflow(checkpoint_storage: FileCheckpointStorage) -> tuple[Workflow, Agent, Agent, Agent]:
"""Build the handoff workflow with checkpointing enabled."""
client = AzureOpenAIChatClient(credential=AzureCliCredential())
@@ -284,9 +284,9 @@ async def resume_with_responses(
elif event.type == "output":
print("\n[Workflow Output Event - Conversation Update]")
if event.data and isinstance(event.data, list) and all(isinstance(msg, ChatMessage) for msg in event.data): # type: ignore
# Now safe to cast event.data to list[ChatMessage]
conversation = cast(list[ChatMessage], event.data) # type: ignore
if event.data and isinstance(event.data, list) and all(isinstance(msg, Message) for msg in event.data): # type: ignore
# Now safe to cast event.data to list[Message]
conversation = cast(list[Message], event.data) # type: ignore
for msg in conversation[-3:]: # Show last 3 messages
author = msg.author_name or msg.role
text = msg.text[:100] + "..." if len(msg.text) > 100 else msg.text
@@ -40,14 +40,14 @@ async def basic_checkpointing() -> None:
print("Basic Checkpointing with Workflow as Agent")
print("=" * 60)
chat_client = OpenAIChatClient()
client = OpenAIChatClient()
assistant = chat_client.as_agent(
assistant = client.as_agent(
name="assistant",
instructions="You are a helpful assistant. Keep responses brief.",
)
reviewer = chat_client.as_agent(
reviewer = client.as_agent(
name="reviewer",
instructions="You are a reviewer. Provide a one-sentence summary of the assistant's response.",
)
@@ -81,9 +81,9 @@ async def checkpointing_with_thread() -> None:
print("Checkpointing with Thread Conversation History")
print("=" * 60)
chat_client = OpenAIChatClient()
client = OpenAIChatClient()
assistant = chat_client.as_agent(
assistant = client.as_agent(
name="memory_assistant",
instructions="You are a helpful assistant with good memory. Reference previous conversation when relevant.",
)
@@ -124,9 +124,9 @@ async def streaming_with_checkpoints() -> None:
print("Streaming with Checkpointing")
print("=" * 60)
chat_client = OpenAIChatClient()
client = OpenAIChatClient()
assistant = chat_client.as_agent(
assistant = client.as_agent(
name="streaming_assistant",
instructions="You are a helpful assistant.",
)
@@ -5,7 +5,7 @@ import json
from typing import Annotated, Any
from agent_framework import (
ChatMessage,
Message,
WorkflowExecutor,
tool,
)
@@ -74,10 +74,10 @@ async def main() -> None:
print("=" * 70)
# Create chat client
chat_client = OpenAIChatClient()
client = OpenAIChatClient()
# Create an agent with tools that use kwargs
inner_agent = chat_client.as_agent(
inner_agent = client.as_agent(
name="data_agent",
instructions=(
"You are a data access agent. Use the available tools to help users. "
@@ -134,7 +134,7 @@ async def main() -> None:
output_data = event.data
if isinstance(output_data, list):
for item in output_data: # type: ignore
if isinstance(item, ChatMessage) and item.text:
if isinstance(item, Message) and item.text:
print(f"\n[Final Answer]: {item.text}")
print("\n" + "=" * 70)
@@ -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."),
@@ -164,43 +164,43 @@ async def main() -> None:
plugin = TicketingPlugin()
# Create Azure OpenAI client
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
client = AzureOpenAIChatClient(credential=AzureCliCredential())
# Create agents with structured outputs
self_service_agent = chat_client.as_agent(
self_service_agent = client.as_agent(
name="SelfServiceAgent",
instructions=SELF_SERVICE_INSTRUCTIONS,
default_options={"response_format": SelfServiceResponse},
)
ticketing_agent = chat_client.as_agent(
ticketing_agent = client.as_agent(
name="TicketingAgent",
instructions=TICKETING_INSTRUCTIONS,
tools=plugin.get_functions(),
default_options={"response_format": TicketingResponse},
)
routing_agent = chat_client.as_agent(
routing_agent = client.as_agent(
name="TicketRoutingAgent",
instructions=TICKET_ROUTING_INSTRUCTIONS,
tools=[plugin.get_ticket],
default_options={"response_format": RoutingResponse},
)
windows_support_agent = chat_client.as_agent(
windows_support_agent = client.as_agent(
name="WindowsSupportAgent",
instructions=WINDOWS_SUPPORT_INSTRUCTIONS,
tools=[plugin.get_ticket],
default_options={"response_format": SupportResponse},
)
resolution_agent = chat_client.as_agent(
resolution_agent = client.as_agent(
name="TicketResolutionAgent",
instructions=RESOLUTION_INSTRUCTIONS,
tools=[plugin.resolve_ticket],
)
escalation_agent = chat_client.as_agent(
escalation_agent = client.as_agent(
name="TicketEscalationAgent",
instructions=ESCALATION_INSTRUCTIONS,
tools=[plugin.get_ticket, plugin.send_notification],
@@ -122,41 +122,41 @@ class ManagerResponse(BaseModel):
async def main() -> None:
"""Run the deep research workflow."""
# Create Azure OpenAI client
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
client = AzureOpenAIChatClient(credential=AzureCliCredential())
# Create agents
research_agent = chat_client.as_agent(
research_agent = client.as_agent(
name="ResearchAgent",
instructions=RESEARCH_INSTRUCTIONS,
)
planner_agent = chat_client.as_agent(
planner_agent = client.as_agent(
name="PlannerAgent",
instructions=PLANNER_INSTRUCTIONS,
)
manager_agent = chat_client.as_agent(
manager_agent = client.as_agent(
name="ManagerAgent",
instructions=MANAGER_INSTRUCTIONS,
default_options={"response_format": ManagerResponse},
)
summary_agent = chat_client.as_agent(
summary_agent = client.as_agent(
name="SummaryAgent",
instructions=SUMMARY_INSTRUCTIONS,
)
knowledge_agent = chat_client.as_agent(
knowledge_agent = client.as_agent(
name="KnowledgeAgent",
instructions=KNOWLEDGE_INSTRUCTIONS,
)
coder_agent = chat_client.as_agent(
coder_agent = client.as_agent(
name="CoderAgent",
instructions=CODER_INSTRUCTIONS,
)
weather_agent = chat_client.as_agent(
weather_agent = client.as_agent(
name="WeatherAgent",
instructions=WEATHER_INSTRUCTIONS,
)
@@ -72,8 +72,8 @@ Session Complete
```python
# Create the agent with tools
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
menu_agent = chat_client.as_agent(
client = AzureOpenAIChatClient(credential=AzureCliCredential())
menu_agent = client.as_agent(
name="MenuAgent",
instructions="You are a helpful restaurant menu assistant...",
tools=[get_menu, get_specials, get_item_price],
@@ -62,8 +62,8 @@ def get_item_price(name: Annotated[str, Field(description="Menu item name")]) ->
async def main():
# Create agent with tools
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
menu_agent = chat_client.as_agent(
client = AzureOpenAIChatClient(credential=AzureCliCredential())
menu_agent = client.as_agent(
name="MenuAgent",
instructions="Answer questions about menu items, specials, and prices.",
tools=[get_menu, get_specials, get_item_price],
@@ -49,17 +49,17 @@ Return the final polished version."""
async def main() -> None:
"""Run the marketing workflow with real Azure AI agents."""
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
client = AzureOpenAIChatClient(credential=AzureCliCredential())
analyst_agent = chat_client.as_agent(
analyst_agent = client.as_agent(
name="AnalystAgent",
instructions=ANALYST_INSTRUCTIONS,
)
writer_agent = chat_client.as_agent(
writer_agent = client.as_agent(
name="WriterAgent",
instructions=WRITER_INSTRUCTIONS,
)
editor_agent = chat_client.as_agent(
editor_agent = client.as_agent(
name="EditorAgent",
instructions=EDITOR_INSTRUCTIONS,
)
@@ -51,15 +51,15 @@ Focus on building understanding, not just getting the right answer."""
async def main() -> None:
"""Run the student-teacher workflow with real Azure AI agents."""
# Create chat client
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
client = AzureOpenAIChatClient(credential=AzureCliCredential())
# Create student and teacher agents
student_agent = chat_client.as_agent(
student_agent = client.as_agent(
name="StudentAgent",
instructions=STUDENT_INSTRUCTIONS,
)
teacher_agent = chat_client.as_agent(
teacher_agent = client.as_agent(
name="TeacherAgent",
instructions=TEACHER_INSTRUCTIONS,
)
@@ -9,8 +9,8 @@ from agent_framework import (
AgentExecutorResponse,
AgentResponse,
AgentResponseUpdate,
ChatMessage,
Executor,
Message,
WorkflowBuilder,
WorkflowContext,
WorkflowEvent,
@@ -47,7 +47,7 @@ class DraftFeedbackRequest:
"""Payload sent for human review."""
prompt: str = ""
conversation: list[ChatMessage] = field(default_factory=lambda: [])
conversation: list[Message] = field(default_factory=lambda: [])
class Coordinator(Executor):
@@ -71,7 +71,7 @@ class Coordinator(Executor):
# Writer agent response; request human feedback.
# Preserve the full conversation so that the final editor has context.
conversation: list[ChatMessage]
conversation: list[Message]
if draft.full_conversation is not None:
conversation = list(draft.full_conversation)
else:
@@ -100,7 +100,7 @@ class Coordinator(Executor):
# Human approved the draft as-is; forward it unchanged.
await ctx.send_message(
AgentExecutorRequest(
messages=original_request.conversation + [ChatMessage("user", text="The draft is approved as-is.")],
messages=original_request.conversation + [Message("user", text="The draft is approved as-is.")],
should_respond=True,
),
target_id=self.final_editor_name,
@@ -108,14 +108,14 @@ class Coordinator(Executor):
return
# Human provided feedback; prompt the writer to revise.
conversation: list[ChatMessage] = list(original_request.conversation)
conversation: list[Message] = list(original_request.conversation)
instruction = (
"A human reviewer shared the following guidance:\n"
f"{note or 'No specific guidance provided.'}\n\n"
"Rewrite the draft from the previous assistant message into a polished final version. "
"Keep the response under 120 words and reflect any requested tone adjustments."
)
conversation.append(ChatMessage("user", text=instruction))
conversation.append(Message("user", text=instruction))
await ctx.send_message(
AgentExecutorRequest(messages=conversation, should_respond=True), target_id=self.writer_name
)
@@ -27,7 +27,7 @@ from typing import Any
from agent_framework import (
AgentExecutorResponse,
ChatMessage,
Message,
WorkflowEvent,
)
from agent_framework.azure import AzureOpenAIChatClient
@@ -76,7 +76,7 @@ async def aggregate_with_synthesis(results: list[AgentExecutorResponse]) -> Any:
# Build prompt with human guidance if provided
guidance_text = f"\n\nHuman guidance: {human_guidance}" if human_guidance else ""
system_msg = ChatMessage(
system_msg = Message(
"system",
text=(
"You are a synthesis expert. Consolidate the following analyst perspectives "
@@ -84,7 +84,7 @@ async def aggregate_with_synthesis(results: list[AgentExecutorResponse]) -> Any:
"prioritize aspects as directed."
),
)
user_msg = ChatMessage("user", text="\n\n".join(expert_sections) + guidance_text)
user_msg = Message("user", text="\n\n".join(expert_sections) + guidance_text)
response = await _chat_client.get_response([system_msg, user_msg])
return response.messages[-1].text if response.messages else ""
@@ -28,7 +28,7 @@ from typing import cast
from agent_framework import (
AgentExecutorResponse,
ChatMessage,
Message,
WorkflowEvent,
)
from agent_framework.azure import AzureOpenAIChatClient
@@ -51,7 +51,7 @@ async def process_event_stream(stream: AsyncIterable[WorkflowEvent]) -> dict[str
print("=" * 60)
print("Final discussion summary:")
# To make the type checker happy, we cast event.data to the expected type
outputs = cast(list[ChatMessage], event.data)
outputs = cast(list[Message], event.data)
for msg in outputs:
speaker = msg.author_name or msg.role
print(f"[{speaker}]: {msg.text}")
@@ -91,10 +91,10 @@ async def process_event_stream(stream: AsyncIterable[WorkflowEvent]) -> dict[str
async def main() -> None:
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
client = AzureOpenAIChatClient(credential=AzureCliCredential())
# Create agents for a group discussion
optimist = chat_client.as_agent(
optimist = client.as_agent(
name="optimist",
instructions=(
"You are an optimistic team member. You see opportunities and potential "
@@ -103,7 +103,7 @@ async def main() -> None:
),
)
pragmatist = chat_client.as_agent(
pragmatist = client.as_agent(
name="pragmatist",
instructions=(
"You are a pragmatic team member. You focus on practical implementation "
@@ -112,7 +112,7 @@ async def main() -> None:
),
)
creative = chat_client.as_agent(
creative = client.as_agent(
name="creative",
instructions=(
"You are a creative team member. You propose innovative solutions and "
@@ -122,7 +122,7 @@ async def main() -> None:
)
# Orchestrator coordinates the discussion
orchestrator = chat_client.as_agent(
orchestrator = client.as_agent(
name="orchestrator",
instructions=(
"You are a discussion manager coordinating a team conversation between participants. "
@@ -8,8 +8,8 @@ from agent_framework import (
AgentExecutorRequest,
AgentExecutorResponse,
AgentResponseUpdate,
ChatMessage,
Executor,
Message,
WorkflowBuilder,
WorkflowContext,
WorkflowEvent,
@@ -84,7 +84,7 @@ class TurnManager(Executor):
- Input is a simple starter token (ignored here).
- Output is an AgentExecutorRequest that triggers the agent to produce a guess.
"""
user = ChatMessage("user", text="Start by making your first guess.")
user = Message("user", text="Start by making your first guess.")
await ctx.send_message(AgentExecutorRequest(messages=[user], should_respond=True))
@handler
@@ -136,7 +136,7 @@ class TurnManager(Executor):
f"Feedback: {reply}. Your last guess was {last_guess}. "
f"Use this feedback to adjust and make your next guess (1-10)."
)
user_msg = ChatMessage("user", text=feedback_text)
user_msg = Message("user", text=feedback_text)
await ctx.send_message(AgentExecutorRequest(messages=[user_msg], should_respond=True))
@@ -27,7 +27,7 @@ from typing import cast
from agent_framework import (
AgentExecutorResponse,
ChatMessage,
Message,
WorkflowEvent,
)
from agent_framework.azure import AzureOpenAIChatClient
@@ -49,7 +49,7 @@ async def process_event_stream(stream: AsyncIterable[WorkflowEvent]) -> dict[str
print("WORKFLOW COMPLETE")
print("=" * 60)
print("Final output:")
outputs = cast(list[ChatMessage], event.data)
outputs = cast(list[Message], event.data)
for message in outputs:
print(f"[{message.author_name or message.role}]: {message.text}")
@@ -88,15 +88,15 @@ async def process_event_stream(stream: AsyncIterable[WorkflowEvent]) -> dict[str
async def main() -> None:
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
client = AzureOpenAIChatClient(credential=AzureCliCredential())
# Create agents for a sequential document review workflow
drafter = chat_client.as_agent(
drafter = client.as_agent(
name="drafter",
instructions=("You are a document drafter. When given a topic, create a brief draft (2-3 sentences)."),
)
editor = chat_client.as_agent(
editor = client.as_agent(
name="editor",
instructions=(
"You are an editor. Review the draft and make improvements. "
@@ -104,7 +104,7 @@ async def main() -> None:
),
)
finalizer = chat_client.as_agent(
finalizer = client.as_agent(
name="finalizer",
instructions=(
"You are a finalizer. Take the edited content and create a polished final version. "
@@ -7,8 +7,8 @@ from agent_framework import (
AgentExecutor, # Wraps a ChatAgent as an Executor for use in workflows
AgentExecutorRequest, # The message bundle sent to an AgentExecutor
AgentExecutorResponse, # The structured result returned by an AgentExecutor
ChatMessage, # Chat message structure
Executor, # Base class for custom Python executors
Message, # Chat message structure
WorkflowBuilder, # Fluent builder for wiring the workflow graph
WorkflowContext, # Per run context and event bus
handler, # Decorator to mark an Executor method as invokable
@@ -41,7 +41,7 @@ class DispatchToExperts(Executor):
@handler
async def dispatch(self, prompt: str, ctx: WorkflowContext[AgentExecutorRequest]) -> None:
# Wrap the incoming prompt as a user message for each expert and request a response.
initial_message = ChatMessage("user", text=prompt)
initial_message = Message("user", text=prompt)
await ctx.send_message(AgentExecutorRequest(messages=[initial_message], should_respond=True))
@@ -7,10 +7,10 @@ from typing import Any
from uuid import uuid4
from agent_framework import (
Agent,
AgentExecutorRequest,
AgentExecutorResponse,
ChatAgent,
ChatMessage,
Message,
WorkflowBuilder,
WorkflowContext,
executor,
@@ -103,7 +103,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)
)
@@ -134,7 +134,7 @@ async def submit_to_email_assistant(detection: DetectionResult, ctx: WorkflowCon
# Load the original content by id from workflow state and forward it to the assistant.
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)
)
@@ -154,7 +154,7 @@ async def handle_spam(detection: DetectionResult, ctx: WorkflowContext[Never, st
raise RuntimeError("This executor should only handle spam messages.")
def create_spam_detection_agent() -> ChatAgent:
def create_spam_detection_agent() -> Agent:
"""Creates a spam detection agent."""
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
instructions=(
@@ -167,7 +167,7 @@ def create_spam_detection_agent() -> ChatAgent:
)
def create_email_assistant_agent() -> ChatAgent:
def create_email_assistant_agent() -> Agent:
"""Creates an email assistant agent."""
return AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
instructions=(
@@ -4,7 +4,7 @@ import asyncio
import json
from typing import Annotated, Any, cast
from agent_framework import ChatMessage, tool
from agent_framework import Message, tool
from agent_framework.openai import OpenAIChatClient
from agent_framework.orchestrations import SequentialBuilder
from pydantic import Field
@@ -74,10 +74,10 @@ async def main() -> None:
print("=" * 70)
# Create chat client
chat_client = OpenAIChatClient()
client = OpenAIChatClient()
# Create agent with tools that use kwargs
agent = chat_client.as_agent(
agent = client.as_agent(
name="assistant",
instructions=(
"You are a helpful assistant. Use the available tools to help users. "
@@ -121,10 +121,10 @@ async def main() -> None:
stream=True,
):
if event.type == "output":
output_data = cast(list[ChatMessage], event.data)
output_data = cast(list[Message], event.data)
if isinstance(output_data, list):
for item in output_data:
if isinstance(item, ChatMessage) and item.text:
if isinstance(item, Message) and item.text:
print(f"\n[Final Answer]: {item.text}")
print("\n" + "=" * 70)
@@ -5,8 +5,8 @@ from collections.abc import AsyncIterable
from typing import Annotated
from agent_framework import (
ChatMessage,
Content,
Message,
WorkflowEvent,
tool,
)
@@ -91,10 +91,10 @@ def _print_output(event: WorkflowEvent) -> None:
if not event.data:
raise ValueError("WorkflowEvent has no data")
if not isinstance(event.data, list) and not all(isinstance(msg, ChatMessage) for msg in event.data):
raise ValueError("WorkflowEvent data is not a list of ChatMessage")
if not isinstance(event.data, list) and not all(isinstance(msg, Message) for msg in event.data):
raise ValueError("WorkflowEvent data is not a list of Message")
messages: list[ChatMessage] = event.data # type: ignore
messages: list[Message] = event.data # type: ignore
print("\n" + "-" * 60)
print("Workflow completed. Aggregated results from both agents:")
@@ -126,9 +126,9 @@ async def process_event_stream(stream: AsyncIterable[WorkflowEvent]) -> dict[str
async def main() -> None:
# 3. Create two agents focused on different stocks but with the same tool sets
chat_client = OpenAIChatClient()
client = OpenAIChatClient()
microsoft_agent = chat_client.as_agent(
microsoft_agent = client.as_agent(
name="MicrosoftAgent",
instructions=(
"You are a personal trading assistant focused on Microsoft (MSFT). "
@@ -137,7 +137,7 @@ async def main() -> None:
tools=[get_stock_price, get_market_sentiment, get_portfolio_balance, execute_trade],
)
google_agent = chat_client.as_agent(
google_agent = client.as_agent(
name="GoogleAgent",
instructions=(
"You are a personal trading assistant focused on Google (GOOGL). "
@@ -5,8 +5,8 @@ from collections.abc import AsyncIterable
from typing import Annotated, cast
from agent_framework import (
ChatMessage,
Content,
Message,
WorkflowEvent,
tool,
)
@@ -105,7 +105,7 @@ async def process_event_stream(stream: AsyncIterable[WorkflowEvent]) -> dict[str
# The output of the workflow comes from the orchestrator and it's a list of messages
print("\n" + "=" * 60)
print("Workflow summary:")
outputs = cast(list[ChatMessage], event.data)
outputs = cast(list[Message], event.data)
for msg in outputs:
speaker = msg.author_name or msg.role
print(f"[{speaker}]: {msg.text}")
@@ -126,9 +126,9 @@ async def process_event_stream(stream: AsyncIterable[WorkflowEvent]) -> dict[str
async def main() -> None:
# 3. Create specialized agents
chat_client = OpenAIChatClient()
client = OpenAIChatClient()
qa_engineer = chat_client.as_agent(
qa_engineer = client.as_agent(
name="QAEngineer",
instructions=(
"You are a QA engineer responsible for running tests before deployment. "
@@ -137,7 +137,7 @@ async def main() -> None:
tools=[run_tests],
)
devops_engineer = chat_client.as_agent(
devops_engineer = client.as_agent(
name="DevOpsEngineer",
instructions=(
"You are a DevOps engineer responsible for deployments. First check staging "
@@ -5,8 +5,8 @@ from collections.abc import AsyncIterable
from typing import Annotated, cast
from agent_framework import (
ChatMessage,
Content,
Message,
WorkflowEvent,
tool,
)
@@ -78,7 +78,7 @@ async def process_event_stream(stream: AsyncIterable[WorkflowEvent]) -> dict[str
# The output of the workflow comes from the orchestrator and it's a list of messages
print("\n" + "=" * 60)
print("Workflow summary:")
outputs = cast(list[ChatMessage], event.data)
outputs = cast(list[Message], event.data)
for msg in outputs:
speaker = msg.author_name or msg.role
print(f"[{speaker}]: {msg.text}")
@@ -99,8 +99,8 @@ async def process_event_stream(stream: AsyncIterable[WorkflowEvent]) -> dict[str
async def main() -> None:
# 2. Create the agent with tools (approval mode is set per-tool via decorator)
chat_client = OpenAIChatClient()
database_agent = chat_client.as_agent(
client = OpenAIChatClient()
database_agent = client.as_agent(
name="DatabaseAgent",
instructions=(
"You are a database assistant. You can view the database schema and execute "
@@ -7,8 +7,8 @@ from agent_framework import (
AgentExecutor,
AgentExecutorRequest,
AgentExecutorResponse,
ChatMessage,
Executor,
Message,
WorkflowBuilder,
WorkflowContext,
WorkflowViz,
@@ -39,7 +39,7 @@ class DispatchToExperts(Executor):
@handler
async def dispatch(self, prompt: str, ctx: WorkflowContext[AgentExecutorRequest]) -> None:
# Wrap the incoming prompt as a user message for each expert and request a response.
initial_message = ChatMessage("user", text=prompt)
initial_message = Message("user", text=prompt)
await ctx.send_message(AgentExecutorRequest(messages=[initial_message], should_respond=True))