# Sessions Manage conversation state and multi-turn interactions URL: https://agentkit.tech/docs/sessions.mdx **Sessions** manage conversation state between you and agents, enabling multi-turn conversations with context and memory. They handle message history, agent handoffs, and conversation continuity. ## Quick Start ```go // Create a session for conversation state session := session.New(agent) // Have a multi-turn conversation response1, _ := session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("Hi, my name is Alice")}, nil) fmt.Println(response1.FinalOutput) // "Hello Alice! Nice to meet you." response2, _ := session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("What's my name?")}, nil) fmt.Println(response2.FinalOutput) // "Your name is Alice." ``` ## Basic Usage ### Single Agent Conversations Maintain context across multiple interactions: ```go // Create agent and session agent := agent.New(). SetModel(model). SetSystemPrompt("You are a helpful coding assistant.") session := session.New(agent) // First question response1, _ := session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("How do I create a slice in Go?")}, nil) // Follow-up question with context response2, _ := session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("Can you show me how to append to it?")}, nil) // Agent remembers we were talking about Go slices response3, _ := session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("What about removing elements?")}, nil) ``` ### Accessing Conversation History Retrieve and analyze conversation messages: ```go session := session.New(agent) // Have some conversations session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("Tell me about Go")}, nil) session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("What are its main features?")}, nil) // Get the conversation history messages := session.Messages() fmt.Printf("Conversation has %d messages\n", len(messages)) for _, msg := range messages { fmt.Printf("%s: %s\n", msg.Role, msg.Content) } ``` ## Agent Handoffs Transfer conversations between specialized agents while maintaining context: ```go // Create specialized agents codeReviewer := agent.New(). SetModel(model). SetSystemPrompt("You are a code reviewer. Analyze code for bugs and improvements.") tester := agent.New(). SetModel(model). SetSystemPrompt("You generate comprehensive unit tests for code.") documenter := agent.New(). SetModel(model). SetSystemPrompt("You create clear documentation for code.") // Start conversation with code reviewer session := session.New(codeReviewer) reviewResponse, _ := session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("Review this function: "+codeSnippet)}, nil) // Hand off to test generator (keeps conversation context) session.SetAgent(tester) testResponse, _ := session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("Generate tests based on the review feedback")}, nil) // Hand off to documenter (knows about code and tests) session.SetAgent(documenter) docResponse, _ := session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("Create documentation covering the reviewed code and tests")}, nil) ``` ## Session Configuration ### Custom Session Options Configure session behavior: ```go // Session with custom configuration session := session.New(agent). WithMaxMessages(100). // Limit conversation history WithSystemContext("Project: E-commerce API") // Add persistent context ``` ### Message Filtering Control which messages are kept in history: ```go // Create session with message filtering session := session.New(agent). WithMessageFilter(func(msg session.Message) bool { // Only keep user messages and final responses return msg.Role == "user" || (msg.Role == "assistant" && !msg.IsIntermediate) }) ``` ## Streaming with Sessions Handle real-time conversations with persistent state: ```go session := session.New(agent) // Stream first response stream1, _ := session.RunStreamed(ctx, []agent.ChatMessage{agent.NewUserMessage("Tell me a story about a robot")}, nil) for event, err := range stream1.StreamEvents() { if err != nil { log.Fatal(err) } if event.IsTextDelta() { fmt.Print(event.GetContent()) } } fmt.Println() // Stream follow-up (remembers the story context) stream2, _ := session.RunStreamed(ctx, []agent.ChatMessage{agent.NewUserMessage("What happens next in the story?")}, nil) for event, err := range stream2.StreamEvents() { if err != nil { log.Fatal(err) } if event.IsTextDelta() { fmt.Print(event.GetContent()) } } ``` ## Advanced Patterns ### Session Branching Create conversation branches for different scenarios: ```go // Main conversation mainSession := session.New(agent) mainSession.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("I'm building a web application")}, nil) // Branch for different technical approaches frontendBranch := mainSession.Branch() frontendBranch.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("Focus on React frontend architecture")}, nil) backendBranch := mainSession.Branch() backendBranch.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("Focus on Go backend architecture")}, nil) // Both branches remember the original context about building a web app ``` ### Session Persistence Save and restore conversation state: ```go // Save session state session := session.New(agent) session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("Help me plan a vacation to Japan")}, nil) sessionData, err := session.Export() if err != nil { log.Fatal(err) } // Store sessionData (JSON) to database/file err = saveToDatabase(sessionData) // Later: restore session sessionData, err = loadFromDatabase() if err != nil { log.Fatal(err) } restoredSession, err := session.Import(sessionData) if err != nil { log.Fatal(err) } // Continue conversation where you left off restoredSession.Run(ctx, []agent.ChatMessage{agent.NewUserMessage("What's the weather like in Tokyo in spring?")}, nil) ``` ### Multi-User Sessions Handle conversations for different users: ```go type ConversationManager struct { sessions map[string]*session.Session agent *agent.Agent } func NewConversationManager(agent *agent.Agent) *ConversationManager { return &ConversationManager{ sessions: make(map[string]*session.Session), agent: agent, } } func (cm *ConversationManager) HandleUserMessage(userID, message string) (string, error) { // Get or create session for user sess, exists := cm.sessions[userID] if !exists { sess = session.New(cm.agent) cm.sessions[userID] = sess } // Process message with user's conversation history response, err := sess.Run(ctx, []agent.ChatMessage{agent.NewUserMessage(message)}, nil) if err != nil { return "", err } return response.FinalOutput, nil } ``` ### Session Cleanup Manage memory usage for long-running applications: ```go type SessionManager struct { sessions map[string]*session.Session lastUsed map[string]time.Time } func (sm *SessionManager) CleanupOldSessions() { now := time.Now() for sessionID, lastUsed := range sm.lastUsed { // Remove sessions inactive for more than 1 hour if now.Sub(lastUsed) > time.Hour { delete(sm.sessions, sessionID) delete(sm.lastUsed, sessionID) } } } func (sm *SessionManager) GetSession(id string, agent *agent.Agent) *session.Session { sm.lastUsed[id] = time.Now() if sess, exists := sm.sessions[id]; exists { return sess } // Create new session sess := session.New(agent) sm.sessions[id] = sess return sess } ``` ## Best Practices ### Memory Management Control conversation length to manage costs and performance: ```go // Limit conversation history session := session.New(agent). WithMaxMessages(50) // Keep last 50 messages // Or use sliding window session := session.New(agent). WithSlidingWindow(20) // Keep last 20 exchanges ``` ### Context Preservation Keep important context while trimming history: ```go session := session.New(agent). WithContextPreservation(func(messages []session.Message) []session.Message { // Always keep system message and last 10 exchanges if len(messages) <= 21 { // 1 system + 20 user/assistant return messages } preserved := []session.Message{messages[0]} // Keep system message preserved = append(preserved, messages[len(messages)-20:]...) // Keep last 20 return preserved }) ``` ### Error Handling Handle session-related errors gracefully: ```go response, err := session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage(userMessage)}, nil) if err != nil { switch { case errors.Is(err, session.ErrMaxMessagesExceeded): // Handle conversation limit session.Reset() return "Conversation history cleared. Please repeat your question." case errors.Is(err, session.ErrInvalidState): // Handle corrupted session session = session.New(agent) return "Session reset due to error. How can I help you?" default: return fmt.Sprintf("Error: %v", err) } } ``` ### Performance Optimization Optimize for high-throughput scenarios: ```go // Use session pools for high concurrency type SessionPool struct { sessions chan *session.Session } func NewSessionPool(size int, agent *agent.Agent) *SessionPool { pool := &SessionPool{ sessions: make(chan *session.Session, size), } // Pre-populate pool for i := 0; i < size; i++ { pool.sessions <- session.New(agent) } return pool } func (sp *SessionPool) Get(agent *agent.Agent) *session.Session { select { case sess := <-sp.sessions: return sess default: // Pool empty, create new session return session.New(agent) } } func (sp *SessionPool) Put(sess *session.Session) { select { case sp.sessions <- sess: // Session returned to pool default: // Pool full, let session be garbage collected } } ``` ## Error Handling Common session errors and how to handle them: ```go response, err := session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage(message)}, nil) if err != nil { switch { case errors.Is(err, session.ErrContextTooLong): // Trim conversation history session.TrimToTokenLimit(4000) response, err = session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage(message)}, nil) case errors.Is(err, session.ErrInvalidMessage): // Handle malformed message log.Printf("Invalid message format: %v", err) case errors.Is(err, session.ErrSessionExpired): // Create new session session = session.New(agent) response, err = session.Run(ctx, []agent.ChatMessage{agent.NewUserMessage(message)}, nil) } } ``` ## Next Steps * [Agents](/agents) - Learn how to create agents that work with sessions * [Models](/models) - Configure models for optimal conversation performance * [Tools](/tools) - Add function calling to conversational agents * [Streaming](/streaming) - Implement real-time conversational interfaces