import { z } from 'zod'; import readline from 'node:readline/promises'; import { Agent, run, tool } from '@openai/agents'; // Prompt user for yes/no confirmation async function confirm(question: string): Promise { const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const answer = await rl.question(`${question} (y/n): `); rl.close(); return ['y', 'yes'].includes(answer.trim().toLowerCase()); } async function main() { // Define a tool that requires approval for certain inputs const getWeatherTool = tool({ name: 'get_weather', description: 'Get the weather for a given city', parameters: z.object({ city: z.string() }), needsApproval: async (_ctx, { city }) => { // forces approval to look up the weather in San Francisco return city === 'San Francisco'; }, async execute({ city }) { return `The weather in ${city} is sunny.`; }, }); const weatherAgent = new Agent({ name: 'Weather agent', instructions: 'You provide weather information.', handoffDescription: 'Handles weather-related queries', tools: [getWeatherTool], }); const mainAgent = new Agent({ name: 'Main agent', instructions: 'You are a general assistant.', handoffs: [weatherAgent], }); let stream = await run( mainAgent, 'What is the weather in San Francisco and Oakland?', { stream: true }, ); stream.toTextStream({ compatibleWithNodeStreams: true }).pipe(process.stdout); await stream.completed; while (stream.interruptions?.length) { console.log( 'Human-in-the-loop: approval required for the following tool calls:', ); const state = stream.state; for (const interruption of stream.interruptions) { const ok = await confirm( `Agent ${interruption.agent.name} would like to use the tool ${interruption.rawItem.name} with "${interruption.rawItem.arguments}". Do you approve?`, ); if (ok) { state.approve(interruption); } else { state.reject(interruption); } } // Resume execution with streaming output stream = await run(mainAgent, state, { stream: true }); const textStream = stream.toTextStream({ compatibleWithNodeStreams: true }); textStream.pipe(process.stdout); await stream.completed; } console.log('\n\nDone'); } main().catch(console.error);