Python: Fix tool normalization and provider sample consolidation (#3953)

* Fix tool normalization and provider samples

- restore callable/single-tool normalization paths and unset tool-choice behavior\n- consolidate and expand chat/provider samples (OpenAI/Azure/Anthropic/Ollama/Bedrock)\n- migrate Bedrock lazy import surface to agent_framework.amazon and move provider samples

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* small fix in sample

* Finalize provider, samples, and core cleanup

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix CopilotTool passthrough in agent

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix link

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Eduard van Valkenburg
2026-02-16 16:30:38 +00:00
committed by GitHub
co-authored by Copilot
parent ed113f941c
commit aab621f5eb
99 changed files with 1190 additions and 969 deletions
@@ -75,6 +75,7 @@ async def main() -> None:
if knowledge_base_name:
# Use existing Knowledge Base - simplest approach
search_provider = AzureAISearchContextProvider(
source_id="search_provider",
endpoint=search_endpoint,
api_key=search_key,
credential=AzureCliCredential() if not search_key else None,
@@ -91,6 +92,7 @@ async def main() -> None:
if not azure_openai_resource_url:
raise ValueError("AZURE_OPENAI_RESOURCE_URL required when using index_name")
search_provider = AzureAISearchContextProvider(
source_id="search_provider",
endpoint=search_endpoint,
index_name=index_name,
api_key=search_key,
@@ -53,6 +53,7 @@ async def main() -> None:
# Create Azure AI Search context provider with semantic mode (recommended, fast)
print("Using SEMANTIC mode (hybrid search + semantic ranking, fast)\n")
search_provider = AzureAISearchContextProvider(
source_id="search_provider",
endpoint=search_endpoint,
index_name=index_name,
api_key=search_key, # Use api_key for API key auth, or credential for managed identity
@@ -39,7 +39,7 @@ async def main() -> None:
name="FriendlyAssistant",
instructions="You are a friendly assistant.",
tools=retrieve_company_report,
context_providers=[Mem0ContextProvider(user_id=user_id)],
context_providers=[Mem0ContextProvider(source_id="mem0", user_id=user_id)],
) as agent,
):
# First ask the agent to retrieve a company report with no previous context.
@@ -10,7 +10,9 @@ from azure.identity.aio import AzureCliCredential
from mem0 import AsyncMemory
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/02-agents/tools/function_tool_with_approval.py and samples/02-agents/tools/function_tool_with_approval_and_sessions.py.
# NOTE: approval_mode="never_require" is for sample brevity.
# Use "always_require" in production; see samples/02-agents/tools/function_tool_with_approval.py
# and samples/02-agents/tools/function_tool_with_approval_and_sessions.py.
@tool(approval_mode="never_require")
def retrieve_company_report(company_code: str, detailed: bool) -> str:
if company_code != "CNTS":
@@ -42,7 +44,7 @@ async def main() -> None:
name="FriendlyAssistant",
instructions="You are a friendly assistant.",
tools=retrieve_company_report,
context_providers=[Mem0ContextProvider(user_id=user_id, mem0_client=local_mem0_client)],
context_providers=[Mem0ContextProvider(source_id="mem0", user_id=user_id, mem0_client=local_mem0_client)],
) as agent,
):
# First ask the agent to retrieve a company report with no previous context.
@@ -34,11 +34,14 @@ async def example_global_thread_scope() -> None:
name="GlobalMemoryAssistant",
instructions="You are an assistant that remembers user preferences across conversations.",
tools=get_user_preferences,
context_providers=[Mem0ContextProvider(
user_id=user_id,
thread_id=global_thread_id,
scope_to_per_operation_thread_id=False, # Share memories across all sessions
)],
context_providers=[
Mem0ContextProvider(
source_id="mem0",
user_id=user_id,
thread_id=global_thread_id,
scope_to_per_operation_thread_id=False, # Share memories across all sessions
)
],
) as global_agent,
):
# Store some preferences in the global scope
@@ -72,10 +75,13 @@ async def example_per_operation_thread_scope() -> None:
name="ScopedMemoryAssistant",
instructions="You are an assistant with thread-scoped memory.",
tools=get_user_preferences,
context_providers=[Mem0ContextProvider(
user_id=user_id,
scope_to_per_operation_thread_id=True, # Isolate memories per session
)],
context_providers=[
Mem0ContextProvider(
source_id="mem0",
user_id=user_id,
scope_to_per_operation_thread_id=True, # Isolate memories per session
)
],
) as scoped_agent,
):
# Create a specific session for this scoped provider
@@ -119,16 +125,22 @@ async def example_multiple_agents() -> None:
AzureAIAgentClient(credential=credential).as_agent(
name="PersonalAssistant",
instructions="You are a personal assistant that helps with personal tasks.",
context_providers=[Mem0ContextProvider(
agent_id=agent_id_1,
)],
context_providers=[
Mem0ContextProvider(
source_id="mem0",
agent_id=agent_id_1,
)
],
) as personal_agent,
AzureAIAgentClient(credential=credential).as_agent(
name="WorkAssistant",
instructions="You are a work assistant that helps with professional tasks.",
context_providers=[Mem0ContextProvider(
agent_id=agent_id_2,
)],
context_providers=[
Mem0ContextProvider(
source_id="mem0",
agent_id=agent_id_2,
)
],
) as work_agent,
):
# Store personal information
@@ -20,7 +20,8 @@ This folder contains an example demonstrating how to use the Redis context provi
1. A running Redis with RediSearch (Redis Stack or a managed service)
2. Python environment with Agent Framework Redis extra installed
3. Optional: OpenAI API key if using vector embeddings
3. Azure AI Foundry project endpoint and Azure OpenAI Responses deployment
4. Optional: OpenAI API key if using vector embeddings
### Install the package
@@ -50,6 +51,8 @@ See quickstart: `https://learn.microsoft.com/azure/redis/quickstart-create-manag
### Environment variables
- `AZURE_AI_PROJECT_ENDPOINT` (required): Azure AI Foundry project endpoint for `AzureOpenAIResponsesClient`
- `AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME` (required): Azure OpenAI Responses deployment name
- `OPENAI_API_KEY` (optional): Required only if you set `vectorizer_choice="openai"` to enable hybrid search.
### Provider configuration highlights
@@ -70,19 +73,26 @@ The provider supports both fulltext only and hybrid vector search:
2. Agent integration: teaches the agent a preference and verifies it is remembered across turns.
3. Agent + tool: calls a sample tool (flight search) and then asks the agent to recall details remembered from the tool output.
It uses OpenAI for both chat (via `OpenAIChatClient`) and, in some steps, optional embeddings for hybrid search.
It uses `AzureOpenAIResponsesClient` (Foundry project endpoint setup) for chat and, in some steps, optional OpenAI embeddings for hybrid search.
## How to run
1) Start Redis (see options above). For local default, ensure it's reachable at `redis://localhost:6379`.
2) Set your OpenAI key if using embeddings and for the chat client used in the sample:
2) Set Azure Foundry/OpenAI responses environment variables:
```bash
export AZURE_AI_PROJECT_ENDPOINT="https://<resource>.services.ai.azure.com/api/projects/<project>"
export AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME="<deployment-name>"
```
3) (Optional) Set your OpenAI key if using embeddings:
```bash
export OPENAI_API_KEY="<your key>"
```
3) Run the example:
4) Run the example:
```bash
python redis_basics.py
@@ -109,5 +119,6 @@ You should see the agent responses and, when using embeddings, context retrieved
## Troubleshooting
- Ensure at least one of `application_id`, `agent_id`, `user_id`, or `thread_id` is set; the provider requires a scope.
- Verify `AZURE_AI_PROJECT_ENDPOINT` and `AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME` are set for the chat client.
- If using embeddings, verify `OPENAI_API_KEY` is set and reachable.
- Make sure Redis exposes RediSearch (Redis Stack image or managed service with search enabled).
@@ -13,24 +13,25 @@ Requirements:
Environment Variables:
- AZURE_REDIS_HOST: Your Azure Managed Redis host (e.g., myredis.redis.cache.windows.net)
- OPENAI_API_KEY: Your OpenAI API key
- OPENAI_CHAT_MODEL_ID: OpenAI model (e.g., gpt-4o-mini)
- AZURE_AI_PROJECT_ENDPOINT: Your Azure AI Foundry project endpoint
- AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME: Azure OpenAI Responses deployment name
- AZURE_USER_OBJECT_ID: Your Azure AD User Object ID for authentication
"""
import asyncio
import os
from agent_framework.openai import OpenAIChatClient
from agent_framework.azure import AzureOpenAIResponsesClient
from agent_framework.redis import RedisHistoryProvider
from azure.identity.aio import AzureCliCredential
from azure.identity import AzureCliCredential
from azure.identity.aio import AzureCliCredential as AsyncAzureCliCredential
from redis.credentials import CredentialProvider
class AzureCredentialProvider(CredentialProvider):
"""Credential provider for Azure AD authentication with Redis Enterprise."""
def __init__(self, azure_credential: AzureCliCredential, user_object_id: str):
def __init__(self, azure_credential: AsyncAzureCliCredential, user_object_id: str):
self.azure_credential = azure_credential
self.user_object_id = user_object_id
@@ -57,24 +58,26 @@ async def main() -> None:
return
# Create Azure CLI credential provider (uses 'az login' credentials)
azure_credential = AzureCliCredential()
azure_credential = AsyncAzureCliCredential()
credential_provider = AzureCredentialProvider(azure_credential, user_object_id)
session_id = "azure_test_session"
# Create Azure Redis history provider
history_provider = RedisHistoryProvider(
source_id="redis_memory",
credential_provider=credential_provider,
host=redis_host,
port=10000,
ssl=True,
thread_id=session_id,
key_prefix="chat_messages",
max_messages=100,
)
# Create chat client
client = OpenAIChatClient()
client = AzureOpenAIResponsesClient(
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
deployment_name=os.environ["AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME"],
credential=AzureCliCredential(),
)
# Create agent with Azure Redis history provider
agent = client.as_agent(
@@ -31,13 +31,16 @@ import asyncio
import os
from agent_framework import Message, tool
from agent_framework.openai import OpenAIChatClient
from agent_framework.azure import AzureOpenAIResponsesClient
from agent_framework.redis import RedisContextProvider
from azure.identity import AzureCliCredential
from redisvl.extensions.cache.embeddings import EmbeddingsCache
from redisvl.utils.vectorize import OpenAITextVectorizer
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/02-agents/tools/function_tool_with_approval.py and samples/02-agents/tools/function_tool_with_approval_and_sessions.py.
# NOTE: approval_mode="never_require" is for sample brevity.
# Use "always_require" in production; see samples/02-agents/tools/function_tool_with_approval.py
# and samples/02-agents/tools/function_tool_with_approval_and_sessions.py.
@tool(approval_mode="never_require")
def search_flights(origin_airport_code: str, destination_airport_code: str, detailed: bool = False) -> str:
"""Simulated flight-search tool to demonstrate tool memory.
@@ -88,6 +91,15 @@ def search_flights(origin_airport_code: str, destination_airport_code: str, deta
)
def create_chat_client() -> AzureOpenAIResponsesClient:
"""Create an Azure OpenAI Responses client using a Foundry project endpoint."""
return AzureOpenAIResponsesClient(
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
deployment_name=os.environ["AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME"],
credential=AzureCliCredential(),
)
async def main() -> None:
"""Walk through provider-only, agent integration, and tool-memory scenarios.
@@ -100,8 +112,8 @@ async def main() -> None:
print("-" * 40)
# Create a provider with partition scope and OpenAI embeddings
# Please set the OPENAI_API_KEY and OPENAI_CHAT_MODEL_ID environment variables to use the OpenAI vectorizer
# Recommend default for OPENAI_CHAT_MODEL_ID is gpt-4o-mini
# Please set OPENAI_API_KEY to use the OpenAI vectorizer.
# For chat responses, also set AZURE_AI_PROJECT_ENDPOINT and AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME.
# We attach an embedding vectorizer so the provider can perform hybrid (text + vector)
# retrieval. If you prefer text-only retrieval, instantiate RedisContextProvider without the
@@ -115,6 +127,7 @@ async def main() -> None:
# scope data for multi-tenant separation; thread_id (set later) narrows to a
# specific conversation.
provider = RedisContextProvider(
source_id="redis_context",
redis_url="redis://localhost:6379",
index_name="redis_basics",
application_id="matrix_of_kermits",
@@ -170,6 +183,7 @@ async def main() -> None:
)
# Recreate a clean index so the next scenario starts fresh
provider = RedisContextProvider(
source_id="redis_context",
redis_url="redis://localhost:6379",
index_name="redis_basics_2",
prefix="context_2",
@@ -183,7 +197,7 @@ async def main() -> None:
)
# Create chat client for the agent
client = OpenAIChatClient(model_id=os.getenv("OPENAI_CHAT_MODEL_ID"), api_key=os.getenv("OPENAI_API_KEY"))
client = create_chat_client()
# Create agent wired to the Redis context provider. The provider automatically
# persists conversational details and surfaces relevant context on each turn.
agent = client.as_agent(
@@ -217,6 +231,7 @@ async def main() -> None:
print("-" * 40)
# Text-only provider (full-text search only). Omits vectorizer and related params.
provider = RedisContextProvider(
source_id="redis_context",
redis_url="redis://localhost:6379",
index_name="redis_basics_3",
prefix="context_3",
@@ -227,7 +242,7 @@ async def main() -> None:
# Create agent exposing the flight search tool. Tool outputs are captured by the
# provider and become retrievable context for later turns.
client = OpenAIChatClient(model_id=os.getenv("OPENAI_CHAT_MODEL_ID"), api_key=os.getenv("OPENAI_API_KEY"))
client = create_chat_client()
agent = client.as_agent(
name="MemoryEnhancedAssistant",
instructions=(
@@ -17,8 +17,9 @@ Run:
import asyncio
import os
from agent_framework.openai import OpenAIChatClient
from agent_framework.azure import AzureOpenAIResponsesClient
from agent_framework.redis import RedisContextProvider
from azure.identity import AzureCliCredential
from redisvl.extensions.cache.embeddings import EmbeddingsCache
from redisvl.utils.vectorize import OpenAITextVectorizer
@@ -36,9 +37,8 @@ async def main() -> None:
cache=EmbeddingsCache(name="openai_embeddings_cache", redis_url="redis://localhost:6379"),
)
session_id = "test_session"
provider = RedisContextProvider(
source_id="redis_context",
redis_url="redis://localhost:6379",
index_name="redis_conversation",
prefix="redis_conversation",
@@ -49,11 +49,14 @@ async def main() -> None:
vector_field_name="vector",
vector_algorithm="hnsw",
vector_distance_metric="cosine",
thread_id=session_id,
)
# Create chat client for the agent
client = OpenAIChatClient(model_id=os.getenv("OPENAI_CHAT_MODEL_ID"), api_key=os.getenv("OPENAI_API_KEY"))
client = AzureOpenAIResponsesClient(
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
deployment_name=os.environ["AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME"],
credential=AzureCliCredential(),
)
# Create agent wired to the Redis context provider. The provider automatically
# persists conversational details and surfaces relevant context on each turn.
agent = client.as_agent(
@@ -28,15 +28,24 @@ Run:
import asyncio
import os
import uuid
from agent_framework.openai import OpenAIChatClient
from agent_framework.azure import AzureOpenAIResponsesClient
from agent_framework.redis import RedisContextProvider
from azure.identity import AzureCliCredential
from redisvl.extensions.cache.embeddings import EmbeddingsCache
from redisvl.utils.vectorize import OpenAITextVectorizer
# Please set the OPENAI_API_KEY and OPENAI_CHAT_MODEL_ID environment variables to use the OpenAI vectorizer
# Recommend default for OPENAI_CHAT_MODEL_ID is gpt-4o-mini
# Please set OPENAI_API_KEY to use the OpenAI vectorizer.
# For chat responses, also set AZURE_AI_PROJECT_ENDPOINT and AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME.
def create_chat_client() -> AzureOpenAIResponsesClient:
"""Create an Azure OpenAI Responses client using a Foundry project endpoint."""
return AzureOpenAIResponsesClient(
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
deployment_name=os.environ["AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME"],
credential=AzureCliCredential(),
)
async def example_global_thread_scope() -> None:
@@ -44,20 +53,15 @@ async def example_global_thread_scope() -> None:
print("1. Global Thread Scope Example:")
print("-" * 40)
global_thread_id = str(uuid.uuid4())
client = OpenAIChatClient(
model_id=os.getenv("OPENAI_CHAT_MODEL_ID", "gpt-4o-mini"),
api_key=os.getenv("OPENAI_API_KEY"),
)
client = create_chat_client()
provider = RedisContextProvider(
source_id="redis_context",
redis_url="redis://localhost:6379",
index_name="redis_threads_global",
application_id="threads_demo_app",
agent_id="threads_demo_agent",
user_id="threads_demo_user",
thread_id=global_thread_id,
scope_to_per_operation_thread_id=False, # Share memories across all sessions
)
@@ -97,10 +101,7 @@ async def example_per_operation_thread_scope() -> None:
print("2. Per-Operation Thread Scope Example:")
print("-" * 40)
client = OpenAIChatClient(
model_id=os.getenv("OPENAI_CHAT_MODEL_ID", "gpt-4o-mini"),
api_key=os.getenv("OPENAI_API_KEY"),
)
client = create_chat_client()
vectorizer = OpenAITextVectorizer(
model="text-embedding-ada-002",
@@ -109,6 +110,7 @@ async def example_per_operation_thread_scope() -> None:
)
provider = RedisContextProvider(
source_id="redis_context",
redis_url="redis://localhost:6379",
index_name="redis_threads_dynamic",
# overwrite_redis_index=True,
@@ -165,10 +167,7 @@ async def example_multiple_agents() -> None:
print("3. Multiple Agents with Different Thread Configurations:")
print("-" * 40)
client = OpenAIChatClient(
model_id=os.getenv("OPENAI_CHAT_MODEL_ID", "gpt-4o-mini"),
api_key=os.getenv("OPENAI_API_KEY"),
)
client = create_chat_client()
vectorizer = OpenAITextVectorizer(
model="text-embedding-ada-002",
@@ -177,6 +176,7 @@ async def example_multiple_agents() -> None:
)
personal_provider = RedisContextProvider(
source_id="redis_context",
redis_url="redis://localhost:6379",
index_name="redis_threads_agents",
application_id="threads_demo_app",
@@ -195,6 +195,7 @@ async def example_multiple_agents() -> None:
)
work_provider = RedisContextProvider(
source_id="redis_context",
redis_url="redis://localhost:6379",
index_name="redis_threads_agents",
application_id="threads_demo_app",
@@ -1,11 +1,13 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from contextlib import suppress
from typing import Any
from agent_framework import Agent, AgentSession, BaseContextProvider, SessionContext, SupportsChatGetResponse
from agent_framework.azure import AzureAIClient
from azure.identity.aio import AzureCliCredential
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
from pydantic import BaseModel
@@ -15,19 +17,13 @@ class UserInfo(BaseModel):
class UserInfoMemory(BaseContextProvider):
def __init__(self, client: SupportsChatGetResponse, user_info: UserInfo | None = None, **kwargs: Any):
def __init__(self, source_id: str = "user-info-memory", *, client: SupportsChatGetResponse, **kwargs: Any):
"""Create the memory.
If you pass in kwargs, they will be attempted to be used to create a UserInfo object.
"""
super().__init__("user-info-memory")
super().__init__(source_id)
self._chat_client = client
if user_info:
self.user_info = user_info
elif kwargs:
self.user_info = UserInfo.model_validate(kwargs)
else:
self.user_info = UserInfo()
async def after_run(
self,
@@ -38,12 +34,15 @@ class UserInfoMemory(BaseContextProvider):
state: dict[str, Any],
) -> None:
"""Extract user information from messages after each agent call."""
request_messages = context.get_messages()
# ensure you get all the messages you want to parse from, including the input in this case.
request_messages = context.get_messages(include_input=True, include_response=True)
# Check if we need to extract user info from user messages
user_messages = [msg for msg in request_messages if hasattr(msg, "role") and msg.role == "user"] # type: ignore
if (self.user_info.name is None or self.user_info.age is None) and user_messages:
try:
if (
state[self.source_id]["user_info"].name is None or state[self.source_id]["user_info"].age is None
) and user_messages:
with suppress(Exception):
# Use the chat client to extract structured information
result = await self._chat_client.get_response(
messages=request_messages, # type: ignore
@@ -53,17 +52,12 @@ class UserInfoMemory(BaseContextProvider):
)
# Update user info with extracted data
try:
with suppress(Exception):
extracted = result.value
if self.user_info.name is None and extracted.name:
self.user_info.name = extracted.name
if self.user_info.age is None and extracted.age:
self.user_info.age = extracted.age
except Exception:
pass # Failed to extract, continue without updating
except Exception:
pass # Failed to extract, continue without updating
if state[self.source_id]["user_info"].name is None and extracted.name:
state[self.source_id]["user_info"].name = extracted.name
if state[self.source_id]["user_info"].age is None and extracted.age:
state[self.source_id]["user_info"].age = extracted.age
async def before_run(
self,
@@ -74,55 +68,52 @@ class UserInfoMemory(BaseContextProvider):
state: dict[str, Any],
) -> None:
"""Provide user information context before each agent call."""
instructions: list[str] = []
if state.setdefault(self.source_id, None) is None:
state[self.source_id] = {"user_info": UserInfo()}
if self.user_info.name is None:
instructions.append(
"Ask the user for their name and politely decline to answer any questions until they provide it."
)
else:
instructions.append(f"The user's name is {self.user_info.name}.")
if self.user_info.age is None:
instructions.append(
"Ask the user for their age and politely decline to answer any questions until they provide it."
)
else:
instructions.append(f"The user's age is {self.user_info.age}.")
# Add context with additional instructions
context.extend_instructions(self.source_id, " ".join(instructions))
def serialize(self) -> str:
"""Serialize the user info for session persistence."""
return self.user_info.model_dump_json()
context.extend_instructions(
self.source_id,
"Ask the user for their name and politely decline to answer any questions until they provide it."
if state[self.source_id]["user_info"].name is None
else f"The user's name is {state[self.source_id]['user_info'].name}.",
)
context.extend_instructions(
self.source_id,
"Ask the user for their age and politely decline to answer any questions until they provide it."
if state[self.source_id]["user_info"].age is None
else f"The user's age is {state[self.source_id]['user_info'].age}.",
)
async def main():
async with AzureCliCredential() as credential:
client = AzureAIClient(credential=credential)
client = AzureOpenAIResponsesClient(
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
deployment_name=os.environ["AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME"],
credential=AzureCliCredential(),
)
# Create the memory provider
memory_provider = UserInfoMemory(client)
context_name = "user-info-memory"
# Create the agent with memory
async with Agent(
client=client,
instructions="You are a friendly assistant. Always address the user by their name.",
context_providers=[memory_provider],
) as agent:
# Create a new session for the conversation
session = agent.create_session()
# Create the memory provider
memory_provider = UserInfoMemory(context_name, client=client)
print(await agent.run("Hello, what is the square root of 9?", session=session))
print(await agent.run("My name is Ruaidhrí", session=session))
print(await agent.run("I am 20 years old", session=session))
# Create the agent with memory
async with Agent(
client=client,
instructions="You are a friendly assistant. Always address the user by their name.",
context_providers=[memory_provider],
) as agent:
# Create a new session for the conversation
session = agent.create_session()
# Access the memory component and inspect the memories
if memory_provider:
print()
print(f"MEMORY - User Name: {memory_provider.user_info.name}")
print(f"MEMORY - User Age: {memory_provider.user_info.age}")
for msg in ["Hello, what is the square root of 9?", "My name is Ruaidhrí", "I am 20 years old"]:
print(f"User: {msg}")
print(f"Assistant: {await agent.run(msg, session=session)}")
# Access the memory component and inspect the memories
print()
print(f"MEMORY - User Name: {session.state[context_name]['user_info'].name}")
print(f"MEMORY - User Age: {session.state[context_name]['user_info'].age}")
if __name__ == "__main__":