Skip to content

Conversation

@hinthornw
Copy link
Collaborator

@hinthornw hinthornw commented Nov 17, 2025

Support injection of injected args (like InjectedToolCallId, ToolRuntime) when an args_schema is specified that doesn't contain said args.

This allows for pydantic validation of other args while retaining the ability to inject langchain specific arguments.

fixes #33646
fixes #31688

Taking a deep dive here reminded me that we definitely need to revisit our internal tooling logic, but I don't think we should do that in this PR.

@hinthornw hinthornw requested a review from eyurtsev as a code owner November 17, 2025 23:41
@github-actions github-actions bot added core Related to the package `langchain-core` infra Chores, devops, repo meta changes labels Nov 17, 2025
@codspeed-hq
Copy link

codspeed-hq bot commented Nov 17, 2025

CodSpeed Performance Report

Merging #33999 will improve performances by 23.04%

Comparing wfh/runtime (58f39e0) with master (990e346)

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

Summary

⚡ 5 improvements
✅ 8 untouched
⏩ 21 skipped1

Benchmarks breakdown

Mode Benchmark BASE HEAD Change
WallTime test_async_callbacks_in_sync 24 ms 19.5 ms +23.04%
WallTime test_import_time[BaseChatModel] 527.7 ms 479.4 ms +10.07%
WallTime test_import_time[ChatPromptTemplate] 594 ms 539.4 ms +10.12%
WallTime test_import_time[InMemoryVectorStore] 614.5 ms 556.4 ms +10.44%
WallTime test_import_time[tool] 514 ms 462.3 ms +11.17%

Footnotes

  1. 21 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Collaborator

@sydney-runkle sydney-runkle left a comment

Choose a reason for hiding this comment

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

Have a few questions about impl here, but generally I think this is the right track for a fix (basically, inspect signature, inject anyways).

Happy to pick this up and finish, just wanted to get some clarification first :).

Comment on lines +249 to +259
@functools.cached_property
def _injected_args_keys(self) -> frozenset[str]:
fn = self.func or self.coroutine
if fn is None:
return _EMPTY_SET
return frozenset(
k
for k, v in signature(fn).parameters.items()
if _is_injected_arg_type(v.annotation)
)

Copy link
Collaborator

Choose a reason for hiding this comment

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

it's clear to me that this solves the problem bc we're inspecting the signature

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also I think we build these from the tool decorator so I understand it solves our specific use case 👍

@github-actions github-actions bot added infra Chores, devops, repo meta changes and removed infra Chores, devops, repo meta changes labels Nov 18, 2025
@github-actions github-actions bot added infra Chores, devops, repo meta changes and removed infra Chores, devops, repo meta changes labels Nov 18, 2025
@sydney-runkle sydney-runkle enabled auto-merge (squash) November 18, 2025 17:09
@sydney-runkle sydney-runkle merged commit 32bbe99 into master Nov 18, 2025
91 checks passed
@sydney-runkle sydney-runkle deleted the wfh/runtime branch November 18, 2025 17:10
sydney-runkle added a commit to langchain-ai/langgraph that referenced this pull request Nov 20, 2025
## overview

The main purpose of this is to respect tool signatures that request
injected args (like `ToolRuntime`) even when the explicitly specified
`args_schema` does not.

Ex in the following example, we should still inject `runtime` despite
its absence in `ArgsSchema`

```py
class ArgsSchema(BaseModel):
    some_arg: int = Field(...)

@tool(args_schema=ArgsSchema)
def my_tool(some_arg: int, runtime: ToolRuntime): ...
```

This is accompanied by
langchain-ai/langchain#34051 which has tests
that pass w/ this change. This tests injection w/ `create_agent` (more
end to end than tests added in
langchain-ai/langchain#33999.

This unblocks the injection of `ToolRuntime` into MCP tools which is
exciting bc that exposes tool call id and state, which we previously
were unable to do.

## other benefits

* Cleaner code structure w/ more helpful docs about injected args.
* Nice perf boost, we're no longer inspecting the annotations of a
tool's schema 3 different times to detect store, state, and runtime
injections.

## additional notes

1. I could see a world where we want more of this logic to reside on the
tools themselves, but tools don't now about LG specific injection types
(like `ToolRuntime`, hence having this logic here for now).
2. We could separately add validation for the case where something is
specified in `args_schema` and not in the function signature (probably
at the tool level though).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core Related to the package `langchain-core` infra Chores, devops, repo meta changes

Projects

None yet

4 participants