Session 6· 06· 15 min

Tool Execution Loop

What you'll learn
  • Build the full cycle: invoke → detect tool_calls → execute → return result → invoke again
  • Compare this to the raw loop from Session 5 lesson 14
  • See how LangChain cleans up the result injection

Same tool loop as Session 5 lesson 14 — but with LangChain's message classes. The model returns tool_calls, you execute them locally, wrap each result in a ToolMessage, append to history, and invoke again. LangChain handles all the serialisation for you.

scripts/06_tool_execution_loop.py
from langchain_core.messages import HumanMessage, ToolMessage    ①

messages = [HumanMessage(content="Weather in Paris?")]

while True:
    response = model_with_tools.invoke(messages)
    messages.append(response)                                    ②

    if not response.tool_calls:                                   ③
        print(response.content); break

    for call in response.tool_calls:                              ④
        fn = tool_map[call["name"]]
        result = fn.invoke(call["args"])                          ⑤
        messages.append(ToolMessage(
            content=str(result),
            tool_call_id=call["id"],                              ⑥
        ))
ToolMessage is the LangChain class for tool results — same role as the "tool" message in Session 5.
Append the assistant response (which carries tool_calls) to history before the tool results.
Exit the loop when the model stops requesting tools.
Iterate every tool_call — parallel support is free.
LangChain tools expose .invoke(args) — you do not need to unpack the dict yourself.
tool_call_id links the result back to the specific request. Same pattern as Session 5 lesson 13.
$ python scripts/06_tool_execution_loop.py
Always cap iterations
Same rule as Session 5 lesson 14. A bug in your tool could make the model keep retrying forever. In production, use "for _ in range(MAX_ITERS)" instead of while True.
Code Check
What message class do you use to return tool results in LangChain?
Recap — what you just learned
  • Tool loop is the same 3-step dance as Session 5 — invoke → execute → return → invoke
  • Return results as ToolMessage(content, tool_call_id)
  • LangChain tools expose .invoke(args) so you skip manual unpacking
  • Cap iterations in production
Next up: 07 — Parallel Tool Calls