Skip to main content

Tool Calling

Key idea

The model never executes anything. It only requests a call — your code decides whether to honour it, runs it, and reports the result back.

A chat model gains access to tools by binding them, then the round trip runs in your code, not inside the model:

from langchain.chat_models import init_chat_model

def get_weather(location: str) -> str:
"""Get the weather at a location."""
return f"It's sunny in {location}."

model = init_chat_model("claude-sonnet-4-6", model_provider="anthropic")
model_with_tools = model.bind_tools([get_weather])

messages = [{"role": "user", "content": "What's the weather in Lisbon?"}]
ai_msg = model_with_tools.invoke(messages)
messages.append(ai_msg)

for tool_call in ai_msg.tool_calls:
tool_result = get_weather.invoke(tool_call)
messages.append(tool_result)

final_response = model_with_tools.invoke(messages)
print(final_response.text)

The AIMessage returned by the first invoke carries tool_calls instead of (or alongside) text — each entry has a name, args, and id. Your code executes the matching tool and appends a ToolMessage keyed to that id. The second invoke gives the model the result so it can produce a final answer.

StepWho actsWhat happens
1modelemits tool_calls on an AIMessage instead of answering directly
2your codematches each call to a tool, executes it
3your codeappends a ToolMessage per call, tool_call_id matching
4modelreads the ToolMessages, produces the final response

This manual loop is what create_agent automates: bind, call, execute, append, repeat until the model stops requesting tools. See Agent Concepts for when that automation is worth reaching for.

See also

  • Messages — the AIMessage/ToolMessage shapes this loop depends on.
  • Custom Tools — writing the tools that get bound.
  • Agent Concepts — automating this loop instead of hand-rolling it.