@@ -1210,6 +1210,26 @@ class InjectedToolArg:
12101210 """
12111211
12121212
1213+ class _DirectlyInjectedToolArg :
1214+ """Annotation for tool arguments that are injected at runtime.
1215+
1216+ Injected via direct type annotation, rather than annotated metadata.
1217+
1218+ For example, ToolRuntime is a directly injected argument.
1219+ Note the direct annotation rather than the verbose alternative:
1220+ Annotated[ToolRuntime, InjectedRuntime]
1221+ ```python
1222+ from langchain_core.tools import tool, ToolRuntime
1223+
1224+
1225+ @tool
1226+ def foo(x: int, runtime: ToolRuntime) -> str:
1227+ # use runtime.state, runtime.context, runtime.store, etc.
1228+ ...
1229+ ```
1230+ """
1231+
1232+
12131233class InjectedToolCallId (InjectedToolArg ):
12141234 """Annotation for injecting the tool call ID.
12151235
@@ -1237,6 +1257,24 @@ def foo(
12371257 """
12381258
12391259
1260+ def _is_directly_injected_arg_type (type_ : Any ) -> bool :
1261+ """Check if a type annotation indicates a directly injected argument.
1262+
1263+ This is currently only used for ToolRuntime.
1264+ Checks if either the annotation itself is a subclass of _DirectlyInjectedToolArg
1265+ or the origin of the annotation is a subclass of _DirectlyInjectedToolArg.
1266+
1267+ Ex: ToolRuntime or ToolRuntime[ContextT, StateT] would both return True.
1268+ """
1269+ return (
1270+ isinstance (type_ , type ) and issubclass (type_ , _DirectlyInjectedToolArg )
1271+ ) or (
1272+ (origin := get_origin (type_ )) is not None
1273+ and isinstance (origin , type )
1274+ and issubclass (origin , _DirectlyInjectedToolArg )
1275+ )
1276+
1277+
12401278def _is_injected_arg_type (
12411279 type_ : type | TypeVar , injected_type : type [InjectedToolArg ] | None = None
12421280) -> bool :
@@ -1249,7 +1287,15 @@ def _is_injected_arg_type(
12491287 Returns:
12501288 `True` if the type is an injected argument, `False` otherwise.
12511289 """
1252- injected_type = injected_type or InjectedToolArg
1290+ if injected_type is None :
1291+ # if no injected type is specified,
1292+ # check if the type is a directly injected argument
1293+ if _is_directly_injected_arg_type (type_ ):
1294+ return True
1295+ injected_type = InjectedToolArg
1296+
1297+ # if the type is an Annotated type, check if annotated metadata
1298+ # is an intance or subclass of the injected type
12531299 return any (
12541300 isinstance (arg , injected_type )
12551301 or (isinstance (arg , type ) and issubclass (arg , injected_type ))
0 commit comments