Skip to content

Commit 90aefc6

Browse files
authored
docs(core): improve tools module docstrings (#33755)
styling in `base.py`, content updates in `libs/core/langchain_core/tools/convert.py`
1 parent 2ca73c4 commit 90aefc6

File tree

2 files changed

+89
-68
lines changed

2 files changed

+89
-68
lines changed

libs/core/langchain_core/tools/base.py

Lines changed: 52 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ class BaseTool(RunnableSerializable[str | dict | ToolCall, Any]):
391391
"""Base class for all LangChain tools.
392392
393393
This abstract class defines the interface that all LangChain tools must implement.
394+
394395
Tools are components that can be called by agents to perform specific actions.
395396
"""
396397

@@ -401,7 +402,7 @@ def __init_subclass__(cls, **kwargs: Any) -> None:
401402
**kwargs: Additional keyword arguments passed to the parent class.
402403
403404
Raises:
404-
SchemaAnnotationError: If args_schema has incorrect type annotation.
405+
SchemaAnnotationError: If `args_schema` has incorrect type annotation.
405406
"""
406407
super().__init_subclass__(**kwargs)
407408

@@ -442,15 +443,15 @@ class ChildTool(BaseTool):
442443
443444
Args schema should be either:
444445
445-
- A subclass of pydantic.BaseModel.
446-
- A subclass of pydantic.v1.BaseModel if accessing v1 namespace in pydantic 2
447-
- a JSON schema dict
446+
- A subclass of `pydantic.BaseModel`.
447+
- A subclass of `pydantic.v1.BaseModel` if accessing v1 namespace in pydantic 2
448+
- A JSON schema dict
448449
"""
449450
return_direct: bool = False
450451
"""Whether to return the tool's output directly.
451452
452-
Setting this to True means
453-
that after the tool is called, the AgentExecutor will stop looping.
453+
Setting this to `True` means that after the tool is called, the `AgentExecutor` will
454+
stop looping.
454455
"""
455456
verbose: bool = False
456457
"""Whether to log the tool's progress."""
@@ -460,39 +461,45 @@ class ChildTool(BaseTool):
460461

461462
tags: list[str] | None = None
462463
"""Optional list of tags associated with the tool.
464+
463465
These tags will be associated with each call to this tool,
464466
and passed as arguments to the handlers defined in `callbacks`.
465-
You can use these to eg identify a specific instance of a tool with its use case.
467+
468+
You can use these to, e.g., identify a specific instance of a tool with its use
469+
case.
466470
"""
467471
metadata: dict[str, Any] | None = None
468472
"""Optional metadata associated with the tool.
473+
469474
This metadata will be associated with each call to this tool,
470475
and passed as arguments to the handlers defined in `callbacks`.
471-
You can use these to eg identify a specific instance of a tool with its use case.
476+
477+
You can use these to, e.g., identify a specific instance of a tool with its use
478+
case.
472479
"""
473480

474481
handle_tool_error: bool | str | Callable[[ToolException], str] | None = False
475-
"""Handle the content of the ToolException thrown."""
482+
"""Handle the content of the `ToolException` thrown."""
476483

477484
handle_validation_error: (
478485
bool | str | Callable[[ValidationError | ValidationErrorV1], str] | None
479486
) = False
480-
"""Handle the content of the ValidationError thrown."""
487+
"""Handle the content of the `ValidationError` thrown."""
481488

482489
response_format: Literal["content", "content_and_artifact"] = "content"
483490
"""The tool response format.
484491
485-
If `"content"` then the output of the tool is interpreted as the contents of a
486-
`ToolMessage`. If `"content_and_artifact"` then the output is expected to be a
487-
two-tuple corresponding to the (content, artifact) of a `ToolMessage`.
492+
If `'content'` then the output of the tool is interpreted as the contents of a
493+
`ToolMessage`. If `'content_and_artifact'` then the output is expected to be a
494+
two-tuple corresponding to the `(content, artifact)` of a `ToolMessage`.
488495
"""
489496

490497
def __init__(self, **kwargs: Any) -> None:
491498
"""Initialize the tool.
492499
493500
Raises:
494501
TypeError: If `args_schema` is not a subclass of pydantic `BaseModel` or
495-
dict.
502+
`dict`.
496503
"""
497504
if (
498505
"args_schema" in kwargs
@@ -526,7 +533,7 @@ def args(self) -> dict:
526533
"""Get the tool's input arguments schema.
527534
528535
Returns:
529-
Dictionary containing the tool's argument properties.
536+
`dict` containing the tool's argument properties.
530537
"""
531538
if isinstance(self.args_schema, dict):
532539
json_schema = self.args_schema
@@ -616,9 +623,9 @@ def _parse_input(
616623
617624
Raises:
618625
ValueError: If `string` input is provided with JSON schema `args_schema`.
619-
ValueError: If InjectedToolCallId is required but `tool_call_id` is not
626+
ValueError: If `InjectedToolCallId` is required but `tool_call_id` is not
620627
provided.
621-
TypeError: If args_schema is not a Pydantic `BaseModel` or dict.
628+
TypeError: If `args_schema` is not a Pydantic `BaseModel` or dict.
622629
"""
623630
input_args = self.args_schema
624631
if isinstance(tool_input, str):
@@ -710,8 +717,8 @@ async def _arun(self, *args: Any, **kwargs: Any) -> Any:
710717
def _filter_injected_args(self, tool_input: dict) -> dict:
711718
"""Filter out injected tool arguments from the input dictionary.
712719
713-
Injected arguments are those annotated with InjectedToolArg or its
714-
subclasses, or arguments in FILTERED_ARGS like run_manager and callbacks.
720+
Injected arguments are those annotated with `InjectedToolArg` or its
721+
subclasses, or arguments in `FILTERED_ARGS` like `run_manager` and callbacks.
715722
716723
Args:
717724
tool_input: The tool input dictionary to filter.
@@ -746,7 +753,7 @@ def _to_args_and_kwargs(
746753
tool_call_id: The ID of the tool call, if available.
747754
748755
Returns:
749-
A tuple of (positional_args, keyword_args) for the tool.
756+
A tuple of `(positional_args, keyword_args)` for the tool.
750757
751758
Raises:
752759
TypeError: If the tool input type is invalid.
@@ -1048,7 +1055,7 @@ def _handle_validation_error(
10481055
10491056
Args:
10501057
e: The validation error that occurred.
1051-
flag: How to handle the error (bool, string, or callable).
1058+
flag: How to handle the error (`bool`, `str`, or `Callable`).
10521059
10531060
Returns:
10541061
The error message to return.
@@ -1080,7 +1087,7 @@ def _handle_tool_error(
10801087
10811088
Args:
10821089
e: The tool exception that occurred.
1083-
flag: How to handle the error (bool, string, or callable).
1090+
flag: How to handle the error (`bool`, `str`, or `Callable`).
10841091
10851092
Returns:
10861093
The error message to return.
@@ -1111,12 +1118,12 @@ def _prep_run_args(
11111118
"""Prepare arguments for tool execution.
11121119
11131120
Args:
1114-
value: The input value (string, dict, or ToolCall).
1121+
value: The input value (`str`, `dict`, or `ToolCall`).
11151122
config: The runnable configuration.
11161123
**kwargs: Additional keyword arguments.
11171124
11181125
Returns:
1119-
A tuple of (tool_input, run_kwargs).
1126+
A tuple of `(tool_input, run_kwargs)`.
11201127
"""
11211128
config = ensure_config(config)
11221129
if _is_tool_call(value):
@@ -1147,7 +1154,7 @@ def _format_output(
11471154
name: str,
11481155
status: str,
11491156
) -> ToolOutputMixin | Any:
1150-
"""Format tool output as a ToolMessage if appropriate.
1157+
"""Format tool output as a `ToolMessage` if appropriate.
11511158
11521159
Args:
11531160
content: The main content of the tool output.
@@ -1157,7 +1164,7 @@ def _format_output(
11571164
status: The execution status.
11581165
11591166
Returns:
1160-
The formatted output, either as a ToolMessage or the original content.
1167+
The formatted output, either as a `ToolMessage` or the original content.
11611168
"""
11621169
if isinstance(content, ToolOutputMixin) or tool_call_id is None:
11631170
return content
@@ -1228,7 +1235,7 @@ def _get_type_hints(func: Callable) -> dict[str, type] | None:
12281235
func: The function to get type hints from.
12291236
12301237
Returns:
1231-
Dictionary of type hints, or None if extraction fails.
1238+
`dict` of type hints, or `None` if extraction fails.
12321239
"""
12331240
if isinstance(func, functools.partial):
12341241
func = func.func
@@ -1239,13 +1246,13 @@ def _get_type_hints(func: Callable) -> dict[str, type] | None:
12391246

12401247

12411248
def _get_runnable_config_param(func: Callable) -> str | None:
1242-
"""Find the parameter name for RunnableConfig in a function.
1249+
"""Find the parameter name for `RunnableConfig` in a function.
12431250
12441251
Args:
12451252
func: The function to check.
12461253
12471254
Returns:
1248-
The parameter name for RunnableConfig, or None if not found.
1255+
The parameter name for `RunnableConfig`, or `None` if not found.
12491256
"""
12501257
type_hints = _get_type_hints(func)
12511258
if not type_hints:
@@ -1269,9 +1276,11 @@ class _DirectlyInjectedToolArg:
12691276
12701277
Injected via direct type annotation, rather than annotated metadata.
12711278
1272-
For example, ToolRuntime is a directly injected argument.
1279+
For example, `ToolRuntime` is a directly injected argument.
1280+
12731281
Note the direct annotation rather than the verbose alternative:
1274-
Annotated[ToolRuntime, InjectedRuntime]
1282+
`Annotated[ToolRuntime, InjectedRuntime]`
1283+
12751284
```python
12761285
from langchain_core.tools import tool, ToolRuntime
12771286
@@ -1314,11 +1323,11 @@ def foo(
13141323
def _is_directly_injected_arg_type(type_: Any) -> bool:
13151324
"""Check if a type annotation indicates a directly injected argument.
13161325
1317-
This is currently only used for ToolRuntime.
1318-
Checks if either the annotation itself is a subclass of _DirectlyInjectedToolArg
1319-
or the origin of the annotation is a subclass of _DirectlyInjectedToolArg.
1326+
This is currently only used for `ToolRuntime`.
1327+
Checks if either the annotation itself is a subclass of `_DirectlyInjectedToolArg`
1328+
or the origin of the annotation is a subclass of `_DirectlyInjectedToolArg`.
13201329
1321-
Ex: ToolRuntime or ToolRuntime[ContextT, StateT] would both return True.
1330+
Ex: `ToolRuntime` or `ToolRuntime[ContextT, StateT]` would both return `True`.
13221331
"""
13231332
return (
13241333
isinstance(type_, type) and issubclass(type_, _DirectlyInjectedToolArg)
@@ -1360,14 +1369,14 @@ def _is_injected_arg_type(
13601369
def get_all_basemodel_annotations(
13611370
cls: TypeBaseModel | Any, *, default_to_bound: bool = True
13621371
) -> dict[str, type | TypeVar]:
1363-
"""Get all annotations from a Pydantic BaseModel and its parents.
1372+
"""Get all annotations from a Pydantic `BaseModel` and its parents.
13641373
13651374
Args:
1366-
cls: The Pydantic BaseModel class.
1367-
default_to_bound: Whether to default to the bound of a TypeVar if it exists.
1375+
cls: The Pydantic `BaseModel` class.
1376+
default_to_bound: Whether to default to the bound of a `TypeVar` if it exists.
13681377
13691378
Returns:
1370-
A dictionary of field names to their type annotations.
1379+
`dict` of field names to their type annotations.
13711380
"""
13721381
# cls has no subscript: cls = FooBar
13731382
if isinstance(cls, type):
@@ -1433,15 +1442,15 @@ def _replace_type_vars(
14331442
*,
14341443
default_to_bound: bool = True,
14351444
) -> type | TypeVar:
1436-
"""Replace TypeVars in a type annotation with concrete types.
1445+
"""Replace `TypeVar`s in a type annotation with concrete types.
14371446
14381447
Args:
14391448
type_: The type annotation to process.
1440-
generic_map: Mapping of TypeVars to concrete types.
1441-
default_to_bound: Whether to use TypeVar bounds as defaults.
1449+
generic_map: Mapping of `TypeVar`s to concrete types.
1450+
default_to_bound: Whether to use `TypeVar` bounds as defaults.
14421451
14431452
Returns:
1444-
The type with TypeVars replaced.
1453+
The type with `TypeVar`s replaced.
14451454
"""
14461455
generic_map = generic_map or {}
14471456
if isinstance(type_, TypeVar):

libs/core/langchain_core/tools/convert.py

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -81,60 +81,72 @@ def tool(
8181
parse_docstring: bool = False,
8282
error_on_invalid_docstring: bool = True,
8383
) -> BaseTool | Callable[[Callable | Runnable], BaseTool]:
84-
"""Make tools out of Python functions, can be used with or without arguments.
84+
"""Convert Python functions and `Runnables` to LangChain tools.
85+
86+
Can be used as a decorator with or without arguments to create tools from functions.
87+
88+
Functions can have any signature - the tool will automatically infer input schemas
89+
unless disabled.
90+
91+
!!! note "Requirements"
92+
- Functions must have type hints for proper schema inference
93+
- When `infer_schema=False`, functions must be `(str) -> str` and have
94+
docstrings
95+
- When using with `Runnable`, a string name must be provided
8596
8697
Args:
87-
name_or_callable: Optional name of the tool or the callable to be
88-
converted to a tool. Must be provided as a positional argument.
89-
runnable: Optional runnable to convert to a tool. Must be provided as a
90-
positional argument.
98+
name_or_callable: Optional name of the tool or the `Callable` to be
99+
converted to a tool. Overrides the function's name.
100+
101+
Must be provided as a positional argument.
102+
runnable: Optional `Runnable` to convert to a tool.
103+
104+
Must be provided as a positional argument.
91105
description: Optional description for the tool.
92106
93107
Precedence for the tool description value is as follows:
94108
95-
- `description` argument
109+
- This `description` argument
96110
(used even if docstring and/or `args_schema` are provided)
97111
- Tool function docstring
98112
(used even if `args_schema` is provided)
99113
- `args_schema` description
100-
(used only if `description` / docstring are not provided)
114+
(used only if `description` and docstring are not provided)
101115
*args: Extra positional arguments. Must be empty.
102-
return_direct: Whether to return directly from the tool rather
103-
than continuing the agent loop.
116+
return_direct: Whether to return directly from the tool rather than continuing
117+
the agent loop.
104118
args_schema: Optional argument schema for user to specify.
105-
106-
infer_schema: Whether to infer the schema of the arguments from
107-
the function's signature. This also makes the resultant tool
108-
accept a dictionary input to its `run()` function.
119+
infer_schema: Whether to infer the schema of the arguments from the function's
120+
signature. This also makes the resultant tool accept a dictionary input to
121+
its `run()` function.
109122
response_format: The tool response format.
110123
111-
If `"content"` then the output of the tool is interpreted as the contents of
112-
a `ToolMessage`. If `"content_and_artifact"` then the output is expected to
113-
be a two-tuple corresponding to the `(content, artifact)` of a
114-
`ToolMessage`.
124+
If `'content'`, then the output of the tool is interpreted as the contents
125+
of a `ToolMessage`.
126+
127+
If `'content_and_artifact'`, then the output is expected to be a two-tuple
128+
corresponding to the `(content, artifact)` of a `ToolMessage`.
115129
parse_docstring: If `infer_schema` and `parse_docstring`, will attempt to
116130
parse parameter descriptions from Google Style function docstrings.
117-
error_on_invalid_docstring: if `parse_docstring` is provided, configure
131+
error_on_invalid_docstring: If `parse_docstring` is provided, configure
118132
whether to raise `ValueError` on invalid Google Style docstrings.
119133
120134
Raises:
121-
ValueError: If too many positional arguments are provided.
122-
ValueError: If a runnable is provided without a string name.
135+
ValueError: If too many positional arguments are provided (e.g. violating the
136+
`*args` constraint).
137+
ValueError: If a `Runnable` is provided without a string name. When using `tool`
138+
with a `Runnable`, a `str` name must be provided as the `name_or_callable`.
123139
ValueError: If the first argument is not a string or callable with
124140
a `__name__` attribute.
125141
ValueError: If the function does not have a docstring and description
126142
is not provided and `infer_schema` is `False`.
127143
ValueError: If `parse_docstring` is `True` and the function has an invalid
128144
Google-style docstring and `error_on_invalid_docstring` is True.
129-
ValueError: If a Runnable is provided that does not have an object schema.
145+
ValueError: If a `Runnable` is provided that does not have an object schema.
130146
131147
Returns:
132148
The tool.
133149
134-
Requires:
135-
- Function must be of type `(str) -> str`
136-
- Function must have a docstring
137-
138150
Examples:
139151
```python
140152
@tool

0 commit comments

Comments
 (0)