Merge branch 'main' into feature-foundry-agents

This commit is contained in:
Chris
2025-11-05 19:14:20 -08:00
committed by GitHub
Unverified
32 changed files with 3537 additions and 3454 deletions
@@ -4,11 +4,15 @@
<TargetFrameworks>$(ProjectsTargetFrameworks)</TargetFrameworks>
<TargetFrameworks Condition="'$(Configuration)' == 'Debug'">$(ProjectsDebugTargetFrameworks)</TargetFrameworks>
<VersionSuffix>preview</VersionSuffix>
<IsPackable>false</IsPackable>
</PropertyGroup>
<Import Project="$(RepoRoot)/dotnet/nuget/nuget-package.props" />
<PropertyGroup>
<!-- Disable packing until we are ready to release this as a nuget -->
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup>
<InjectSharedThrow>true</InjectSharedThrow>
</PropertyGroup>
@@ -6,15 +6,14 @@
<Nullable>enable</Nullable>
<RootNamespace>Microsoft.Agents.AI.DevUI</RootNamespace>
<OutputType>Library</OutputType>
<Title>Microsoft Agent Framework Developer UI</Title>
<Description>Provides Microsoft Agent Framework support for developer UI.</Description>
<EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator>
<VersionSuffix>preview</VersionSuffix>
<!-- Suppress warnings for internal DevUI implementation -->
<NoWarn>$(NoWarn);CS1591;CA1852;CA1050;RCS1037;RCS1036;RCS1124;RCS1021;RCS1146;RCS1211;CA2007;CA1308;IL2026;IL3050;CA1812</NoWarn>
</PropertyGroup>
<!-- Import nuget packaging properties -->
<Import Project="..\..\nuget\nuget-package.props" />
<Import Project="$(RepoRoot)/dotnet/nuget/nuget-package.props" />
<!-- Import frontend web assets build targets -->
<Import Project="Microsoft.Agents.AI.DevUI.Frontend.targets" />
@@ -28,4 +27,10 @@
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
</ItemGroup>
<PropertyGroup>
<!-- NuGet Package Settings -->
<Title>Microsoft Agent Framework Developer UI</Title>
<Description>Provides Microsoft Agent Framework support for developer UI.</Description>
</PropertyGroup>
</Project>
@@ -6,13 +6,17 @@
<RootNamespace>Microsoft.Agents.AI.Hosting.AGUI.AspNetCore</RootNamespace>
<VersionSuffix>preview</VersionSuffix>
<DefineConstants>$(DefineConstants);ASPNETCORE</DefineConstants>
<IsPackable>false</IsPackable>
<InterceptorsNamespaces>$(InterceptorsNamespaces);Microsoft.AspNetCore.Http.Generated</InterceptorsNamespaces>
<EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator>
</PropertyGroup>
<Import Project="$(RepoRoot)/dotnet/nuget/nuget-package.props" />
<PropertyGroup>
<!-- Disable packing until we are ready to release this as a nuget -->
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup>
<!-- NuGet Package Settings -->
<Title>Microsoft Agent Framework Hosting AG-UI ASP.NET Core</Title>
@@ -4,7 +4,6 @@
<TargetFrameworks>$(ProjectsTargetFrameworks)</TargetFrameworks>
<TargetFrameworks Condition="'$(Configuration)' == 'Debug'">$(ProjectsDebugTargetFrameworks)</TargetFrameworks>
<VersionSuffix>preview</VersionSuffix>
<!-- Disable packing until we are ready to release this as a nuget -->
</PropertyGroup>
<PropertyGroup>
@@ -14,6 +13,7 @@
<Import Project="$(RepoRoot)/dotnet/nuget/nuget-package.props" />
<PropertyGroup>
<!-- Disable packing until we are ready to release this as a nuget -->
<IsPackable>false</IsPackable>
</PropertyGroup>
+6
View File
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [1.0.0b251106] - 2025-11-06
### Changed
- **agent-framework-ag-ui**: export sample ag-ui agents ([#1927](https://github.com/microsoft/agent-framework/pull/1927))
## [1.0.0b251105] - 2025-11-05
### Added
+2 -2
View File
@@ -36,7 +36,7 @@ add_agent_framework_fastapi_endpoint(app, agent, "/")
## Documentation
- **[Getting Started Tutorial](getting_started/)** - Step-by-step guide to building your first AG-UI server and client
- **[Examples](examples/)** - Complete examples for AG-UI features
- **[Examples](agent_framework_ag_ui_examples/)** - Complete examples for AG-UI features
## Features
@@ -64,7 +64,7 @@ The package uses a clean, orchestrator-based architecture:
## Next Steps
1. **New to AG-UI?** Start with the [Getting Started Tutorial](getting_started/)
2. **Want to see examples?** Check out the [Examples](examples/) for AG-UI features
2. **Want to see examples?** Check out the [Examples](agent_framework_ag_ui_examples/) for AG-UI features
## License
@@ -629,7 +629,7 @@ Now that you understand the basics of AG-UI, you can:
## Additional Resources
- [AG-UI Examples](../examples/README.md): Complete working examples for all 7 features
- [AG-UI Examples](../agent_framework_ag_ui_examples/README.md): Complete working examples for all 7 features
- [Agent Framework Documentation](../../core/README.md): Learn more about creating agents
- [AG-UI Protocol Spec](https://docs.ag-ui.com/): Official protocol documentation
+2 -3
View File
@@ -1,6 +1,6 @@
[project]
name = "agent-framework-ag-ui"
version = "1.0.0b251105"
version = "1.0.0b251106.post1"
description = "AG-UI protocol integration for Agent Framework"
readme = "README.md"
license-files = ["LICENSE"]
@@ -40,8 +40,7 @@ requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["agent_framework_ag_ui"]
force-include = { "examples" = "agent_framework_ag_ui_examples" }
packages = ["agent_framework_ag_ui", "agent_framework_ag_ui_examples"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
@@ -7,5 +7,14 @@ This folder contains examples demonstrating different ways to manage conversatio
| File | Description |
|------|-------------|
| [`custom_chat_message_store_thread.py`](custom_chat_message_store_thread.py) | Demonstrates how to implement a custom `ChatMessageStore` for persisting conversation history. Shows how to create a custom store with serialization/deserialization capabilities and integrate it with agents for thread management across multiple sessions. |
| [`suspend_resume_thread.py`](suspend_resume_thread.py) | Shows how to suspend and resume conversation threads, allowing you to save the state of a conversation and continue it later. This is useful for long-running conversations or when you need to persist conversation state across application restarts. |
| [`redis_chat_message_store_thread.py`](redis_chat_message_store_thread.py) | Comprehensive examples of using the Redis-backed `RedisChatMessageStore` for persistent conversation storage. Covers basic usage, user session management, conversation persistence across app restarts, thread serialization, and automatic message trimming. Requires Redis server and demonstrates production-ready patterns for scalable chat applications. |
| [`suspend_resume_thread.py`](suspend_resume_thread.py) | Shows how to suspend and resume conversation threads, comparing service-managed threads (Azure AI) with in-memory threads (OpenAI). Demonstrates saving conversation state and continuing it later, useful for long-running conversations or persisting state across application restarts. |
## Environment Variables
Make sure to set the following environment variables before running the examples:
- `OPENAI_API_KEY`: Your OpenAI API key (required for all samples)
- `OPENAI_CHAT_MODEL_ID`: The OpenAI model to use (e.g., `gpt-4o`, `gpt-4o-mini`, `gpt-3.5-turbo`) (required for all samples)
- `AZURE_AI_PROJECT_ENDPOINT`: Azure AI Project endpoint URL (required for service-managed thread examples)
- `AZURE_AI_MODEL_DEPLOYMENT_NAME`: The name of your model deployment (required for service-managed thread examples)
@@ -8,6 +8,14 @@ from agent_framework import ChatMessage, ChatMessageStoreProtocol
from agent_framework._threads import ChatMessageStoreState
from agent_framework.openai import OpenAIChatClient
"""
Custom Chat Message Store Thread Example
This sample demonstrates how to implement and use a custom chat message store
for thread management, allowing you to persist conversation history in your
preferred storage solution (database, file system, etc.).
"""
class CustomChatMessageStore(ChatMessageStoreProtocol):
"""Implementation of custom chat message store.
@@ -24,13 +32,22 @@ class CustomChatMessageStore(ChatMessageStoreProtocol):
async def list_messages(self) -> list[ChatMessage]:
return self._messages
async def deserialize_state(self, serialized_store_state: Any, **kwargs: Any) -> None:
@classmethod
async def deserialize(cls, serialized_store_state: Any, **kwargs: Any) -> "CustomChatMessageStore":
"""Create a new instance from serialized state."""
store = cls()
await store.update_from_state(serialized_store_state, **kwargs)
return store
async def update_from_state(self, serialized_store_state: Any, **kwargs: Any) -> None:
"""Update this instance from serialized state."""
if serialized_store_state:
state = ChatMessageStoreState.from_dict(serialized_store_state, **kwargs)
if state.messages:
self._messages.extend(state.messages)
async def serialize_state(self, **kwargs: Any) -> Any:
async def serialize(self, **kwargs: Any) -> Any:
"""Serialize this store's state."""
state = ChatMessageStoreState(messages=self._messages)
return state.to_dict(**kwargs)
@@ -42,8 +59,8 @@ async def main() -> None:
# OpenAI Chat Client is used as an example here,
# other chat clients can be used as well.
agent = OpenAIChatClient().create_agent(
name="Joker",
instructions="You are good at telling jokes.",
name="CustomBot",
instructions="You are a helpful assistant that remembers our conversation.",
# Use custom chat message store.
# If not provided, the default in-memory store will be used.
chat_message_store_factory=CustomChatMessageStore,
@@ -53,7 +70,7 @@ async def main() -> None:
thread = agent.get_new_thread()
# Respond to user input.
query = "Tell me a joke about a pirate."
query = "Hello! My name is Alice and I love pizza."
print(f"User: {query}")
print(f"Agent: {await agent.run(query, thread=thread)}\n")
@@ -67,7 +84,7 @@ async def main() -> None:
resumed_thread = await agent.deserialize_thread(serialized_thread)
# Respond to user input.
query = "Now tell the same joke in the voice of a pirate, and add some emojis to the joke."
query = "What do you remember about me?"
print(f"User: {query}")
print(f"Agent: {await agent.run(query, thread=resumed_thread)}\n")
@@ -8,6 +8,14 @@ from agent_framework import AgentThread
from agent_framework.openai import OpenAIChatClient
from agent_framework.redis import RedisChatMessageStore
"""
Redis Chat Message Store Thread Example
This sample demonstrates how to use Redis as a chat message store for thread
management, enabling persistent conversation history storage across sessions
with Redis as the backend data store.
"""
async def example_manual_memory_store() -> None:
"""Basic example of using Redis chat message store."""
@@ -2,38 +2,51 @@
import asyncio
from agent_framework.azure import AzureAIAgentClient
from agent_framework.openai import OpenAIChatClient
from azure.identity.aio import AzureCliCredential
"""
Thread Suspend and Resume Example
This sample demonstrates how to suspend and resume conversation threads, comparing
service-managed threads (Azure AI) with in-memory threads (OpenAI) for persistent
conversation state across sessions.
"""
async def suspend_resume_service_managed_thread() -> None:
"""Demonstrates how to suspend and resume a service-managed thread."""
print("=== Suspend-Resume Service-Managed Thread ===")
# OpenAI Chat Client is used as an example here,
# other chat clients can be used as well.
agent = OpenAIChatClient().create_agent(name="Joker", instructions="You are good at telling jokes.")
# AzureAIAgentClient supports service-managed threads.
async with (
AzureCliCredential() as credential,
AzureAIAgentClient(async_credential=credential).create_agent(
name="MemoryBot", instructions="You are a helpful assistant that remembers our conversation."
) as agent,
):
# Start a new thread for the agent conversation.
thread = agent.get_new_thread()
# Start a new thread for the agent conversation.
thread = agent.get_new_thread()
# Respond to user input.
query = "Hello! My name is Alice and I love pizza."
print(f"User: {query}")
print(f"Agent: {await agent.run(query, thread=thread)}\n")
# Respond to user input.
query = "Tell me a joke about a pirate."
print(f"User: {query}")
print(f"Agent: {await agent.run(query, thread=thread)}\n")
# Serialize the thread state, so it can be stored for later use.
serialized_thread = await thread.serialize()
# Serialize the thread state, so it can be stored for later use.
serialized_thread = await thread.serialize()
# The thread can now be saved to a database, file, or any other storage mechanism and loaded again later.
print(f"Serialized thread: {serialized_thread}\n")
# The thread can now be saved to a database, file, or any other storage mechanism and loaded again later.
print(f"Serialized thread: {serialized_thread}\n")
# Deserialize the thread state after loading from storage.
resumed_thread = await agent.deserialize_thread(serialized_thread)
# Deserialize the thread state after loading from storage.
resumed_thread = await agent.deserialize_thread(serialized_thread)
# Respond to user input.
query = "Now tell the same joke in the voice of a pirate, and add some emojis to the joke."
print(f"User: {query}")
print(f"Agent: {await agent.run(query, thread=resumed_thread)}\n")
# Respond to user input.
query = "What do you remember about me?"
print(f"User: {query}")
print(f"Agent: {await agent.run(query, thread=resumed_thread)}\n")
async def suspend_resume_in_memory_thread() -> None:
@@ -42,13 +55,15 @@ async def suspend_resume_in_memory_thread() -> None:
# OpenAI Chat Client is used as an example here,
# other chat clients can be used as well.
agent = OpenAIChatClient().create_agent(name="Joker", instructions="You are good at telling jokes.")
agent = OpenAIChatClient().create_agent(
name="MemoryBot", instructions="You are a helpful assistant that remembers our conversation."
)
# Start a new thread for the agent conversation.
thread = agent.get_new_thread()
# Respond to user input.
query = "Tell me a joke about a pirate."
query = "Hello! My name is Alice and I love pizza."
print(f"User: {query}")
print(f"Agent: {await agent.run(query, thread=thread)}\n")
@@ -62,7 +77,7 @@ async def suspend_resume_in_memory_thread() -> None:
resumed_thread = await agent.deserialize_thread(serialized_thread)
# Respond to user input.
query = "Now tell the same joke in the voice of a pirate, and add some emojis to the joke."
query = "What do you remember about me?"
print(f"User: {query}")
print(f"Agent: {await agent.run(query, thread=resumed_thread)}\n")
+3428 -3412
View File
File diff suppressed because it is too large Load Diff