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:
committed by
GitHub
Unverified
parent
a4c9e43afb
commit
0521f5bed8
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user