Skip to main content
AgentLIB provides built-in session management for multi-user applications. Sessions isolate conversation history, agent state, and memory across different users or contexts.

Session Basics

Every agent run can specify a sessionId to scope the conversation:
import { createAgent } from '@agentlib/core'
import { openai } from '@agentlib/openai'
import { BufferMemory } from '@agentlib/memory'

const memory = new BufferMemory({ maxMessages: 10 })

const agent = createAgent({
  name: 'assistant',
  systemPrompt: 'You are a helpful assistant.',
})
  .provider(openai({ apiKey: process.env.OPENAI_API_KEY }))
  .memory(memory)

// User A's conversation
await agent.run({
  input: 'My name is Alice.',
  sessionId: 'user-alice',
})

// User B's conversation (completely isolated)
await agent.run({
  input: 'My name is Bob.',
  sessionId: 'user-bob',
})

// Back to User A
await agent.run({
  input: 'What is my name?',
  sessionId: 'user-alice',
})
// Agent responds: "Your name is Alice."

Session ID Strategies

1

User-Based Sessions

Use user IDs for personal conversations:
const userId = req.user.id
const result = await agent.run({
  input: userMessage,
  sessionId: `user-${userId}`,
})
2

Conversation-Based Sessions

Use conversation/thread IDs for multi-conversation apps:
const conversationId = req.params.conversationId
const result = await agent.run({
  input: userMessage,
  sessionId: conversationId,
})
3

Composite Sessions

Combine user and context for fine-grained isolation:
const sessionId = `user-${userId}-workspace-${workspaceId}`
const result = await agent.run({
  input: userMessage,
  sessionId,
})
4

Temporary Sessions

Use UUIDs for ephemeral conversations:
import { randomUUID } from 'crypto'

const sessionId = randomUUID()
const result = await agent.run({
  input: userMessage,
  sessionId,
})
If you don’t provide a sessionId, AgentLIB generates a random UUID automatically.

Multi-User Web Application

Here’s a complete example of session management in an Express API:
import express from 'express'
import { createAgent } from '@agentlib/core'
import { openai } from '@agentlib/openai'
import { BufferMemory } from '@agentlib/memory'

const app = express()
app.use(express.json())

// Create a single agent instance (reused across requests)
const memory = new BufferMemory({ maxMessages: 20 })

const agent = createAgent({
  name: 'customer-support',
  systemPrompt: 'You are a helpful customer support assistant.',
})
  .provider(openai({
    apiKey: process.env.OPENAI_API_KEY,
    model: 'gpt-4o',
  }))
  .memory(memory)

// Chat endpoint
app.post('/api/chat', async (req, res) => {
  try {
    const { userId, message } = req.body
    
    if (!userId || !message) {
      return res.status(400).json({ error: 'Missing userId or message' })
    }
    
    // Use userId as sessionId for user-specific conversations
    const result = await agent.run({
      input: message,
      sessionId: `user-${userId}`,
    })
    
    res.json({
      response: result.output,
      tokens: result.state.usage?.totalTokens,
      steps: result.state.steps.length,
    })
  } catch (error) {
    console.error('Chat error:', error)
    res.status(500).json({ error: 'Internal server error' })
  }
})

// Get conversation history
app.get('/api/history/:userId', async (req, res) => {
  try {
    const { userId } = req.params
    const sessionId = `user-${userId}`
    
    const entries = await memory.entries(sessionId)
    
    res.json({
      sessionId,
      messages: entries[0]?.messages || [],
    })
  } catch (error) {
    console.error('History error:', error)
    res.status(500).json({ error: 'Internal server error' })
  }
})

// Clear conversation
app.delete('/api/history/:userId', async (req, res) => {
  try {
    const { userId } = req.params
    const sessionId = `user-${userId}`
    
    await memory.clear(sessionId)
    
    res.json({ success: true })
  } catch (error) {
    console.error('Clear error:', error)
    res.status(500).json({ error: 'Internal server error' })
  }
})

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000')
})

Per-Session Agent Data

Pass session-specific data to customize agent behavior:
interface SessionData {
  userId: string
  userName: string
  plan: 'free' | 'pro'
  preferences: Record<string, any>
}

const agent = createAgent<SessionData>({
  name: 'personalized-agent',
  data: {
    userId: '',
    userName: '',
    plan: 'free',
    preferences: {},
  },
})
  .provider(model)

// Different data per session
await agent.run({
  input: 'Hello',
  sessionId: 'user-alice',
  data: {
    userId: 'alice-123',
    userName: 'Alice',
    plan: 'pro',
    preferences: { theme: 'dark' },
  },
})

await agent.run({
  input: 'Hello',
  sessionId: 'user-bob',
  data: {
    userId: 'bob-456',
    userName: 'Bob',
    plan: 'free',
    preferences: { theme: 'light' },
  },
})

Session Isolation in Tools

Tools can access session-specific data from the execution context:
import { defineTool } from '@agentlib/core'

interface UserData {
  userId: string
  apiKey: string
}

const databaseTool = defineTool({
  schema: {
    name: 'query_database',
    description: 'Query the user database',
    parameters: {
      type: 'object',
      properties: {
        query: { type: 'string' },
      },
      required: ['query'],
    },
  },
  async execute({ query }, ctx) {
    // Access user-specific credentials
    const { userId, apiKey } = ctx.data
    
    console.log(`User ${userId} querying database`)
    
    // Execute query with user credentials
    const results = await db.query(query, { userId, apiKey })
    return results
  },
})

const agent = createAgent<UserData>({
  name: 'db-agent',
  data: { userId: '', apiKey: '' },
})
  .provider(model)
  .tool(databaseTool)

// Different users get different data
await agent.run({
  input: 'Show my orders',
  sessionId: 'user-alice',
  data: { userId: 'alice', apiKey: 'key-alice' },
})

await agent.run({
  input: 'Show my orders',
  sessionId: 'user-bob',
  data: { userId: 'bob', apiKey: 'key-bob' },
})

Session Cleanup

Implement session cleanup for inactive users:
import { BufferMemory } from '@agentlib/memory'

const memory = new BufferMemory({ maxMessages: 10 })

// Track last activity per session
const lastActivity = new Map<string, number>()

const agent = createAgent({ name: 'agent' })
  .provider(model)
  .memory(memory)

agent.on('run:start', ({ sessionId }) => {
  lastActivity.set(sessionId, Date.now())
})

// Periodic cleanup (every hour)
setInterval(async () => {
  const now = Date.now()
  const maxAge = 24 * 60 * 60 * 1000  // 24 hours
  
  for (const [sessionId, timestamp] of lastActivity.entries()) {
    if (now - timestamp > maxAge) {
      console.log(`Cleaning up inactive session: ${sessionId}`)
      await memory.clear(sessionId)
      lastActivity.delete(sessionId)
    }
  }
}, 60 * 60 * 1000)  // Every hour

Conversation Branching

Create branches from existing conversations:
import { BufferMemory } from '@agentlib/memory'

const memory = new BufferMemory({ maxMessages: 20 })

const agent = createAgent({ name: 'agent' })
  .provider(model)
  .memory(memory)

// Main conversation
await agent.run({
  input: 'Tell me about TypeScript',
  sessionId: 'main-conversation',
})

// Get existing history
const entries = await memory.entries('main-conversation')
const history = entries[0]?.messages || []

// Create a branch with copied history
const branchSessionId = 'branch-conversation'
if (history.length > 0) {
  await memory.write(history, {
    sessionId: branchSessionId,
  })
}

// Continue in the branch
await agent.run({
  input: 'What about type inference?',
  sessionId: branchSessionId,
})

Session Analytics

Track session metrics:
const sessionMetrics = new Map<string, {
  messageCount: number
  totalTokens: number
  lastActive: Date
}>()

agent.on('run:end', ({ state }) => {
  const sessionId = state.sessionId
  const metrics = sessionMetrics.get(sessionId) || {
    messageCount: 0,
    totalTokens: 0,
    lastActive: new Date(),
  }
  
  metrics.messageCount += 1
  metrics.totalTokens += state.usage?.totalTokens || 0
  metrics.lastActive = new Date()
  
  sessionMetrics.set(sessionId, metrics)
})

// Query metrics
function getSessionMetrics(sessionId: string) {
  return sessionMetrics.get(sessionId) || null
}

const metrics = getSessionMetrics('user-alice')
console.log(`Alice: ${metrics?.messageCount} messages, ${metrics?.totalTokens} tokens`)

Next Steps

Build docs developers (and LLMs) love