145 lines
4.3 KiB
TypeScript
145 lines
4.3 KiB
TypeScript
/**
|
|
* Comprehensive error handling patterns for OpenAI Agents SDK
|
|
*
|
|
* Covers all major error types:
|
|
* - MaxTurnsExceededError: Agent hit maximum turns limit
|
|
* - InputGuardrailTripwireTriggered: Input blocked by guardrail
|
|
* - OutputGuardrailTripwireTriggered: Output blocked by guardrail
|
|
* - ToolCallError: Tool execution failed
|
|
* - ModelBehaviorError: Unexpected model behavior
|
|
* - GuardrailExecutionError: Guardrail itself failed
|
|
*/
|
|
|
|
import {
|
|
Agent,
|
|
run,
|
|
MaxTurnsExceededError,
|
|
InputGuardrailTripwireTriggered,
|
|
OutputGuardrailTripwireTriggered,
|
|
ModelBehaviorError,
|
|
ToolCallError,
|
|
GuardrailExecutionError,
|
|
} from '@openai/agents';
|
|
|
|
/**
|
|
* Run agent with comprehensive error handling and retry logic
|
|
*/
|
|
export async function runAgentWithErrorHandling(
|
|
agent: Agent,
|
|
input: string,
|
|
options: {
|
|
maxRetries?: number;
|
|
maxTurns?: number;
|
|
onError?: (error: Error, attempt: number) => void;
|
|
} = {}
|
|
) {
|
|
const { maxRetries = 3, maxTurns = 10, onError } = options;
|
|
|
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
try {
|
|
const result = await run(agent, input, { maxTurns });
|
|
return result;
|
|
|
|
} catch (error) {
|
|
// Notify error callback
|
|
if (onError) {
|
|
onError(error as Error, attempt);
|
|
}
|
|
|
|
// Handle specific error types
|
|
if (error instanceof MaxTurnsExceededError) {
|
|
console.error('❌ Agent exceeded maximum turns');
|
|
console.error(` Agent entered an infinite loop after ${maxTurns} turns`);
|
|
throw error; // Don't retry - this is a logic issue
|
|
|
|
} else if (error instanceof InputGuardrailTripwireTriggered) {
|
|
console.error('❌ Input blocked by guardrail');
|
|
console.error(' Reason:', error.outputInfo);
|
|
throw error; // Don't retry - input is invalid
|
|
|
|
} else if (error instanceof OutputGuardrailTripwireTriggered) {
|
|
console.error('❌ Output blocked by guardrail');
|
|
console.error(' Reason:', error.outputInfo);
|
|
throw error; // Don't retry - output violates policy
|
|
|
|
} else if (error instanceof ToolCallError) {
|
|
console.error(`⚠️ Tool call failed (attempt ${attempt}/${maxRetries})`);
|
|
console.error(' Tool:', error.toolName);
|
|
console.error(' Error:', error.message);
|
|
|
|
if (attempt === maxRetries) {
|
|
throw error; // Give up after max retries
|
|
}
|
|
|
|
// Exponential backoff
|
|
const delay = 1000 * Math.pow(2, attempt - 1);
|
|
console.log(` Retrying in ${delay}ms...`);
|
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
|
|
} else if (error instanceof ModelBehaviorError) {
|
|
console.error('❌ Unexpected model behavior');
|
|
console.error(' Details:', error.message);
|
|
throw error; // Don't retry - model is behaving incorrectly
|
|
|
|
} else if (error instanceof GuardrailExecutionError) {
|
|
console.error('❌ Guardrail execution failed');
|
|
console.error(' Guardrail:', error.guardrailName);
|
|
console.error(' Error:', error.message);
|
|
|
|
// Option to retry with fallback guardrail
|
|
// See common-errors.md for fallback pattern
|
|
throw error;
|
|
|
|
} else {
|
|
// Unknown error - retry with exponential backoff
|
|
console.error(`⚠️ Unknown error (attempt ${attempt}/${maxRetries})`);
|
|
console.error(' Error:', error);
|
|
|
|
if (attempt === maxRetries) {
|
|
throw error;
|
|
}
|
|
|
|
const delay = 1000 * Math.pow(2, attempt - 1);
|
|
console.log(` Retrying in ${delay}ms...`);
|
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
}
|
|
}
|
|
}
|
|
|
|
throw new Error('Max retries exceeded');
|
|
}
|
|
|
|
/**
|
|
* Example usage
|
|
*/
|
|
export async function exampleUsage() {
|
|
const agent = new Agent({
|
|
name: 'Assistant',
|
|
instructions: 'You are a helpful assistant.',
|
|
});
|
|
|
|
try {
|
|
const result = await runAgentWithErrorHandling(
|
|
agent,
|
|
'What is 2+2?',
|
|
{
|
|
maxRetries: 3,
|
|
maxTurns: 10,
|
|
onError: (error, attempt) => {
|
|
console.log(`Error on attempt ${attempt}:`, error.message);
|
|
},
|
|
}
|
|
);
|
|
|
|
console.log('✅ Success:', result.finalOutput);
|
|
console.log('Tokens used:', result.usage.totalTokens);
|
|
|
|
} catch (error) {
|
|
console.error('❌ Final error:', error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// Uncomment to run example
|
|
// exampleUsage();
|