Overview
The endSession function ends the active session, marking it as complete with a success status and optional reason.
Syntax
await lai.endSession({
  task?: string,
  sessionEval?: number,
  sessionEvalReason?: string,
  isSuccessful?: boolean,
  isSuccessfulReason?: string,
  tags?: string[],
}): Promise<void>
 
Parameters
Whether the session completed successfully.
 
Explanation of why the session succeeded or failed.
 
Numeric evaluation score for the session.
 
Reason for the evaluation score.
 
Returns
Returns a Promise that resolves to void.
Examples
Basic Usage
// End successfully with default
await lai.endSession({ isSuccessful: true });
// End successfully with reason
await lai.endSession({ isSuccessful: true, isSuccessfulReason: "All tasks completed" });
// End with failure
await lai.endSession({ isSuccessful: false, isSuccessfulReason: "API rate limit exceeded" });
 
With Error Handling
async function runWorkflow() {
  try {
    await lai.init({ sessionName: "Data processing" });
    
    await processData();
    await generateReport();
    
    // Success case
    await lai.endSession({ isSuccessful: true, isSuccessfulReason: "Workflow completed successfully" });
    
  } catch (error) {
    // Failure case
    await lai.endSession({ isSuccessful: false, isSuccessfulReason: `Workflow failed: ${error.message}` });
    throw error;
  }
}
 
Conditional Success
async function batchProcessor(items: any[]) {
  await lai.init({ sessionName: "Batch processing" });
  
  const results = await processItems(items);
  
  const successCount = results.filter(r => r.success).length;
  const successRate = successCount / results.length;
  
  if (successRate === 1) {
    await lai.endSession({ isSuccessful: true, isSuccessfulReason: "All items processed successfully" });
  } else if (successRate > 0.8) {
    await lai.endSession({ isSuccessful: true, isSuccessfulReason: `Partial success: ${successCount}/${results.length} items processed` });
  } else {
    await lai.endSession({ isSuccessful: false, isSuccessfulReason: `Too many failures: only ${successCount}/${results.length} succeeded` });
  }
}
 
With Cleanup
async function robustWorkflow() {
  let session;
  
  try {
    session = await lai.init({ sessionName: "Critical workflow" });
    
    // Your workflow
    await performCriticalOperations();
    
    await lai.endSession({ isSuccessful: true, isSuccessfulReason: "Operations completed" });
    
  } catch (error) {
    // Ensure session ends even on error
    if (session) {
      await lai.endSession({ isSuccessful: false, isSuccessfulReason: error.message });
    }
    throw error;
    
  } finally {
    // Additional cleanup
    await cleanup();
  }
}
 
Auto-End Behavior
When autoEnd is enabled (default), sessions automatically end on:
- Process exit
 
- Uncaught exceptions
 
- SIGINT/SIGTERM signals
 
// Auto-end enabled by default (configurable via autoEnd)
await lai.init({ sessionName: "My session" });
// Session will auto-end on exit; you may still call endSession() explicitly when appropriate
 
To disable auto-end:
await lai.init({ sessionName: "Manual session", autoEnd: false }); // Must manually call endSession()
 
Common Patterns
1. Success Criteria
async function taskWithCriteria() {
  await lai.init({ sessionName: "Goal-based task" });
  
  const goals = {
    accuracy: 0.95,
    performance: 1000, // ms
    errorRate: 0.01
  };
  
  const results = await runTask();
  
  const success = 
    results.accuracy >= goals.accuracy &&
    results.performanceMs <= goals.performance &&
    results.errorRate <= goals.errorRate;
    
  await lai.endSession(
    success,
    success 
      ? "All goals met"
      : `Failed criteria: accuracy=${results.accuracy}, performance=${results.performanceMs}ms`
  );
}
 
2. Multi-Phase Workflows
const phases = ['extract', 'transform', 'load'];
let completedPhases = [];
try {
  await lai.init({ sessionName: "ETL Pipeline" });
  
  for (const phase of phases) {
    await executePhase(phase);
    completedPhases.push(phase);
  }
  
  await lai.endSession(true, "All phases completed");
  
} catch (error) {
  await lai.endSession(
    false, 
    `Failed at ${phases[completedPhases.length]}: ${error.message}`
  );
}
 
3. Timeout Handling
async function timedOperation() {
  await lai.init({ sessionName: "Time-sensitive task" });
  
  const timeout = setTimeout(async () => {
    await lai.endSession({ isSuccessful: false, isSuccessfulReason: "Operation timed out after 5 minutes" });
    process.exit(1);
  }, 5 * 60 * 1000);
  
  try {
    await performOperation();
    clearTimeout(timeout);
    await lai.endSession({ isSuccessful: true, isSuccessfulReason: "Completed within time limit" });
  } catch (error) {
    clearTimeout(timeout);
    await lai.endSession(false, error.message);
  }
}
 
Best Practices
1. Always End Sessions
// Use try-finally to ensure ending
try {
  await lai.init({ sessionName: "Important task" });
  await doWork();
} finally {
  await lai.endSession();
}
 
2. Meaningful Reasons
// ✅ Good - specific and actionable
await lai.endSession({ isSuccessful: false, isSuccessfulReason: "Database connection failed after 3 retries: timeout" });
// ❌ Less helpful
await lai.endSession(false, "Error occurred");
 
3. Success Doesn’t Mean Perfect
// Partial success is still success
const processed = 95;
const total = 100;
await lai.endSession({
  isSuccessful: true,
  isSuccessfulReason: `Processed ${processed}/${total} items, ${total - processed} skipped due to validation`
});
 
Notes
- Only the active session can be ended
 
- Steps are automatically ended when session ends
 
- After ending, a new session can be started
 
- Telemetry spans are flushed on exit; provider shutdown is handled automatically
 
See Also