Skip to content

fix: use functools.wraps in activity_tool to preserve __annotations__ and __module__#1636

Merged
brianstrauch merged 2 commits into
temporalio:mainfrom
brucearctor:fix/activity-tool-functools-wraps
Jul 10, 2026
Merged

fix: use functools.wraps in activity_tool to preserve __annotations__ and __module__#1636
brianstrauch merged 2 commits into
temporalio:mainfrom
brucearctor:fix/activity-tool-functools-wraps

Conversation

@brucearctor

Copy link
Copy Markdown
Contributor

Summary

Replace manual metadata copying in activity_tool() with @functools.wraps(activity_def) to fix missing __annotations__ and __module__ on the wrapper function.

Problem

The activity_tool() wrapper copies __name__, __doc__, and __signature__ but misses __annotations__ and __module__. ADK's build_function_declaration()_handle_params_as_deferred_annotations() reads the wrapper's __annotations__ to resolve parameter types, but finds {'args': Any, 'kw': Any} instead of the original function's typed parameters, causing a KeyError.

Fix

+import functools

 def activity_tool(activity_def, **kwargs):
+    @functools.wraps(activity_def)
     async def wrapper(*args, **kw):
         ...

-    wrapper.__name__ = activity_def.__name__
-    wrapper.__doc__ = activity_def.__doc__
-    setattr(wrapper, "__signature__", inspect.signature(activity_def))
+    wrapper.__signature__ = inspect.signature(activity_def)
     return wrapper

functools.wraps copies __name__, __qualname__, __module__, __annotations__, __doc__, __dict__, and sets __wrapped__. The explicit __signature__ override remains because the wrapper uses *args/**kw.

Testing

Verified locally: wrapping a typed activity with activity_tool() and using it as a LlmAgent tool now produces correct function declarations without KeyError.

Fixes #1635

@brucearctor brucearctor requested review from a team as code owners July 9, 2026 03:37
@brianstrauch

Copy link
Copy Markdown
Member

Thanks for the PR, happy to merge it in! Can you fix the lint and add a test?

@brucearctor

Copy link
Copy Markdown
Contributor Author

Thanks for the PR, happy to merge it in! Can you fix the lint and add a test?

On it.

ALso -- it'd be great if we can get some sort of default linter in some sort of precommit hook [ i tend to like lefthook ] at least to be able to easily opt into. Otherwise, I imagine this will continue to happen [ I forget things, but not if the machines make sure I do ].

I tend to make those things rather automatic for people. But, at least if there is an easy and persistent opt-in/enablement, that'd also be sufficient.

@brucearctor brucearctor force-pushed the fix/activity-tool-functools-wraps branch from 5153958 to 982c26b Compare July 9, 2026 19:28
@brucearctor

Copy link
Copy Markdown
Contributor Author

Thanks @brianstrauch! Done — force-pushed with both fixes:

  1. Lint: Fixed pyright error on wrapper.__signature__ — switched back to setattr() (matching the original pattern) since pyright cant resolve attributes on functools.wraps return types.

  2. Test: Added test_activity_tool_preserves_metadata that verifies all the critical metadata attributes:

    • __name__, __doc__ (previously covered by manual copy)
    • __annotations__ (was missing — the bug)
    • __module__ (was missing — the bug)
    • __signature__ (parameters, types, defaults)

@brianstrauch

Copy link
Copy Markdown
Member

Looks like changes to temporalio/bridge/sdk-core got added to this PR. Once you reset that we should be ok.

@brucearctor brucearctor force-pushed the fix/activity-tool-functools-wraps branch from 982c26b to 0f9ec2c Compare July 9, 2026 21:37
@brucearctor

Copy link
Copy Markdown
Contributor Author

Fixed — force-pushed with the temporalio/bridge/sdk-core submodule reset. The PR now only touches the two intended files:

  • temporalio/contrib/google_adk_agents/workflow.py
  • tests/contrib/google_adk_agents/test_google_adk_agents.py

Replace manual metadata copying with @functools.wraps(activity_def) to
preserve __annotations__, __module__, __qualname__, and __dict__ on the
wrapper function. These are needed by ADK's tool schema generation
(specifically _handle_params_as_deferred_annotations) to resolve type
hints from the original activity function.

Also adds test_activity_tool_preserves_metadata verifying that
__name__, __doc__, __annotations__, __module__, and __signature__
are all correctly preserved on the wrapper.

Fixes temporalio#1635
@brucearctor brucearctor force-pushed the fix/activity-tool-functools-wraps branch from 6b8abb0 to ce7e9b2 Compare July 9, 2026 22:15

@brianstrauch brianstrauch left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you!

@brianstrauch brianstrauch merged commit aa26c8d into temporalio:main Jul 10, 2026
26 of 27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

activity_tool() wrapper breaks ADK tool declarations — missing __annotations__ and __module__

2 participants