Skip to content

feat: expose the wrapped callable on FunctionTool (closes #3381)#3692

Open
fede-kamel wants to merge 2 commits into
openai:mainfrom
fede-kamel:feat/function-tool-expose-callable
Open

feat: expose the wrapped callable on FunctionTool (closes #3381)#3692
fede-kamel wants to merge 2 commits into
openai:mainfrom
fede-kamel:feat/function-tool-expose-callable

Conversation

@fede-kamel

Copy link
Copy Markdown

Summary

Adds a public FunctionTool.function attribute that holds the original Python callable wrapped by @function_tool.

Today the wrapped function is only reachable by walking the closure of on_invoke_tool (...on_invoke_tool._invoke_tool_impl.__closure__), which is brittle and got an extra hop in 0.16 with the failure-handling indirection. This gives code outside the Agents runtime a stable hook to introspect, directly test, or re-run a tool's body without constructing a ToolContext and doing a JSON encode/decode cycle.

  • New field is None for tools not backed by a plain function (agent-as-tool, hosted-tool wrappers), so the attribute is always present and safe to check.
  • Added as a keyword-only dataclass field, so it does not change the positional constructor order of FunctionTool.
  • Documented via the field docstring (renders in the API reference).

This revives the approach from #2146 (which was closed only over an unrelated pytest fixture-collection regression, not the concept). Happy to rename to func or also wire __wrapped__ for inspect.unwrap() if preferred.

Test plan

  • New tests/test_function_tool_exposes_function.py: sync + async tools expose a runnable .function; directly-constructed tools expose None.
  • tests/test_function_tool.py (49 tests) still pass — no regression.
  • make format, make lint, make typecheck (mypy + pyright) clean.

Issue number

Closes #3381

Checks

  • I've added new tests (if relevant)
  • I've added/updated the relevant documentation
  • I've run make lint and make format
  • I've made sure tests pass

Add a public FunctionTool.function attribute holding the original Python
callable that @function_tool wrapped (None for tools not backed by a plain
function). Gives code outside the runtime a stable hook to introspect,
directly test, or re-run the underlying function without a ToolContext/JSON
round-trip.

Closes openai#3381
@fede-kamel fede-kamel force-pushed the feat/function-tool-expose-callable branch from dbd627d to a76a6da Compare June 25, 2026 22:02
@seratch seratch added duplicate This issue or pull request already exists feature:core labels Jun 25, 2026
@seratch seratch changed the title Expose the wrapped callable on FunctionTool (closes #3381) feat: expose the wrapped callable on FunctionTool (closes #3381) Jun 25, 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 feature:core

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide stable public access to the underlying function on FunctionTool

2 participants