In LangChain, tools are bound to model instances using the bind_tools() method, which attaches tool definitions to the model, enabling it to intelligently decide when to invoke external functions during a conversation.
In LangChain, the primary way to equip a model with the ability to use external tools is through the bind_tools() method. This method attaches a set of tool definitions to a model instance, creating a new runnable that includes the tool configuration in all subsequent invocations[citation:3]. The model is then able to decide, based on a user's query, whether to call one of these tools and, if so, with what arguments. Once the model indicates it wants to use a tool, the tool's function is executed, and its output is passed back to the model to generate a final, informed answer[citation:7][citation:8].
name: A unique, descriptive identifier for the tool.
description: A clear explanation of what the tool does, which helps the model decide when to use it.
schema: A definition of the input parameters the tool expects, often defined using Zod or Pydantic. Tools can be defined using the @tool decorator or by creating a class that inherits from BaseTool[citation:3][citation:4].
func: The actual function that will be executed when the tool is called.
tools: The array of tool objects to be bound to the model[citation:1][citation:5].
tool_choice: (Optional) Controls how the model selects tools. Can be 'auto' (default), 'any' (forces a tool call), 'none' (disables tool use), or the name of a specific tool[citation:1][citation:5][citation:10].
parallel_tool_calls: (Optional) When set to false, disables the model from calling multiple tools in a single response[citation:1].
strict: (Optional) For some providers, like Anthropic, this enforces strict schema adherence for tool calls[citation:1].
The tool_calls property contains an array of the tools the model decided to use, including the extracted arguments based on the user's query.
If the finish_reason in the response metadata is 'tool_calls', it means the model is requesting a tool to be executed[citation:7].
This output shows that the model recognized two distinct tasks within the query and, thanks to bind_tools, it was able to structure the requests for each one appropriately. The args are generated by the model based on the schema defined for the tool[citation:1][citation:3].
ToolMessage: A special message type that contains the output of the tool. Its tool_call_id must match the id of the corresponding tool call in the AIMessage.
ToolMessage needs a name (the tool name) and content (the result of the function call).
ToolMessage allows the model to understand the outcome of its request and use it to formulate a final, coherent response to the user[citation:7].
The model then uses the history containing the tool results to generate the final, natural-language response for the user[citation:7].
The tool_choice parameter provides fine-grained control over tool usage. In the bind_tools() method, you can pass the tool_choice argument to specify this behavior[citation:1][citation:10].
"auto" (Default): The model decides whether to use any tool based on the user's prompt. This is the most flexible option."any" or "required": Forces the model to call at least one tool. The model must choose one of the bound tools and cannot respond with plain text[citation:1][citation:5][citation:10]."none": Prevents the model from using any tools, forcing it to generate a regular text response."calculator"): Forces the model to use the specified tool[citation:1][citation:5][citation:10].Additionally, parallel_tool_calls can be set to false to force the model to generate only one tool call at a time, which can be useful for sequential tasks where order of operations matters[citation:1].
Structured Output: A closely related pattern to tool calling is using with_structured_output(), which can be more stable for forcing the model to produce a specific JSON schema, as opposed to a function call[citation:9].
Third-Party Tool Calling: For production scenarios, as highlighted in recent articles, integrating with services like Auth0's Token Vault allows you to offload the complexity and security of obtaining and refreshing API tokens for third-party tools, ensuring that the LLM never directly handles sensitive credentials[citation:8].
Handling Tool Errors: Always wrap your tool's function logic in try-catch blocks and return meaningful error messages back to the model. This allows the model to inform the user of the issue or attempt to correct its input.