Tools and bind_tools
A tool is a Python function a model can call. @tool turns a function into one, and model.bind_tools([...]) returns a new model that is allowed to request it.
Last updated: 29 Sep, 2026 · LangChain 1.4
A model on its own can only write text. A tool lets it look something up or take an action. The model does not run the tool; it asks for it, and your program runs it.
A weather tool, bound to a model
The LangChain section of the video turns get_weather into a tool with the @tool decorator from langchain.tools. The docstring, "Get the weather at a location", is what the model reads once the tool is bound, and the return value is hard-coded where a real tool would call an API or a database. model.bind_tools([get_weather]) returns model_with_tools, and asking it "What's the weather like in Boston?" gets back a tool call instead of an answer. The video runs it on groq:qwen/qwen3-32b, since retired, and prints the whole response before the tool calls; this version runs the course model and prints only the tool calls:
from langchain.chat_models import init_chat_model
model = init_chat_model("groq:openai/gpt-oss-120b")
from langchain.tools import tool
@tool
def get_weather(location:str)->str:
"""Get the weather at a location"""
return f"It's sunny in {location}"
model_with_tools=model.bind_tools([get_weather])
response = model_with_tools.invoke("What's the weather like in Boston?")
for tool_call in response.tool_calls:
print(f"Tool: {tool_call['name']}")
print(f"Args: {tool_call['args']}")Tool: get_weather
Args: {'location': 'Boston'}The model picked get_weather and filled in location from the question, but it ran nothing: the reply only names the tool and its arguments. Running it is your code's job, or a graph's, as the ToolNode and tools_condition lesson shows. The shop's tool below looks up an order the same way.
The @tool decorator and bind_tools
from langchain.tools import tool
@tool
def name(arg: str) -> str:
"""What the tool does (the model reads this)."""
return result
model_with_tools = model.bind_tools([name]) # returns a NEW modelTurning a function into a tool
Start by turning a plain function into a tool. The @tool decorator reads the type hints for the input schema and the docstring for the description the model sees.
from langchain.tools import tool
@tool
def lookup_order(order_id: str) -> str:
"""Look up the status of an order by its id.""" # the model reads this line
return f"Order {order_id}: shipped on 3 March."Calling the tool directly
Run the tool yourself with .invoke, passing its arguments as a dict. The model would ask for it, but here you call it directly to see what it returns.
print(lookup_order.invoke({"order_id": "A17"})) # call the tool with its argumentThe tool in a run
The tool and the call together:
from langchain.tools import tool
@tool
def lookup_order(order_id: str) -> str:
"""Look up the status of an order by its id."""
return f"Order {order_id}: shipped on 3 March."
print(lookup_order.invoke({"order_id": "A17"}))Order A17: shipped on 3 March.
Asking a real model for the tool
The same call with the shop's tool. The reply has no text, only the tool call.
from langchain.chat_models import init_chat_model
from langchain.tools import tool
@tool
def lookup_order(order_id: str) -> str:
"""Look up an order by id."""
return f"Order {order_id}: shipped on 3 March."
model = init_chat_model("groq:openai/gpt-oss-120b", temperature=0) # uses your GROQ_API_KEY
model_with_tools = model.bind_tools([lookup_order])
reply = model_with_tools.invoke("Where is order A17?")
print(repr(reply.content))
print(reply.tool_calls[0]["name"], reply.tool_calls[0]["args"])''
lookup_order {'order_id': 'A17'}What @tool adds to a function
- The type hints are required: they define the tool's input schema.
- The docstring becomes the tool's description, which the model reads to decide when to call it.
bind_toolsreturns a NEW model that knows about the tool; the original model is unchanged.
Plain function vs @tool
| Plain function | @tool | |
|---|---|---|
| A model can request it | No | Yes, once bound |
| Has a schema | No | From the type hints |
| Has a description | No | From the docstring |
Where tools fit
- Any action an agent takes: search, look up an order, send an email, run a query.
- You give the model the tools; it chooses which to call and with what arguments.
bind_tools returns a new model, so assign it: model = model.bind_tools([...]). If you keep calling the old model, it will never ask for a tool.Related
- Previous: Chat models
- Next: ToolNode and tools_condition
- Reference: Tools
- Add a second argument to
lookup_orderand call it. - Write a
refundtool and give it a clear docstring.
You understood something today that you didn't yesterday.