Skip to content

Conversation

@aasullivan
Copy link
Contributor

Fix: Emit agent_tool_end Event When Function Tools Throw Errors

Summary

Fixes inconsistent event emission for function tools by ensuring agent_tool_end is always emitted, even when tool execution throws an error. This brings function tools in line with shell, computer, and apply patch tools, which already emit end events on errors.

Problem

When a function tool throws an error, the agent_tool_end event was never emitted, breaking the expected event lifecycle where every agent_tool_start should be paired with an agent_tool_end. This inconsistency created problems for:

  • Event sourcing systems tracking tool executions
  • Monitoring systems measuring tool completion rates
  • Debugging tools tracking execution time
  • Any code expecting paired start/end events

Changes

Code Change

File: packages/agents-core/src/runImplementation.ts:1361-1370

Added agent_tool_end emission in the error catch block before re-throwing:

catch (error) {
  span.setError({
    message: 'Error running tool',
    data: {
      tool_name: toolRun.tool.name,
      error: String(error),
    },
  });

  // Emit agent_tool_end even on error to maintain consistent event lifecycle
  const errorResult = String(error);
  runner.emit('agent_tool_end', state._context, agent, toolRun.tool, errorResult, {
    toolCall: toolRun.toolCall,
  });
  agent.emit('agent_tool_end', state._context, toolRun.tool, errorResult, {
    toolCall: toolRun.toolCall,
  });

  throw error;
}

Test Added

File: packages/agents-core/test/runImplementation.test.ts:1774-1819

Added test case emits agent_tool_end even when function tool throws error that:

  • Creates a tool that throws an error
  • Disables the default error handler to expose raw error propagation
  • Verifies both agent_tool_start and agent_tool_end are emitted
  • Confirms the error is still thrown (backward compatibility)

Why This is Correct

  1. Consistency: Matches behavior of shell, computer, and apply patch tools
  2. Event Lifecycle: Maintains the expected start/end pairing for all events
  3. Backward Compatible: Still re-throws the error, so existing error handling is unchanged
  4. Error Information: Error message is available as a string in the result parameter
  5. Non-Breaking: Adds events that were missing; doesn't change any existing events

Testing

New Test

  • emits agent_tool_end even when function tool throws error - Passes

Regression Testing

  • ✅ All 89 tests in runImplementation.test.ts - Pass
  • ✅ All 411 tests in agents-core package - Pass

Test Output

Test Files  1 passed (1)
     Tests  89 passed (89)

Comparison: Before and After

Before (Broken)

agent_tool_start emitted  
tool throws error         💥
agent_tool_end emitted     NEVER
error propagated          

After (Fixed)

agent_tool_start emitted  
tool throws error         💥
agent_tool_end emitted     WITH ERROR CONTEXT
error propagated          

Event Data Format

When a tool throws an error, the agent_tool_end event is emitted with:

  • result parameter: String representation of the error (e.g., "Error: Tool execution failed")
  • details parameter: { toolCall: protocol.FunctionCallItem } (same as success case)

Listeners can distinguish error cases by checking if the result string contains error information or by catching the error that is re-thrown after the event emission.

Backward Compatibility

Fully backward compatible

  • Errors are still thrown and propagated exactly as before
  • No changes to success path event emission
  • Only adds missing events that should have been emitted
  • Existing event listeners will receive additional (previously missing) events

Impact

Systems that rely on event lifecycle consistency (event sourcing, monitoring, debugging tools) will now receive complete event streams for function tools, matching the behavior of other tool types.

Closes #753

Function tools were not emitting agent_tool_end when errors
occurred,
breaking the expected event lifecycle where every agent_tool_start
should be paired with an agent_tool_end.

This change makes function tools consistent with shell, computer,
and
apply patch tools, which all emit agent_tool_end even on errors.

The error is still re-thrown after emitting the event, maintaining
full backward compatibility.

Fixes event sourcing systems, monitoring, and any code that depends
on paired start/end events.

Closes openai#753
@changeset-bot
Copy link

changeset-bot bot commented Dec 10, 2025

🦋 Changeset detected

Latest commit: 683b676

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@openai/agents-core Patch
@openai/agents-extensions Patch
@openai/agents-openai Patch
@openai/agents-realtime Patch
@openai/agents Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@seratch seratch changed the title fix: emit agent_tool_end event when function tools throw errors (Closes #753) fix: #753 Emit agent_tool_end event when function tools throw errors Dec 10, 2025
@seratch seratch added this to the 0.3.x milestone Dec 10, 2025
@seratch seratch merged commit dccc9b3 into openai:main Dec 10, 2025
5 checks passed
@aasullivan
Copy link
Contributor Author

Fastest PR merge I've ever seen, thanks @seratch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

agent_tool_end event not emitted when function tool throws error

2 participants