/** * Example 02: Chat with Exits * * This example demonstrates how to use custom exits in chat mode. * It shows how to: * - Define custom exit conditions with and without output schemas * - Handle different exit types in the execution result * - Use type-safe exit checking with result.is() * - Implement escalation workflows with structured data * * Key concepts: * - Exit definitions with typed schemas * - Multiple exit conditions handling * - Automatic ListenExit for user interaction * - Type-safe result checking */ import { Client } from '@botpress/client' import { z } from '@bpinternal/zui' import { execute, Exit, ListenExit } from 'llmz' import { CLIChat } from '../utils/cli-chat' // Initialize Botpress client for LLM communication const client = new Client({ botId: process.env.BOTPRESS_BOT_ID!, token: process.env.BOTPRESS_TOKEN!, }) // Chat executions can terminate in multiple ways: // 1. ListenExit: Agent pauses to wait for user input (automatic in chat mode) // 2. Custom exits: User-defined conditions that end execution with specific outcomes // This example shows two custom exits for different termination scenarios const chat = new CLIChat() // Define a simple exit without output data // When this exit is triggered, the execution ends with no additional information const exit = new Exit({ name: 'exit', description: 'When the user wants to exit the program', }) // Define an exit with structured output schema // The LLM will generate data matching this schema when the exit is triggered // This enables type-safe data extraction from exit conditions const escalation = new Exit({ name: 'escalation', description: 'Escalate the issue to a human agent', schema: z.object({ reason: z.enum(['Frustrated user', 'Technical issue', 'Sensitive topic', 'Other']), }), }) // Main conversation loop with exit handling while (await chat.iterate()) { // Execute with custom exits defined const result = await execute({ instructions: 'You are a helpful assistant. Greet the user and suggest topics for discussion using buttons.', // Custom exits available to the agent // Note: ListenExit is automatically added when using chat mode exits: [exit, escalation], chat, client, }) // Type-safe exit checking using result.is() // This provides compile-time safety and runtime type narrowing if (result.is(exit)) { // Handle simple exit - no additional data console.log('-----------------------') console.log('👋 Goodbye!') console.log('-----------------------') process.exit(0) } if (result.is(escalation)) { // Handle escalation exit - access typed output data console.log('-----------------------') console.log(`🚨 Escalation needed: ${result.output.reason}`) console.log('-----------------------') process.exit(0) } if (result.is(ListenExit)) { // The agent has paused execution to wait for user input // Continue the loop to process the next user message // This is the normal flow for continuing conversations } }