Context Manager¶
Overview¶
Context Manager provides a convenient way to manage the context lifecycle. It consists of:
a set of context services (session history, memory)
a
ContextComposer
to orchestrate history and memory updates
Services¶
The services
in context manager are those that are required for the context.
For example, if you want to use the context manager to manage the session history, you need to add the SessionHistoryService
to the services list.
We provide some basic built-in services for you to use. And you can also create your own services.
Here are the built-in services:
SessionHistoryService¶
SessionHistoryService
is a base class to manage the session history.
It contains the following methods
create_session
: create a new sessionget_session
: get a sessiondelete_session
: delete a sessionlist_sessions
: list all sessionsappend_message
: append a message to the history
Since the SessionHistoryService
is a base class, use a concrete implementation instead.
For example, we provide an InMemorySessionHistoryService
to store history in memory. For details, see here
MemoryService¶
The MemoryService
is a basic class to manage the memory.
In Agent, memory stores previous conversation of an end-user.
For example, an end-user may mention their name in a previous conversation.
The memory service will store it so that the agent can use it in the next conversation.
The MemoryService
contains the following methods:
add_memory
: add a memory to the memory servicesearch_memory
: search a memory from the memory servicedelete_memory
: delete a memory from the memory servicelist_memory
: list all memories
Like SessionHistoryService
, prefer using a concrete implementation such as InMemoryMemoryService
. For details, see here
RAGService¶
The RAGService
is a basic class to provide retrieval augmented generation (RAG) capabilities.
When asked by an end-user, the agent may need to retrieve relevant information from the knowledge base.
The knowledge base can be a database or a collection of documents.
The RAGService
contains the following methods:
retrieve
: retrieve relevant information from the knowledge base.
The LangChainRAGService
is a concrete implementation of RAGService
that uses LangChain to retrieve relevant information.
It can be initialized by:
vectorstore
the vectorstore to be indexed. Specifically, it can be aVectorStore
instance of LangChain.embedding
the embedding model to be used for indexing.
Read more about RAGService here
Life-cycle of a context manager¶
The context manager can be initialized by two ways:
Initialize an instance directly¶
The simplest way is to initialize an instance directly.
from agentscope_runtime.engine.services.context_manager import ContextManager
from agentscope_runtime.engine.services.session_history_service import InMemorySessionHistoryService
from agentscope_runtime.engine.services.memory_service import InMemoryMemoryService
session_history_service = InMemorySessionHistoryService()
memory_service = InMemoryMemoryService()
context_manager = ContextManager(
session_history_service=session_history_service,
memory_service=memory_service
)
# use the manager
async with context_manager as services:
session = await services.compose_session(user_id="u1", session_id="s1")
await services.compose_context(session, request_input=[])
Use the async factory helper¶
We provide a factory function to create a context manager.
from agentscope_runtime.engine.services.context_manager import create_context_manager
from agentscope_runtime.engine.services.session_history_service import InMemorySessionHistoryService
from agentscope_runtime.engine.services.memory_service import InMemoryMemoryService
async with create_context_manager(
session_history_service=InMemorySessionHistoryService(),
memory_service=InMemoryMemoryService(),
) as manager:
session = await manager.compose_session(user_id="u1", session_id="s1")
await manager.compose_context(session, request_input=[])
ContextComposer¶
The ContextComposer
is a class to compose the context.
It will be called by the context manager when the context is created.
The ContextComposer
contains a static method:
compose
: compose the context
It provides a sequential composition method and can be overridden by subclasses.
Pass a custom composer class to ContextManager
when initializing.
from agentscope_runtime.engine.services.context_manager import ContextManager, ContextComposer
from agentscope_runtime.engine.services.session_history_service import InMemorySessionHistoryService
from agentscope_runtime.engine.services.memory_service import InMemoryMemoryService
async with ContextManager(
session_history_service=InMemorySessionHistoryService(),
memory_service=InMemoryMemoryService(),
context_composer_cls=ContextComposer,
) as manager:
session = await manager.compose_session(user_id="u1", session_id="s1")
await manager.compose_context(session, request_input=[])
Appending outputs to context¶
from agentscope_runtime.engine.services.context_manager import create_context_manager
async with create_context_manager() as manager:
session = await manager.compose_session(user_id="u1", session_id="s1")
await manager.append(session, event_output=[])
Available Memory Services¶
MemoryType |
Import |
Note |
---|---|---|
InMemoryMemoryService |
|
|
RedisMemoryService |
|
|
ReMe.PersonalMemoryService |
|
|
ReMe.TaskMemoryService |
|
|
Mem0MemoryService |
|
|
TablestoreMemoryService |
|
develop by tablestore-for-agent-memory |
Description¶
InMemoryMemoryService: An in-memory memory service without persistent storage.
RedisMemoryService: A memory service leveraging Redis for persistent storage.
ReMe.PersonalMemoryService: ReMe’s personalized memory service (formerly MemoryScope) empowers you to generate, retrieve, and share customized memories. Leveraging advanced LLM, embedding, and vector store technologies, it builds a comprehensive memory system with intelligent, context- and time-aware memory management—seamlessly enabling you to configure and deploy powerful AI agents.
ReMe.TaskMemoryService: ReMe’s task-oriented memory service helps you efficiently manage and schedule task-related memories, enhancing both the accuracy and efficiency of task execution. Powered by LLM capabilities, it supports flexible creation, retrieval, update, and deletion of memories across diverse task scenarios—enabling you to effortlessly build and scale robust agent-based task systems.
Mem0MemoryService: An intelligent memory service powered by the mem0 platform, providing long-term memory storage and management capabilities. Supports asynchronous operations and automatically extracts, stores, and retrieves key information from conversations, enabling context-aware memory for AI agents. Ideal for complex conversational scenarios and agent applications requiring persistent memory. (For more details, see mem0 platform documentation)
TablestoreMemoryService: A memory service based on aliyun tablestore (Tablestore provides Serverless table storage services for massive structured data, and provides a one-stop IoTstore solution for deep optimization of IoT scenarios. It is suitable for structured data storage in scenarios such as massive bills, IM messages, IoT, Internet of Vehicles, risk control, and recommendations, and provides low-cost storage of massive data, millisecond-level online data query and retrieval, and flexible data analysis capabilities), develop by tablestore-for-agent-memory. Example:
from agentscope_runtime.engine.services.tablestore_memory_service import TablestoreMemoryService
from agentscope_runtime.engine.services.utils.tablestore_service_utils import create_tablestore_client
from agentscope_runtime.engine.services.tablestore_memory_service import SearchStrategy
# create tablestore memory service, default search strategy is full text
tablestore_memory_service = TablestoreMemoryService(
tablestore_client=create_tablestore_client(
end_point="your_endpoint",
instance_name="your_instance_name",
access_key_id="your_access_key_id",
access_key_secret="your_access_key_secret",
),
)
# Create a tablestore memory service based on vector retrieval, with DashScopeEmbeddings() as the default embedding model
tablestore_memory_service = TablestoreMemoryService(
tablestore_client=create_tablestore_client(
end_point="your_endpoint",
instance_name="your_instance_name",
access_key_id="your_access_key_id",
access_key_secret="your_access_key_secret",
),
search_strategy=SearchStrategy.VECTOR,
)
Details about Session History Service¶
The Session History Service manages conversation sessions for users, providing a structured way to handle conversation history and message storage. Each session contains the history of a conversation and is uniquely identified by its ID.
Service Overview¶
The Session Service provides an abstract interface for session management with concrete implementations like InMemorySessionHistoryService
.
from agentscope_runtime.engine.services.session_history_service import InMemorySessionHistoryService, Session
# Create a session service instance
session_history_service = InMemorySessionHistoryService()
Session Object Structure¶
Each session is represented by a Session
object with the following structure:
from agentscope_runtime.engine.services.session_history_service import Session
from agentscope_runtime.engine.schemas.agent_schemas import Message, TextContent, Role
# Session object structure
session_obj = Session(
id="session_123",
user_id="user_456",
messages=[
Message(role=Role.USER, content=[TextContent(type="text", text="Hello")]),
Message(role=Role.ASSISTANT, content=[TextContent(type="text", text="Hi there!")]),
],
)
print(f"Session ID: {session_obj.id}")
print(f"User ID: {session_obj.user_id}")
print(f"Message count: {len(session_obj.messages)}")
Core Functionality¶
Creating Sessions¶
The create_session
method creates new conversation sessions for users:
import asyncio
async def main():
# Create a session with auto-generated ID
user_id = "test_user"
session = await session_history_service.create_session(user_id)
print(f"Created session: {session.id}")
print(f"User ID: {session.user_id}")
print(f"Messages count: {len(session.messages)}")
# Create a session with custom ID
custom_session = await session_history_service.create_session(
user_id,
session_id="my_custom_session_id",
)
print(f"Custom session ID: {custom_session.id}")
await main()
Retrieving Sessions¶
The get_session
method retrieves specific sessions by user ID and session ID:
import asyncio
async def main():
user_id = "u1"
# Retrieve an existing session (auto-creates if not exists in in-memory impl)
retrieved_session = await session_history_service.get_session(user_id, "s1")
assert retrieved_session is not None
await main()
Listing Sessions¶
The list_sessions
method provides a list of all sessions for a user:
import asyncio
async def main():
user_id = "u_list"
# Create multiple sessions
session1 = await session_history_service.create_session(user_id)
session2 = await session_history_service.create_session(user_id)
# List all sessions (without message history for efficiency)
listed_sessions = await session_history_service.list_sessions(user_id)
assert len(listed_sessions) >= 2
# Returned sessions don't include message history
for s in listed_sessions:
assert s.messages == [], "History should be empty in list view"
await main()
Appending Messages¶
The append_message
method adds messages to session history and supports multiple message formats:
Using Dictionary Format¶
import asyncio
from agentscope_runtime.engine.schemas.agent_schemas import Message, TextContent
async def main():
user_id = "u_append"
# Create a session and add messages (dict format is also accepted)
session = await session_history_service.create_session(user_id)
# Append a single message (Message object)
message1 = Message(role="user", content=[TextContent(type="text", text="Hello, world!")])
await session_history_service.append_message(session, message1)
# Verify message was added
assert len(session.messages) == 1
# Append multiple messages at once (mixed formats)
messages3 = [
{"role": "user", "content": [{"type": "text", "text": "How are you?"}]},
Message(role="assistant", content=[TextContent(type="text", text="I am fine, thank you.")]),
]
await session_history_service.append_message(session, messages3)
# Verify all messages were added
assert len(session.messages) == 3
await main()
Using Built-in Message Format¶
from agentscope_runtime.engine.schemas.agent_schemas import Message, TextContent, MessageType, Role
# Create a session
session = await session_history_service.create_session(user_id)
# Add a single message using built-in Message format
message1 = Message(
type=MessageType.MESSAGE,
role=Role.USER,
content=[TextContent(type="text", text="Hello, world!")]
)
await session_history_service.append_message(session, message1)
# Verify the message was added
assert len(session.messages) == 1
# Session stores actual Message objects in memory for the in-memory impl
assert session.messages[0].role == "user"
assert session.messages[0].content[0].text == "Hello, world!"
# Add assistant reply message
message2 = Message(
type=MessageType.MESSAGE,
role=Role.ASSISTANT,
content=[TextContent(type="text", text="Hi there! How can I help you?")]
)
await session_history_service.append_message(session, message2)
# Add multiple built-in Message format messages at once
messages3 = [
Message(
type=MessageType.MESSAGE,
role=Role.USER,
content=[TextContent(type="text", text="What's the weather like?")]
),
Message(
type=MessageType.MESSAGE,
role=Role.ASSISTANT,
content=[TextContent(type="text", text="I don't have access to real-time weather data.")]
)
]
await session_history_service.append_message(session, messages3)
# Verify all messages were added
assert len(session.messages) == 4
Mixed Format Support¶
# Session service supports mixing dictionary and Message objects
session = await session_history_service.create_session(user_id)
# Add dictionary format message
dict_message = {"role": "user", "content": "Hello"}
await session_history_service.append_message(session, dict_message)
# Add Message object
message_obj = Message(
type=MessageType.MESSAGE,
role=Role.ASSISTANT,
content=[TextContent(type="text", text="Hello! How can I assist you?")]
)
await session_history_service.append_message(session, message_obj)
# Verify messages were added correctly
assert len(session.messages) == 2
assert session.messages[0]["role"] == "user" # Dictionary format
assert session.messages[1]["role"] == "assistant" # Message object converted to dictionary format
Deleting Sessions¶
The delete_session
method removes specific sessions:
# Create and then delete a session
session_to_delete = await session_history_service.create_session(user_id)
session_id = session_to_delete.id
# Verify session exists
assert await session_history_service.get_session(user_id, session_id) is not None
# Delete the session
await session_history_service.delete_session(user_id, session_id)
# Verify session is deleted
assert await session_history_service.get_session(user_id, session_id) is None
# Deleting non-existent sessions doesn't raise errors
await session_history_service.delete_session(user_id, "non_existent_id")
Service Lifecycle¶
The Session Service follows a simple lifecycle pattern:
# Start the service (optional for InMemorySessionHistoryService)
await session_history_service.start()
# Check service health
is_healthy = await session_history_service.health()
# Stop the service (optional for InMemorySessionHistoryService)
await session_history_service.stop()
Implementation Details¶
The InMemorySessionHistoryService
stores data in a nested dictionary structure:
Top level:
{user_id: {session_id: Session}}
Each Session object contains id, user_id, and messages list
Session IDs are auto-generated using UUID if not provided
Empty or whitespace-only session IDs are replaced with auto-generated IDs
TablestoreSessionHistoryService
stores data in aliyun tablestore, example:
from agentscope_runtime.engine.services.tablestore_session_history_service import TablestoreSessionHistoryService
from agentscope_runtime.engine.services.utils.tablestore_service_utils import create_tablestore_client
tablestore_session_history_service = TablestoreSessionHistoryService(
tablestore_client=create_tablestore_client(
end_point="your_endpoint",
instance_name="your_instance_name",
access_key_id="your_access_key_id",
access_key_secret="your_access_key_secret",
),
)
Note
For production use, consider implementing persistent storage by extending the SessionHistoryService
abstract base class to support databases or file systems.
Details about Memory Service¶
The Memory Service is designed to store and retrieve long-term memory from databases or in-memory storage. Memory is organized by user ID at the top level, with the message list serving as the elemental values stored in different locations. Additionally, messages can be grouped by session ID.
Service Overview¶
The Memory Service provides an abstract interface for memory management with concrete implementations like InMemoryMemoryService
.
The following is an example to initialize an in-memory service:
from agentscope_runtime.engine.services.memory_service import InMemoryMemoryService
# Create and start the memory service
memory_service = InMemoryMemoryService()
Core Functionality¶
Adding Memory¶
The add_memory
method allows you to store messages for a specific user, optionally providing a session ID:
import asyncio
from agentscope_runtime.engine.services.memory_service import InMemoryMemoryService
from agentscope_runtime.engine.schemas.agent_schemas import Message, TextContent
# Add memory without a session ID
user_id = "user1"
messages = [
Message(
role="user",
content=[TextContent(type="text", text="hello world")]
)
]
await memory_service.add_memory(user_id, messages)
Searching Memory¶
The search_memory
method searches for messages based on content keywords:
In the in-memory
memory service, a simple keyword search algorithm is implemented
to related content based on the query from historical messages.
Other complicated search algorithms could be used to replace the simple method by implementing or overriding the class.
User could use message as a query to search for related content.
search_query = [
Message(
role="user",
content=[TextContent(type="text", text="hello")]
)
]
retrieved = await memory_service.search_memory(user_id, search_query)
Listing Memory¶
list memory method provide a paginated interface for listing memory shown below,
# List memory with pagination
memory_list = await memory_service.list_memory(
user_id,
filters={"page_size": 10, "page_num": 1}
)
Deleting Memory¶
Users can delete memory for specific sessions or entire users:
# Delete memory for specific session
await memory_service.delete_memory(user_id, session_id)
# Delete all memory for user
await memory_service.delete_memory(user_id)
Service Lifecycle¶
Managing Lifecycle through ContextManager¶
When using ContextManager, memory service lifecycle is automatically managed:
import asyncio
from agentscope_runtime.engine.services.context_manager import create_context_manager
from agentscope_runtime.engine.services.memory_service import InMemoryMemoryService
async def main():
async with create_context_manager() as context_manager:
# Register memory service - automatically started
context_manager.register(InMemoryMemoryService, name="memory")
# Service is automatically started and ready to use
memory_service = context_manager.memory
# Check service health status
health_status = await context_manager.health_check()
print(f"Memory service health status: {health_status['memory']}")
# Use service...
# When exiting context, service automatically stops and cleans up
await main()
Service Lifecycle Management¶
The Memory Service follows a standard lifecycle pattern and can be managed through start()
, stop()
, health()
:
import asyncio
from agentscope_runtime.engine.services.memory_service import InMemoryMemoryService
async def main():
# Create memory service
memory_service = InMemoryMemoryService()
# Start service
await memory_service.start()
# Check service health
is_healthy = await memory_service.health()
print(f"Service health status: {is_healthy}")
# Stop service
await memory_service.stop()
await main()
Implementation Details¶
The InMemoryMemoryService
stores data in a dictionary structure:
Top level:
{user_id: {session_id: [messages]}}
Default session ID is used when no session is specified
Keyword-based search is case-insensitive
Messages are stored in chronological order within each session
Note
For more advanced memory implementations, consider extending the MemoryService
abstract base class to support persistent storage or vector databases.