Use this file to discover all available pages before exploring further.
Sessions enable multi-turn conversations by maintaining conversation history and context across multiple agent invocations. They provide a lightweight mechanism for stateful interactions without requiring external storage.
A session is a container for conversation state that includes:
Session IDs for identifying and tracking conversations
Conversation history (stored messages)
Mutable state for context providers
Provider-managed data (memory, context, metadata)
Python
.NET
In Python, AgentSession is a lightweight state container:
class AgentSession: session_id: str # Unique session identifier service_session_id: str | None # Service-managed ID (if using service storage) state: dict[str, Any] # Mutable state shared with providers
Sessions are created per agent and can be serialized for persistence.
In .NET, AgentSession is an abstract class managed by agents:
public abstract class AgentSession{ // Session-specific implementation}
Each agent type provides its own session implementation.
from agent_framework.azure import AzureOpenAIResponsesClientimport osclient = AzureOpenAIResponsesClient( project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], deployment_name=os.environ["AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME"],)agent = client.as_agent( name="ConversationAgent", instructions="You are a friendly assistant. Keep your answers brief.",)# Create a sessionsession = agent.create_session()# Multi-turn conversationresponse1 = await agent.run("My name is Alice and I love hiking.", session=session)print(f"Agent: {response1.text}")# Agent remembers previous contextresponse2 = await agent.run("What do you remember about me?", session=session)print(f"Agent: {response2.text}")# Output: "You said your name is Alice and you love hiking."
Key points:
Call agent.create_session() to create a new session
Pass the same session object to all related run() calls
The agent automatically manages conversation history
var agent = client.GetChatClient(deploymentName).AsAIAgent( name: "ConversationAgent", instructions: "You are a friendly assistant. Keep your answers brief.");// Create a sessionvar session = await agent.CreateSessionAsync();// Multi-turn conversationvar response1 = await agent.RunAsync( "My name is Alice and I love hiking.", session: session);Console.WriteLine($"Agent: {response1.Messages.LastOrDefault()?.Text}");// Agent remembers previous contextvar response2 = await agent.RunAsync( "What do you remember about me?", session: session);Console.WriteLine($"Agent: {response2.Messages.LastOrDefault()?.Text}");
# Create session with specific ID (useful for resuming)session = agent.create_session(session_id="user-123-conversation-456")# Or get/create session for a service-managed IDsession = agent.get_session( service_session_id="azure-thread-abc123", session_id="local-session-789",)
// Create session (ID is managed by the agent implementation)var session = await agent.CreateSessionAsync();// Access session IDConsole.WriteLine($"Session ID: {session.Id}");
When you provide a session without configuring storage, the framework automatically adds an in-memory history provider:
agent = client.as_agent(name="Assistant")session = agent.create_session()# First turnawait agent.run("Hello, I'm learning Python", session=session)# Second turn - history is automatically maintainedawait agent.run("Can you recommend some resources?", session=session)# The agent sees both messages in the conversation
The InMemoryHistoryProvider is added automatically when:
A session is provided
No context providers are configured
Service-side storage is not requested (no service_session_id)
var agent = client.GetChatClient(deploymentName).AsAIAgent(name: "Assistant");var session = await agent.CreateSessionAsync();// First turnawait agent.RunAsync("Hello, I'm learning C#", session: session);// Second turn - history is automatically maintainedawait agent.RunAsync("Can you recommend some resources?", session: session);
Implement custom history storage by extending BaseHistoryProvider:
from agent_framework import BaseHistoryProvider, Messageclass DatabaseHistoryProvider(BaseHistoryProvider): def __init__(self, db_connection): super().__init__(source_id="database") self.db = db_connection async def get_messages(self, session_id: str | None, **kwargs) -> list[Message]: """Load messages from database.""" if not session_id: return [] rows = await self.db.query( "SELECT role, content FROM messages WHERE session_id = ?", session_id ) return [Message(role=row['role'], text=row['content']) for row in rows] async def save_messages( self, session_id: str | None, messages: Sequence[Message], **kwargs ) -> None: """Save messages to database.""" if not session_id: return for msg in messages: await self.db.execute( "INSERT INTO messages (session_id, role, content) VALUES (?, ?, ?)", session_id, msg.role, msg.text )# Use custom provideragent = Agent( client=client, name="Assistant", context_providers=[DatabaseHistoryProvider(db)],)
Configure what gets stored:
history_provider = DatabaseHistoryProvider( db, load_messages=True, # Load history before runs store_inputs=True, # Store user messages store_outputs=True, # Store agent responses store_context_messages=False, # Don't store provider context)
Custom history is typically managed through AIContextProvider:
// Context providers manage history and state// Implementation varies by agent type
Some services (like Azure AI Foundry) manage sessions server-side:
# Service creates and manages the sessionsession = agent.get_session( service_session_id="azure-thread-abc123")# Or pass service session ID in optionsresult = await agent.run( "Hello", options={"conversation_id": "azure-thread-abc123"},)# Service maintains history; no local storage needed
The framework automatically:
Skips local history providers when service_session_id is set
Updates session.service_session_id from service responses
Propagates conversation IDs between calls
// Service-managed sessions are handled automaticallyvar session = await agent.CreateSessionAsync();// The session ID is managed by the underlying servicevar response = await agent.RunAsync("Hello", session: session);
Sessions work with both streaming and non-streaming modes:
session = agent.create_session()# Streaming modeasync for chunk in agent.run("Tell me a story", session=session, stream=True): print(chunk.text, end="", flush=True)# History is automatically updated after stream completes# Next turn remembers the storyresult = await agent.run("What happened next?", session=session)
var session = await agent.CreateSessionAsync();// Streaming modeawait foreach (var chunk in agent.RunStreamingAsync("Tell me a story", session: session)){ Console.Write(chunk.Text);}// Next turn remembers the storyvar response = await agent.RunAsync("What happened next?", session: session);