Skip to content

fix(tools): raise clear TypeError when on_invoke_tool gets non-ToolContext#3685

Open
wustwyh wants to merge 1 commit into
openai:mainfrom
wustwyh:fix/on-invoke-tool-clear-error
Open

fix(tools): raise clear TypeError when on_invoke_tool gets non-ToolContext#3685
wustwyh wants to merge 1 commit into
openai:mainfrom
wustwyh:fix/on-invoke-tool-clear-error

Conversation

@wustwyh

@wustwyh wustwyh commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #3681.

Calling a @function_tool's on_invoke_tool(ctx, input_json) with a ctx that is not a run context (most commonly None when unit-testing a tool directly) currently fails far from the cause with a cryptic chained AttributeError:

AttributeError: 'NoneType' object has no attribute 'tool_name'

The wrapper's failure handler then dereferences the same bad ctx again (context.run_config), masking the original cause behind a second exception.

What changed

Validate the context once, at the top of _FailureHandlingFunctionToolInvoker.__call__ (the public on_invoke_tool entry point), before the try block. The check accepts RunContextWrapper (which covers both ToolContext and the base wrapper used by agent.as_tool()), and raises a precise TypeError for anything else.

The happy path is untouched (one isinstance check), and the error now propagates cleanly instead of being routed through the failure formatter.

Tests

Added tests/test_function_tool.py::test_on_invoke_tool_rejects_non_tool_context, which asserts:

  • None raises the clear TypeError.
  • Another non-context type raises the clear TypeError.
  • A valid ToolContext still works and returns the expected result.

Notes

  • The guard accepts RunContextWrapper rather than strictly ToolContext, because the same wrapper is used by agent.as_tool(), whose invoker legitimately runs with a base RunContextWrapper. Requiring ToolContext would break that path.
  • No documentation changes: valid usage is unchanged, and the new error message is self-documenting.

…ntext

Calling a @function_tool's on_invoke_tool(ctx, ...) with a ctx that is
not a RunContextWrapper (e.g. None when unit-testing) currently fails
with a chained AttributeError that masks the real mistake. The wrapper's
failure handler dereferences the bad ctx again, producing a confusing
stack trace.

Validate ctx at the top of _FailureHandlingFunctionToolInvoker.__call__
before the try block. The happy path is untouched, and the error now
propagates cleanly with an actionable message.

Fixes openai#3681.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 36c4c74730

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/tool.py
return bound_invoker

async def __call__(self, ctx: ToolContext[Any], input: str) -> Any:
if not isinstance(ctx, RunContextWrapper):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Require ToolContext for non-agent function tools

For a regular @function_tool, passing a plain RunContextWrapper is still a non-ToolContext direct invocation, but this guard treats it as valid; _on_invoke_tool_impl then immediately reads ctx.tool_name and the handled-error path can read ctx.run_config, so callers still get the same confusing/masked AttributeError instead of the clear TypeError. If base wrappers are only needed for agent.as_tool(), gate that exception on the bound FunctionTool; otherwise require ToolContext here.

Useful? React with 👍 / 👎.

@seratch seratch added the duplicate This issue or pull request already exists label Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

duplicate This issue or pull request already exists

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants