import { z } from 'zod'; import readline from 'node:readline/promises'; import fs from 'node:fs/promises'; import { Agent, run, tool, RunState, RunResult } from '@openai/agents'; const getWeatherTool = tool({ name: 'get_weather', description: 'Get the weather for a given city', parameters: z.object({ location: z.string(), }), needsApproval: async (_context, { location }) => { // forces approval to look up the weather in San Francisco return location === 'San Francisco'; }, execute: async ({ location }) => { return `The weather in ${location} is sunny`; }, }); const dataAgentTwo = new Agent({ name: 'Data agent', instructions: 'You are a data agent', handoffDescription: 'You know everything about the weather', tools: [getWeatherTool], }); const agent = new Agent({ name: 'Basic test agent', instructions: 'You are a basic agent', handoffs: [dataAgentTwo], }); async function confirm(question: string) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const answer = await rl.question(`${question} (y/n): `); const normalizedAnswer = answer.toLowerCase(); rl.close(); return normalizedAnswer === 'y' || normalizedAnswer === 'yes'; } async function main() { let result: RunResult> = await run( agent, 'What is the weather in Oakland and San Francisco?', ); let hasInterruptions = result.interruptions?.length > 0; while (hasInterruptions) { // storing await fs.writeFile( 'result.json', JSON.stringify(result.state, null, 2), 'utf-8', ); // from here on you could run things on a different thread/process // reading later on const storedState = await fs.readFile('result.json', 'utf-8'); const state = await RunState.fromString(agent, storedState); for (const interruption of result.interruptions) { const confirmed = await confirm( `Agent ${interruption.agent.name} would like to use the tool ${interruption.rawItem.name} with "${interruption.rawItem.arguments}". Do you approve?`, ); if (confirmed) { state.approve(interruption); } else { state.reject(interruption); } } // resume execution of the current state result = await run(agent, state); hasInterruptions = result.interruptions?.length > 0; } console.log(result.finalOutput); } main().catch((error) => { console.dir(error, { depth: null }); });