mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Merge branch 'main' into feature-python-foundry-agents
This commit is contained in:
@@ -2,9 +2,14 @@
|
||||
|
||||
This getting-started sample shows how to attach Microsoft Purview policy evaluation to an Agent Framework `ChatAgent` using the **middleware** approach.
|
||||
|
||||
**What this sample demonstrates:**
|
||||
1. Configure an Azure OpenAI chat client
|
||||
2. Add Purview policy enforcement middleware (`PurviewPolicyMiddleware`)
|
||||
3. Run a short conversation and observe prompt / response blocking behavior
|
||||
3. Add Purview policy enforcement at the chat client level (`PurviewChatPolicyMiddleware`)
|
||||
4. Implement a custom cache provider for advanced caching scenarios
|
||||
5. Run conversations and observe prompt / response blocking behavior
|
||||
|
||||
**Note:** Caching is **automatic** and enabled by default with sensible defaults (30-minute TTL, 200MB max size).
|
||||
|
||||
---
|
||||
## 1. Setup
|
||||
@@ -20,8 +25,6 @@ This getting-started sample shows how to attach Microsoft Purview policy evaluat
|
||||
| `PURVIEW_CERT_PATH` | Yes (when cert auth on) | Path to your .pfx certificate |
|
||||
| `PURVIEW_CERT_PASSWORD` | Optional | Password for encrypted certs |
|
||||
|
||||
*A demo default exists in code for illustration only—always set your own value.
|
||||
|
||||
### 2. Auth Modes Supported
|
||||
|
||||
#### A. Interactive Browser Authentication (default)
|
||||
@@ -42,7 +45,7 @@ $env:PURVIEW_CERT_PATH = "C:\path\to\cert.pfx"
|
||||
$env:PURVIEW_CERT_PASSWORD = "optional-password"
|
||||
```
|
||||
|
||||
Certificate steps (summary): create / register app, generate certificate, upload public key, export .pfx with private key, grant required Graph / Purview permissions.
|
||||
Certificate steps (summary): create / register entra app, generate certificate, upload public key, export .pfx with private key, grant required Graph / Purview permissions.
|
||||
|
||||
---
|
||||
|
||||
@@ -61,18 +64,39 @@ If interactive auth is used, a browser window will appear the first time.
|
||||
|
||||
## 4. How It Works
|
||||
|
||||
The sample demonstrates three different scenarios:
|
||||
|
||||
### A. Agent Middleware (`run_with_agent_middleware`)
|
||||
1. Builds an Azure OpenAI chat client (using the environment endpoint / deployment)
|
||||
2. Chooses credential mode (certificate vs interactive)
|
||||
3. Creates `PurviewPolicyMiddleware` with `PurviewSettings`
|
||||
4. Injects middleware into the agent at construction
|
||||
5. Sends two user messages sequentially
|
||||
6. Prints results (or policy block messages)
|
||||
7. Uses default caching automatically
|
||||
|
||||
### B. Chat Client Middleware (`run_with_chat_middleware`)
|
||||
1. Creates a chat client with `PurviewChatPolicyMiddleware` attached directly
|
||||
2. Policy evaluation happens at the chat client level rather than agent level
|
||||
3. Demonstrates an alternative integration point for Purview policies
|
||||
4. Uses default caching automatically
|
||||
|
||||
### C. Custom Cache Provider (`run_with_custom_cache_provider`)
|
||||
1. Implements the `CacheProvider` protocol with a custom class (`SimpleDictCacheProvider`)
|
||||
2. Shows how to add custom logging and metrics to cache operations
|
||||
3. The custom provider must implement three async methods:
|
||||
- `async def get(self, key: str) -> Any | None`
|
||||
- `async def set(self, key: str, value: Any, ttl_seconds: int | None = None) -> None`
|
||||
- `async def remove(self, key: str) -> None`
|
||||
|
||||
**Policy Behavior:**
|
||||
Prompt blocks set a system-level message: `Prompt blocked by policy` and terminate the run early. Response blocks rewrite the output to `Response blocked by policy`.
|
||||
|
||||
---
|
||||
|
||||
## 5. Code Snippet (Middleware Injection)
|
||||
## 5. Code Snippets
|
||||
|
||||
### Agent Middleware Injection
|
||||
|
||||
```python
|
||||
agent = ChatAgent(
|
||||
@@ -80,9 +104,41 @@ agent = ChatAgent(
|
||||
instructions="You are good at telling jokes.",
|
||||
name="Joker",
|
||||
middleware=[
|
||||
PurviewPolicyMiddleware(credential, PurviewSettings(app_name="Sample App", default_user_id="<guid>"))
|
||||
PurviewPolicyMiddleware(credential, PurviewSettings(app_name="Sample App"))
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
### Custom Cache Provider Implementation
|
||||
|
||||
This is only needed if you want to integrate with external caching systems.
|
||||
|
||||
```python
|
||||
class SimpleDictCacheProvider:
|
||||
"""Custom cache provider that implements the CacheProvider protocol."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._cache: dict[str, Any] = {}
|
||||
|
||||
async def get(self, key: str) -> Any | None:
|
||||
"""Get a value from the cache."""
|
||||
return self._cache.get(key)
|
||||
|
||||
async def set(self, key: str, value: Any, ttl_seconds: int | None = None) -> None:
|
||||
"""Set a value in the cache."""
|
||||
self._cache[key] = value
|
||||
|
||||
async def remove(self, key: str) -> None:
|
||||
"""Remove a value from the cache."""
|
||||
self._cache.pop(key, None)
|
||||
|
||||
# Use the custom cache provider
|
||||
custom_cache = SimpleDictCacheProvider()
|
||||
middleware = PurviewPolicyMiddleware(
|
||||
credential,
|
||||
PurviewSettings(app_name="Sample App"),
|
||||
cache_provider=custom_cache,
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -5,7 +5,10 @@ Shows:
|
||||
1. Creating a basic chat agent
|
||||
2. Adding Purview policy evaluation via AGENT middleware (agent-level)
|
||||
3. Adding Purview policy evaluation via CHAT middleware (chat-client level)
|
||||
4. Running a threaded conversation and printing results
|
||||
4. Implementing a custom cache provider for advanced caching scenarios
|
||||
5. Running threaded conversations and printing results
|
||||
|
||||
Note: Caching is automatic and enabled by default.
|
||||
|
||||
Environment variables:
|
||||
- AZURE_OPENAI_ENDPOINT (required)
|
||||
@@ -31,7 +34,6 @@ from azure.identity import (
|
||||
InteractiveBrowserCredential,
|
||||
)
|
||||
|
||||
# Purview integration pieces
|
||||
from agent_framework.microsoft import (
|
||||
PurviewPolicyMiddleware,
|
||||
PurviewChatPolicyMiddleware,
|
||||
@@ -42,6 +44,59 @@ JOKER_NAME = "Joker"
|
||||
JOKER_INSTRUCTIONS = "You are good at telling jokes. Keep responses concise."
|
||||
|
||||
|
||||
# Custom Cache Provider Implementation
|
||||
class SimpleDictCacheProvider:
|
||||
"""A simple custom cache provider that stores everything in a dictionary.
|
||||
|
||||
This example demonstrates how to implement the CacheProvider protocol.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize the simple dictionary cache."""
|
||||
self._cache: dict[str, Any] = {}
|
||||
self._access_count: dict[str, int] = {}
|
||||
|
||||
async def get(self, key: str) -> Any | None:
|
||||
"""Get a value from the cache.
|
||||
|
||||
Args:
|
||||
key: The cache key.
|
||||
|
||||
Returns:
|
||||
The cached value or None if not found.
|
||||
"""
|
||||
value = self._cache.get(key)
|
||||
if value is not None:
|
||||
self._access_count[key] = self._access_count.get(key, 0) + 1
|
||||
print(f"[CustomCache] Cache HIT for key: {key[:50]}... (accessed {self._access_count[key]} times)")
|
||||
else:
|
||||
print(f"[CustomCache] Cache MISS for key: {key[:50]}...")
|
||||
return value
|
||||
|
||||
async def set(self, key: str, value: Any, ttl_seconds: int | None = None) -> None:
|
||||
"""Set a value in the cache.
|
||||
|
||||
Args:
|
||||
key: The cache key.
|
||||
value: The value to cache.
|
||||
ttl_seconds: Time to live in seconds (ignored in this simple implementation).
|
||||
"""
|
||||
self._cache[key] = value
|
||||
print(f"[CustomCache] Cached value for key: {key[:50]}... (TTL: {ttl_seconds}s)")
|
||||
|
||||
async def remove(self, key: str) -> None:
|
||||
"""Remove a value from the cache.
|
||||
|
||||
Args:
|
||||
key: The cache key.
|
||||
"""
|
||||
if key in self._cache:
|
||||
del self._cache[key]
|
||||
self._access_count.pop(key, None)
|
||||
print(f"[CustomCache] Removed key: {key[:50]}...")
|
||||
|
||||
|
||||
|
||||
def _get_env(name: str, *, required: bool = True, default: str | None = None) -> str:
|
||||
val = os.environ.get(name, default)
|
||||
if required and not val:
|
||||
@@ -161,9 +216,91 @@ async def run_with_chat_middleware() -> None:
|
||||
)
|
||||
print("Second response (chat middleware):\n", second)
|
||||
|
||||
async def run_with_custom_cache_provider() -> None:
|
||||
"""Demonstrate implementing and using a custom cache provider."""
|
||||
endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT")
|
||||
if not endpoint:
|
||||
print("Skipping custom cache provider run: AZURE_OPENAI_ENDPOINT not set")
|
||||
return
|
||||
|
||||
deployment = os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4o-mini")
|
||||
user_id = os.environ.get("PURVIEW_DEFAULT_USER_ID")
|
||||
chat_client = AzureOpenAIChatClient(deployment_name=deployment, endpoint=endpoint, credential=AzureCliCredential())
|
||||
|
||||
custom_cache = SimpleDictCacheProvider()
|
||||
|
||||
purview_agent_middleware = PurviewPolicyMiddleware(
|
||||
build_credential(),
|
||||
PurviewSettings(
|
||||
app_name="Agent Framework Sample App (Custom Provider)",
|
||||
),
|
||||
cache_provider=custom_cache,
|
||||
)
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=chat_client,
|
||||
instructions=JOKER_INSTRUCTIONS,
|
||||
name=JOKER_NAME,
|
||||
middleware=purview_agent_middleware,
|
||||
)
|
||||
|
||||
print("-- Custom Cache Provider Path --")
|
||||
print("Using SimpleDictCacheProvider")
|
||||
|
||||
first: AgentRunResponse = await agent.run(
|
||||
ChatMessage(role=Role.USER, text="Tell me a joke about a programmer.", additional_properties={"user_id": user_id})
|
||||
)
|
||||
print("First response (custom provider):\n", first)
|
||||
|
||||
second: AgentRunResponse = await agent.run(
|
||||
ChatMessage(role=Role.USER, text="That's hilarious! One more?", additional_properties={"user_id": user_id})
|
||||
)
|
||||
print("Second response (custom provider):\n", second)
|
||||
|
||||
"""Demonstrate using the default built-in cache."""
|
||||
endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT")
|
||||
if not endpoint:
|
||||
print("Skipping default cache run: AZURE_OPENAI_ENDPOINT not set")
|
||||
return
|
||||
|
||||
deployment = os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4o-mini")
|
||||
user_id = os.environ.get("PURVIEW_DEFAULT_USER_ID")
|
||||
chat_client = AzureOpenAIChatClient(deployment_name=deployment, endpoint=endpoint, credential=AzureCliCredential())
|
||||
|
||||
# No cache_provider specified - uses default InMemoryCacheProvider
|
||||
purview_agent_middleware = PurviewPolicyMiddleware(
|
||||
build_credential(),
|
||||
PurviewSettings(
|
||||
app_name="Agent Framework Sample App (Default Cache)",
|
||||
cache_ttl_seconds=3600,
|
||||
max_cache_size_bytes=100 * 1024 * 1024, # 100MB
|
||||
),
|
||||
)
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=chat_client,
|
||||
instructions=JOKER_INSTRUCTIONS,
|
||||
name=JOKER_NAME,
|
||||
middleware=purview_agent_middleware,
|
||||
)
|
||||
|
||||
print("-- Default Cache Path --")
|
||||
print("Using default InMemoryCacheProvider with settings-based configuration")
|
||||
|
||||
first: AgentRunResponse = await agent.run(
|
||||
ChatMessage(role=Role.USER, text="Tell me a joke about AI.", additional_properties={"user_id": user_id})
|
||||
)
|
||||
print("First response (default cache):\n", first)
|
||||
|
||||
second: AgentRunResponse = await agent.run(
|
||||
ChatMessage(role=Role.USER, text="Nice! Another AI joke please.", additional_properties={"user_id": user_id})
|
||||
)
|
||||
print("Second response (default cache):\n", second)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
print("== Purview Agent Sample (Agent & Chat Middleware) ==")
|
||||
print("== Purview Agent Sample (Middleware with Automatic Caching) ==")
|
||||
|
||||
try:
|
||||
await run_with_agent_middleware()
|
||||
except Exception as ex: # pragma: no cover - demo resilience
|
||||
@@ -174,6 +311,11 @@ async def main() -> None:
|
||||
except Exception as ex: # pragma: no cover - demo resilience
|
||||
print(f"Chat middleware path failed: {ex}")
|
||||
|
||||
try:
|
||||
await run_with_custom_cache_provider()
|
||||
except Exception as ex: # pragma: no cover - demo resilience
|
||||
print(f"Custom cache provider path failed: {ex}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user