Skip to content

fix: forward callbacks/config through static-args tool wrapper#922

Open
edis-uipath wants to merge 1 commit into
wrap-tools-in-static-argsfrom
static-args-forward-config-callbacks
Open

fix: forward callbacks/config through static-args tool wrapper#922
edis-uipath wants to merge 1 commit into
wrap-tools-in-static-argsfrom
static-args-forward-config-callbacks

Conversation

@edis-uipath

Copy link
Copy Markdown
Contributor

Stacked on top of #921. Base branch is wrap-tools-in-static-args, so this diff shows only the hardening. Review/merge #921 first.

What

Addresses the Copilot review comment on #921 (discussion).

wrap_tool_with_static_args replaces a tool's coroutine/func with a **kwargs-only callable. StructuredTool._arun/_run (and BaseUiPathStructuredTool's override) decide whether to forward the child callbacks and the runnable config into the callable by inspecting its signature (signature(self.coroutine).parameters.get("callbacks") and _get_runnable_config_param(...)). A **kwargs-only wrapper hides those, so a wrapped tool that declares config/callbacks would stop receiving them.

Fix

  • @functools.wraps(_coroutine) / @functools.wraps(_func) so inspect.signature sees through to the original callable — restoring LangChain's detection.
  • New _runtime_passthrough_keys helper computes which keys LangChain injects (callbacks + the RunnableConfig-typed param) from the original signature.
  • Those injected runtime kwargs are forwarded as-is, bypassing apply_static_args — whose sanitize_dict_for_serialization would otherwise mangle a live callback-manager / config object. Static-arg injection still applies only to the model-supplied args.

Impact / scope

No behavior change for any current tool: every wrapped coroutine today is **kwargs-only (integration / process / escalation / extraction / MCP / A2A) or reads config from the var_child_runnable_config contextvar (analyze_files), so _runtime_passthrough_keys is empty and the path is identical to before. This is forward-looking hardening so a future wrapped coroutine that declares config/callbacks keeps working.

Tests

New test_wrapper_forwards_config_and_callbacks_to_coroutine: a coroutine declaring config: RunnableConfig + callbacks, invoked via ainvoke, asserts the static value is injected and both config and callbacks arrive. (It errors without the functools.wraps fix, so it's a real guard.)

Verification: ruff check/format clean, mypy clean, pytest tests/agent/tools/637 passed.

🤖 Generated with Claude Code

The static-args wrapper replaced a tool's coroutine/func with a
**kwargs-only callable, which hid the original signature from
StructuredTool._arun/_run. Those methods inspect the callable signature
to decide whether to forward the child `callbacks` and the runnable
`config`, so a wrapped tool that declares either stopped receiving them.

Use functools.wraps so inspect.signature sees through to the original
callable (restoring detection), and forward the injected callbacks/config
as-is, bypassing apply_static_args whose serialization sanitization would
mangle the callback manager / config objects. Static-arg injection still
applies only to the model-supplied args.

Adds a test invoking a config/callbacks-declaring coroutine through
ainvoke and asserting both arrive alongside the injected static value.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 23, 2026 08:42

Copilot AI 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.

Pull request overview

This PR hardens the static-args tool wrapper so LangChain can still detect and forward runtime-injected kwargs (callbacks and the RunnableConfig-typed param) after wrapping a tool’s coroutine/func.

Changes:

  • Add functools.wraps around the wrapper callables so inspect.signature remains transparent to LangChain.
  • Introduce _runtime_passthrough_keys() and ensure runtime-injected kwargs bypass apply_static_args.
  • Add a regression test asserting config/callbacks reach a wrapped coroutine that explicitly declares them.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/uipath_langchain/agent/tools/static_args.py Preserve callable signatures via wraps and forward runtime-injected kwargs outside static-arg merging.
tests/agent/tools/test_wrap_static_args.py Add coverage ensuring wrapped tools still receive RunnableConfig and callbacks.

Comment on lines +361 to +367
keys: set[str] = set()
if "callbacks" in signature(target).parameters:
keys.add("callbacks")
config_param = _get_runnable_config_param(target)
if config_param:
keys.add(config_param)
return keys
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.

2 participants