Skip to content

Sessions

Sessions enable conversation persistence across multiple interactions, allowing your agent to maintain context and remember previous messages.

Overview

graph LR
    A[User Message] --> B[Agent]
    B --> C[Session Manager]
    C --> D[(SQLite DB)]
    D --> C
    C --> B
    B --> E[Response]

Session Manager

Required Component

The SessionManager is required when creating an Agent. It handles all conversation persistence.

Create a session manager with a SQLite database:

session_setup.py
from pathlib import Path
from nagents import Agent, SessionManager, Provider, ProviderType

# Create session manager
session_manager = SessionManager(Path("sessions.db"))  # (1)!

# Create agent with session manager
agent = Agent(
    provider=provider,
    session_manager=session_manager,
)
  1. The database file will be created automatically if it doesn't exist.

Using Sessions

Specify a session_id to maintain conversation history:

session_usage.py
# First interaction
async for event in agent.run(
    "My name is Alice",
    session_id="user-123",
):
    ...

# Later interaction (same session)
async for event in agent.run(
    "What's my name?",
    session_id="user-123",
):
    # Agent remembers: "Your name is Alice"
    ...

Session ID Best Practices

Use meaningful, consistent session IDs:

  • User-based: user-{user_id}
  • Conversation-based: conv-{uuid}
  • Thread-based: thread-{thread_id}

Auto-Generated Sessions

If no session_id is provided, a new session is created automatically:

auto_session.py
async for event in agent.run("Hello"):
    if isinstance(event, DoneEvent):
        print(f"Session ID: {event.session_id}")
        # Save this ID to continue the conversation later

Session Data

Sessions store:

  • Conversation messages - User, assistant, tool calls/results
  • Session metadata - created_at, updated_at, user_id
  • System prompt - At session creation time
Database Schema
CREATE TABLE sessions (
    id TEXT PRIMARY KEY,
    user_id TEXT,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    system_prompt TEXT
);

CREATE TABLE messages (
    id INTEGER PRIMARY KEY,
    session_id TEXT REFERENCES sessions(id),
    role TEXT,
    content TEXT,
    tool_calls TEXT,  -- JSON
    created_at TIMESTAMP
);

User Association

Associate sessions with users for multi-user applications:

user_sessions.py
async for event in agent.run(
    "Hello",
    session_id="conversation-456",
    user_id="user-123",
):
    ...

This allows you to:

  • Query all sessions for a user
  • Implement user-specific context
  • Track usage per user

Session Lifecycle

stateDiagram-v2
    [*] --> Created: agent.run() with new session_id
    Created --> Active: Messages added
    Active --> Active: More messages
    Active --> Closed: agent.close()
    Closed --> [*]
lifecycle.py
from pathlib import Path
from nagents import Agent, SessionManager

async def main():
    session_manager = SessionManager(Path("sessions.db"))

    # Initialize (creates tables if needed)
    await session_manager.initialize()  # (1)!

    agent = Agent(provider=provider, session_manager=session_manager)

    # Sessions are automatically created/updated during agent.run()
    async for event in agent.run("Hello", session_id="test"):
        ...

    # Close when done
    await agent.close()  # (2)!
  1. Called automatically by Agent, but can be called explicitly.
  2. Also closes the session manager.

Multiple Sessions

Handle multiple concurrent sessions easily:

multi_session.py
# User A's conversation
async for event in agent.run(
    "I like pizza",
    session_id="user-a-session",
):
    ...

# User B's conversation (completely separate)
async for event in agent.run(
    "I prefer sushi",
    session_id="user-b-session",
):
    ...

# Back to User A (remembers pizza preference)
async for event in agent.run(
    "What food do I like?",
    session_id="user-a-session",
):
    # Agent responds about pizza
    ...

Session Isolation

Each session is completely isolated:

isolation_example.py
# Session 1: Set a name
await run_agent("My name is Alice", session_id="session-1")

# Session 2: Different conversation
await run_agent("My name is Bob", session_id="session-2")

# Session 1: Remembers Alice
await run_agent("What's my name?", session_id="session-1")
# Response: "Your name is Alice"

# Session 2: Remembers Bob
await run_agent("What's my name?", session_id="session-2")
# Response: "Your name is Bob"

Example: Chat Application

Here's a complete example of a session-based chat application:

chat_app.py
import asyncio
from pathlib import Path
from nagents import Agent, Provider, ProviderType, SessionManager, DoneEvent

async def chat(session_id: str):
    """Run an interactive chat session."""

    provider = Provider(
        provider_type=ProviderType.OPENAI_COMPATIBLE,
        api_key="sk-...",
        model="gpt-4o-mini",
    )

    session_manager = SessionManager(Path("chat.db"))

    agent = Agent(
        provider=provider,
        session_manager=session_manager,
        system_prompt="You are a helpful assistant. Be concise.",
    )

    print(f"Chat session: {session_id}")
    print("Type 'quit' to exit\n")

    while True:
        user_input = input("You: ").strip()
        if user_input.lower() == "quit":
            break

        print("Assistant: ", end="")
        async for event in agent.run(user_input, session_id=session_id):
            if hasattr(event, 'chunk'):
                print(event.chunk, end="", flush=True)
        print()  # newline

    await agent.close()
    print("\nGoodbye!")

if __name__ == "__main__":
    import sys
    session_id = sys.argv[1] if len(sys.argv) > 1 else "default"
    asyncio.run(chat(session_id))

Usage:

# Start a new session
python chat_app.py my-session

# Continue the same session later
python chat_app.py my-session

Best Practices

Session Management Tips

  1. Use meaningful session IDs - Makes debugging easier
  2. Associate with users - Use user_id for multi-user apps
  3. Handle session cleanup - Consider implementing session expiration
  4. Don't store sensitive data - Sessions are stored in SQLite
  5. Close properly - Always call agent.close() when done