Skip to content

feat: select errors that will be caught when raised within a tool#5488

Open
wistuba wants to merge 3 commits intomicrosoft:mainfrom
wistuba:main
Open

feat: select errors that will be caught when raised within a tool#5488
wistuba wants to merge 3 commits intomicrosoft:mainfrom
wistuba:main

Conversation

@wistuba
Copy link
Copy Markdown
Contributor

@wistuba wistuba commented Feb 11, 2025

Conversation starter to agree on the implementation. When we are aligned, I'll add tests.

Why are these changes needed?

Not every tool error should be returned to the agent. This change allows to cherry-pick which exceptions we want to share with the agent.

Related issue number

Closes: #5274

Checks

def schema(self) -> ToolSchema: ...

@property
def return_errors(self) -> tuple[type[Exception], ...] | type[Exception]: ...
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's rename it return_error_types? This makes it align with the return_type property that already exists.

Let's also add API doc comment to each field of Tool and BaseTool as a good Samaritan 😄

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's also add API doc comment to each field of Tool and BaseTool as a good Samaritan

Not sure what you mean by this. Do you want me to add docstrings to every function in Tool/BaseTool?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I was asking if you would be willing to add the docstrings.

@wistuba
Copy link
Copy Markdown
Contributor Author

wistuba commented Feb 12, 2025

I think there was some confusion on the Issue regarding what this feature should do. Do we want to keep adding the error types to the Tool or is there now a preference to add it to the agent? Former has the advantage that you can deal differently with each tool, latter allows you to only define it once and it is applied automatically for every tool.

@ekzhu
Copy link
Copy Markdown
Contributor

ekzhu commented Feb 12, 2025

So sorry I am going back-and-forth here.

My initial thought for #5274 is that we want to configure how FunctionTool behaves when it comes to what error to catch and return the error message as the result, and what errors to raise up the stack. So that the actual function passed in does not need to implement special handling for errors. For example, a function that raises an HTTP 401 error, the FunctionTool that wraps it can return back to the caller a string result rather than raising the error up the stack, without changing the implementation of the underlying function that performs the HTTP call.

However, I think there could be some issues:

  1. The common usage case of BaseTool is not to execute the tool directly but through an agent. So we need to make BaseTool works well with FunctionExecutionResult, which has is_error field to indicate error. If the BaseTool returns a string, there is no way to know whether is_error field should be set. So we still need a way to indicate whether an error has occurred or not.
  2. The added return_error_types field addresses the problem but doesn't solve it cleanly, because we now still need to catch the error and see if it is part of the return_error_types and then make a decision on whether to return the message or raise. It feels strange, because the class that is responsible for using the property is not the owner of the property.

So I am more inclined to configure how the errors raised from BaseTool is managed through the caller of BaseTool. So in this case it should be the agent's responsibility to manage it.

So, we need to update AssistantAgent class regarding to how tool errors are handled.

However, I do think we need to wait for a bit because it is an important API change, and overlaps with concepts discussed in #4721. Let's wait on this PR and consider multiple ideas together.

@ekzhu ekzhu added the workbench Issues related to workbench of tools label Feb 12, 2025
@wistuba
Copy link
Copy Markdown
Contributor Author

wistuba commented Feb 13, 2025

My proposal is to pass the return_error_types to the AssistantAgent. Then the AssistantAgent calls the tools and catches all return_error_types. I don't see why this change will impact the PR you've mentioned. In any case, let me know how to progress on this.

@ekzhu
Copy link
Copy Markdown
Contributor

ekzhu commented Feb 13, 2025

In any case, let me know how to progress on this.

Let's pause this for now. There are a number of things related to tool calls such as #5510 #4721 and this one. I think we need to design this a bit. Would you like to join our discord for more interactive discussion?

@nidhishgajjar
Copy link
Copy Markdown

Orb Code Review (powered by GLM 5.1 on Orb Cloud)

Summary

This PR adds the ability to specify which exception types should be caught and forwarded to the agent when a tool execution fails, rather than catching all Exception types indiscriminately. It introduces a return_error_types property on Tool, BaseTool, and FunctionTool, and refactors error handling in both _assistant_agent.py and _openai_assistant_agent.py.

Architecture

The design is clean and fits the existing codebase well. The return_error_types property is threaded through the Tool protocol → BaseToolFunctionTool hierarchy, and the agent-level _execute_tool_call methods use it as the exception filter. Moving "no tools available" and "tool not found" checks out of the try/except into early returns is a good structural improvement.

Issues

1. Tool Protocol — Breaking change (warning)

File: python/packages/autogen-core/src/autogen_core/tools/_base.py

The Tool protocol is @runtime_checkable and is a public API. Adding a new required property return_error_types will break any third-party classes that implement the Tool protocol but don't define this property. While @runtime_checkable only checks methods (not properties) at runtime, any code that relies on structural subtyping will fail static type checks.

Suggestion: Consider making this property optional by providing a default implementation or using a separate protocol (e.g., ToolWithErrorTypes(Tool)). Alternatively, document this as a breaking change.

2. Inconsistent error message prefix (warning)

File: python/packages/autogen-ext/src/autogen_ext/agents/openai/_openai_assistant_agent.py

In _assistant_agent.py, the "no tools" and "tool not found" errors are prefixed with "Error: " via error_prefix_string. In _openai_assistant_agent.py, the same error messages lack this prefix:

# _openai_assistant_agent.py
return FunctionExecutionResult(content="No tools are available.", call_id=tool_call.id, is_error=True)

vs.

# _assistant_agent.py
return FunctionExecutionResult(content=f"{error_prefix_string}No tools are available.", call_id=tool_call.id, is_error=True)

Fix: Use the same "Error: " prefix in _openai_assistant_agent.py for consistency.

3. No tests (warning)

The PR description explicitly states tests will be added later. This is a significant behavioral change affecting error handling across multiple components. Tests should cover:

  • Default behavior (catching all Exception)
  • Selective catching with specific error types
  • Uncaught exceptions propagating up
  • Both agent implementations (_assistant_agent and _openai_assistant_agent)

4. Repeated type annotation (suggestion)

File: python/packages/autogen-core/src/autogen_core/tools/_base.py, _function_tool.py

Tuple[Type[Exception], ...] | Type[Exception] is repeated 5+ times. Consider a type alias:

ErrorTypes = Tuple[Type[Exception], ...] | Type[Exception]

5. BaseTool.__init__ parameter ordering (suggestion)

The new return_error_types parameter is added between description and strict. Consider placing it at the end of the parameter list to minimize disruption for callers using keyword arguments.

Cross-file impact

  • Any code that subclasses BaseTool directly (beyond FunctionTool) will need to pass return_error_types to super().__init__() if they want non-default behavior.
  • The Tool protocol change affects any third-party implementations.
  • The _openai_assistant_agent.py return type change from str to FunctionExecutionResult is an internal refactor with no external API impact.

Assessment

comment — This is a solid feature with a clean design, but it needs tests before merging and should address the backward compatibility concern with the Tool protocol. The error message inconsistency between the two agent implementations should also be fixed. Looking forward to seeing this with tests.

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

Labels

workbench Issues related to workbench of tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

To support configuring how errors are handled in tools.

3 participants