Skip to main content
Sessions represent active conversations between users and agents. They track events, manage state, and provide a foundation for all agent interactions in ADK-TS.

Session Lifecycle

BaseSessionService

All session services extend the abstract BaseSessionService class:
// packages/adk/src/sessions/base-session-service.ts:27
export abstract class BaseSessionService {
  abstract createSession(
    appName: string,
    userId: string,
    state?: Record<string, any>,
    sessionId?: string,
  ): Promise<Session>;
  
  abstract getSession(
    appName: string,
    userId: string,
    sessionId: string,
    config?: GetSessionConfig,
  ): Promise<Session | undefined>;
  
  abstract listSessions(
    appName: string,
    userId: string,
  ): Promise<ListSessionsResponse>;
  
  abstract deleteSession(
    appName: string,
    userId: string,
    sessionId: string,
  ): Promise<void>;
  
  abstract endSession(
    appName: string,
    userId: string,
    sessionId: string,
  ): Promise<Session | undefined>;
  
  async appendEvent(session: Session, event: Event): Promise<Event>;
}

Session Structure

A session contains all conversation data:
// packages/adk/src/sessions/session.ts:6
interface Session {
  id: string;                    // Unique session identifier
  appName: string;               // Application name
  userId: string;                // User identifier
  state: Record<string, any>;    // Session state variables
  events: Event[];               // All conversation events
  lastUpdateTime: number;        // Unix timestamp (seconds)
}

Creating Sessions

import { InMemorySessionService } from '@iqai/adk';

const sessionService = new InMemorySessionService();

const session = await sessionService.createSession(
  'my-app',      // App name
  'user-123',    // User ID
  {              // Initial state (optional)
    counter: 0,
    language: 'en',
  },
  'custom-id'    // Custom session ID (optional)
);

console.log('Session ID:', session.id);
console.log('Initial state:', session.state);

Session Services

Simple in-memory storage for development:
// packages/adk/src/sessions/in-memory-session-service.ts:14
import { InMemorySessionService } from '@iqai/adk';

const sessionService = new InMemorySessionService();

const agent = await AgentBuilder
  .withModel('gpt-4')
  .withSessionService(sessionService)
  .build();
Features:
  • Fast and lightweight
  • No external dependencies
  • Data lost on restart
  • Perfect for testing and development
Storage structure:
Map<appName, Map<userId, Map<sessionId, Session>>>
└─ app-level state: Map<appName, Map<key, value>>
└─ user-level state: Map<appName, Map<userId, Map<key, value>>>
All session data is lost when the process exits. Use for development only.

Managing Sessions

1

Create a Session

const session = await sessionService.createSession(
  'my-app',
  'user-123',
  { counter: 0 }
);
2

Append Events

const event = {
  id: 'evt-1',
  invocationId: 'inv-1',
  author: 'user',
  timestamp: Date.now() / 1000,
  content: { parts: [{ text: 'Hello' }] },
};

await sessionService.appendEvent(session, event);
3

Get Session

const retrieved = await sessionService.getSession(
  'my-app',
  'user-123',
  session.id,
  {
    numRecentEvents: 10,        // Only get last 10 events
    afterTimestamp: 1234567890, // Only events after timestamp
  }
);
4

List User Sessions

const { sessions } = await sessionService.listSessions(
  'my-app',
  'user-123'
);

for (const s of sessions) {
  console.log(`${s.id}: ${new Date(s.lastUpdateTime * 1000)}`);
}
5

End Session

// Get final state before cleanup
const finalSession = await sessionService.endSession(
  'my-app',
  'user-123',
  session.id
);

// Save to long-term memory if needed
await memoryService.addSessionToMemory(finalSession);
6

Delete Session

await sessionService.deleteSession(
  'my-app',
  'user-123',
  session.id
);

Event Structure

Events represent individual interactions:
interface Event {
  id: string;                     // Unique event ID
  invocationId: string;           // Groups related events
  author: string;                 // 'user' or 'model'
  branch?: string;                // For branching conversations
  timestamp: number;              // Unix seconds
  
  // Content (user input or model response)
  content?: Content;
  
  // Actions (tool calls, state changes)
  actions?: {
    stateDelta?: Record<string, any>;     // State changes
    functionCalls?: FunctionCall[];        // Tool invocations
    functionResponses?: FunctionResponse[]; // Tool results
    compaction?: CompactionData;           // Event summarization
  };
  
  // Metadata
  partial?: boolean;              // Streaming in progress
  turnComplete?: boolean;         // Response complete
  errorCode?: string;             // Error type
  errorMessage?: string;          // Error details
  interrupted?: boolean;          // User interrupted
  longRunningToolIds?: Set<string>; // Async tools in progress
  groundingMetadata?: any;        // RAG metadata
}

Session Rewind

Travel back in time by reverting to a previous state:
// apps/examples/src/04-persistence-and-sessions/index.ts:32
import { AgentBuilder } from '@iqai/adk';

// Make some changes
await runner.ask('Increment counter by 100');

// Get the invocation ID of the change
const invocationId = getLastInvocationIdWithStateDelta(session);

// Rewind to before that change
await runner.rewind({
  userId: 'user-123',
  sessionId: session.id,
  rewindBeforeInvocationId: invocationId,
});

// State is now as if the increment never happened
const rewoundSession = await sessionService.getSession(
  'my-app',
  'user-123',
  session.id
);

console.log('Rewound state:', rewoundSession.state);
Rewind removes all events and state changes that occurred at or after the specified invocation ID.

Finding Invocation IDs

// Get the last invocation that changed state
function getLastInvocationIdWithStateDelta(session: Session): string | undefined {
  for (let i = session.events.length - 1; i >= 0; i--) {
    const event = session.events[i];
    if (event.actions?.stateDelta && 
        Object.keys(event.actions.stateDelta).length > 0) {
      return event.invocationId;
    }
  }
  return undefined;
}

Events Compaction

Automatically summarize old events to save context window:
const { runner } = await AgentBuilder
  .withModel('gpt-4')
  .withSessionService(sessionService)
  .withEventsCompaction({
    compactionInterval: 5,  // Compact every 5 events
    overlapSize: 2,         // Keep 2 recent events uncompacted
  })
  .build();
How it works:
  1. After N events, old events are summarized
  2. Summary stored as a compaction event
  3. Original events can be removed
  4. Reduces context window usage
  5. Maintains conversation continuity

State Management Integration

Sessions automatically track state changes. See State Management for details:
// State changes are captured in events
const event = {
  id: 'evt-1',
  invocationId: 'inv-1',
  author: 'model',
  timestamp: Date.now() / 1000,
  actions: {
    stateDelta: {
      counter: 5,              // Session state
      'user:name': 'Alice',    // User state
      'app:version': '1.0',    // App state
    },
  },
};

await sessionService.appendEvent(session, event);

// State automatically updated
console.log(session.state.counter);        // 5
console.log(session.state['user:name']);  // 'Alice'

Best Practices

  • Create sessions at conversation start
  • Use consistent appName and userId
  • Call endSession() before saving to memory
  • Clean up old sessions periodically
  • Don’t reuse sessions across different contexts
  • Use numRecentEvents to limit event loading
  • Enable compaction for long conversations
  • Index frequently queried fields in database
  • Consider partitioning by appName or date
  • Use transactions for consistency
  • Use appropriate state scope (session/user/app)
  • Keep state minimal (only what you need)
  • Use temp: prefix for transient data
  • Validate state before use
  • Document your state schema
  • Check for stale sessions (lastUpdateTime)
  • Handle concurrent updates
  • Validate session exists before operations
  • Use rewind for error recovery
  • Log state changes for debugging

Complete Example

import {
  AgentBuilder,
  createDatabaseSessionService,
  InMemoryArtifactService,
} from '@iqai/adk';

// Setup
const sessionService = createDatabaseSessionService(
  'postgresql://localhost/mydb'
);

const artifactService = new InMemoryArtifactService();

// Create agent with session management
const { runner, session, sessionService: svc } = await AgentBuilder
  .withModel('gpt-4')
  .withInstruction('You are a helpful assistant with state.')
  .withSessionService(sessionService)
  .withArtifactService(artifactService)
  .withEventsCompaction({
    compactionInterval: 10,
    overlapSize: 2,
  })
  .build({
    userId: 'user-123',
  });

// Interact
await runner.ask('Set my name to Alice');
await runner.ask('What is my name?');

// List sessions
const { sessions } = await svc.listSessions('my-app', 'user-123');
console.log('User has', sessions.length, 'sessions');

// End and cleanup
const finalSession = await svc.endSession(
  session.appName,
  session.userId,
  session.id
);

// Optional: save to memory
if (memoryService) {
  await memoryService.addSessionToMemory(finalSession);
}

// Delete if no longer needed
await svc.deleteSession(session.appName, session.userId, session.id);

Build docs developers (and LLMs) love